diff options
author | Michelle McDaniel <adiaaida@gmail.com> | 2016-10-07 08:32:17 -0700 |
---|---|---|
committer | Michelle McDaniel <adiaaida@gmail.com> | 2016-10-10 15:36:15 -0700 |
commit | 12c70e569d9c20fba1c7441dc0591db40b3fcda1 (patch) | |
tree | ee47d355b1f78e8dd7a9b2ef2701cad27766f235 /src | |
parent | c6eff2e7f2c8e596617ab7dcac1f44f625f1dece (diff) | |
download | coreclr-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.h | 4 | ||||
-rw-r--r-- | src/jit/lowerxarch.cpp | 81 |
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 |