summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichelle McDaniel <adiaaida@gmail.com>2016-10-07 08:32:17 -0700
committerMichelle McDaniel <adiaaida@gmail.com>2016-10-10 15:36:15 -0700
commit12c70e569d9c20fba1c7441dc0591db40b3fcda1 (patch)
treeee47d355b1f78e8dd7a9b2ef2701cad27766f235 /src
parentc6eff2e7f2c8e596617ab7dcac1f44f625f1dece (diff)
downloadcoreclr-12c70e569d9c20fba1c7441dc0591db40b3fcda1.tar.gz
coreclr-12c70e569d9c20fba1c7441dc0591db40b3fcda1.tar.bz2
coreclr-12c70e569d9c20fba1c7441dc0591db40b3fcda1.zip
Force byteable register for CMP if op2 is CNS_INT
On x86 we need to force byteable registers for compares not only when both ops are typ_byte, but also when the first is of typ_byte and the second is a constant int. The original condition for cmp only considered the first case. This change adds the second condition.
Diffstat (limited to 'src')
-rw-r--r--src/jit/lower.h4
-rw-r--r--src/jit/lowerxarch.cpp81
2 files changed, 71 insertions, 14 deletions
diff --git a/src/jit/lower.h b/src/jit/lower.h
index a4b9860ca6..41d8869432 100644
--- a/src/jit/lower.h
+++ b/src/jit/lower.h
@@ -128,6 +128,10 @@ private:
// return true if this call target is within range of a pc-rel call on the machine
bool IsCallTargetInRange(void* addr);
+#ifdef _TARGET_X86_
+ bool ExcludeNonByteableRegisters(GenTree* tree);
+#endif
+
void TreeNodeInfoInit(GenTree* stmt);
#if defined(_TARGET_XARCH_)
diff --git a/src/jit/lowerxarch.cpp b/src/jit/lowerxarch.cpp
index f951c547e2..7e0f72c017 100644
--- a/src/jit/lowerxarch.cpp
+++ b/src/jit/lowerxarch.cpp
@@ -909,23 +909,11 @@ void Lowering::TreeNodeInfoInit(GenTree* tree)
// Exclude RBM_NON_BYTE_REGS from dst candidates of tree node and src candidates of operands
// if the tree node is a byte type.
//
- // Example1: GT_STOREIND(byte, addr, op2) - storeind of byte sized value from op2 into mem 'addr'
- // Storeind itself will not produce any value and hence dstCount=0. But op2 could be TYP_INT
- // value. In this case we need to exclude esi/edi from the src candidates of op2.
- //
- // Example2: GT_CAST(int <- bool <- int) - here type of GT_CAST node is int and castToType is bool.
- //
- // Example3: GT_EQ(int, op1 of type ubyte, op2 of type ubyte) - in this case codegen uses
- // ubyte as the result of comparison and if the result needs to be materialized into a reg
- // simply zero extend it to TYP_INT size. Here is an example of generated code:
- // cmp dl, byte ptr[addr mode]
- // movzx edx, dl
- //
// Though this looks conservative in theory, in practice we could not think of a case where
// the below logic leads to conservative register specification. In future when or if we find
// one such case, this logic needs to be fine tuned for that case(s).
- if (varTypeIsByte(tree) || ((tree->OperGet() == GT_CAST) && varTypeIsByte(tree->CastToType())) ||
- (tree->OperIsCompare() && varTypeIsByte(tree->gtGetOp1()) && varTypeIsByte(tree->gtGetOp2())))
+
+ if (ExcludeNonByteableRegisters(tree))
{
regMaskTP regMask;
if (info->dstCount > 0)
@@ -4451,6 +4439,71 @@ GenTree* Lowering::PreferredRegOptionalOperand(GenTree* tree)
return preferredOp;
}
+#ifdef _TARGET_X86_
+//------------------------------------------------------------------------
+// ExcludeNonByteableRegisters: Determines if we need to exclude non-byteable registers for
+// various reasons
+//
+// Arguments:
+// tree - The node of interest
+//
+// Return Value:
+// If we need to exclude non-byteable registers
+//
+bool Lowering::ExcludeNonByteableRegisters(GenTree* tree)
+{
+ // Example1: GT_STOREIND(byte, addr, op2) - storeind of byte sized value from op2 into mem 'addr'
+ // Storeind itself will not produce any value and hence dstCount=0. But op2 could be TYP_INT
+ // value. In this case we need to exclude esi/edi from the src candidates of op2.
+ if (varTypeIsByte(tree))
+ {
+ return true;
+ }
+ // Example2: GT_CAST(int <- bool <- int) - here type of GT_CAST node is int and castToType is bool.
+ else if ((tree->OperGet() == GT_CAST) && varTypeIsByte(tree->CastToType()))
+ {
+ return true;
+ }
+ else if (tree->OperIsCompare())
+ {
+ GenTree* op1 = tree->gtGetOp1();
+ GenTree* op2 = tree->gtGetOp2();
+
+ // Example3: GT_EQ(int, op1 of type ubyte, op2 of type ubyte) - in this case codegen uses
+ // ubyte as the result of comparison and if the result needs to be materialized into a reg
+ // simply zero extend it to TYP_INT size. Here is an example of generated code:
+ // cmp dl, byte ptr[addr mode]
+ // movzx edx, dl
+ if (varTypeIsByte(op1) && varTypeIsByte(op2))
+ {
+ return true;
+ }
+ // Example4: GT_EQ(int, op1 of type ubyte, op2 is GT_CNS_INT) - in this case codegen uses
+ // ubyte as the result of the comparison and if the result needs to be materialized into a reg
+ // simply zero extend it to TYP_INT size.
+ else if (varTypeIsByte(op1) && op2->IsCnsIntOrI())
+ {
+ return true;
+ }
+ // Example4: GT_EQ(int, op1 is GT_CNS_INT, op2 of type ubyte) - in this case codegen uses
+ // ubyte as the result of the comparison and if the result needs to be materialized into a reg
+ // simply zero extend it to TYP_INT size.
+ else if (op1->IsCnsIntOrI() && varTypeIsByte(op2))
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
+}
+#endif
+
#endif // _TARGET_XARCH_
#endif // !LEGACY_BACKEND