diff options
author | Tanner Gooding <tagoo@outlook.com> | 2018-03-08 14:08:37 -0800 |
---|---|---|
committer | Tanner Gooding <tagoo@outlook.com> | 2018-03-09 16:34:08 -0800 |
commit | 34e3ef76afe783326f4232e317bc5561285f7696 (patch) | |
tree | 32c58d88bd34f3fe5e11f84f034e961faf888200 /src/jit/hwintrinsiccodegenxarch.cpp | |
parent | c128ba146c3190ac907aa4ee5d4067cb6ceb0742 (diff) | |
download | coreclr-34e3ef76afe783326f4232e317bc5561285f7696.tar.gz coreclr-34e3ef76afe783326f4232e317bc5561285f7696.tar.bz2 coreclr-34e3ef76afe783326f4232e317bc5561285f7696.zip |
Updating the hwintrinsic codegen to handle the case where `op2Reg == targetReg`
Diffstat (limited to 'src/jit/hwintrinsiccodegenxarch.cpp')
-rw-r--r-- | src/jit/hwintrinsiccodegenxarch.cpp | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/src/jit/hwintrinsiccodegenxarch.cpp b/src/jit/hwintrinsiccodegenxarch.cpp index e9264651cb..ea95eca76d 100644 --- a/src/jit/hwintrinsiccodegenxarch.cpp +++ b/src/jit/hwintrinsiccodegenxarch.cpp @@ -81,6 +81,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) switch (numArgs) { case 1: + { genConsumeOperands(node); op1Reg = op1->gtRegNum; if (category == HW_Category_MemoryLoad) @@ -100,11 +101,29 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) emit->emitIns_R_R(ins, simdSize, targetReg, op1Reg); } break; + } case 2: + { genConsumeOperands(node); + op1Reg = op1->gtRegNum; op2Reg = op2->gtRegNum; + + if ((op1Reg != targetReg) && (op2Reg == targetReg) && node->isRMWHWIntrinsic(compiler)) + { + // We have "reg2 = reg1 op reg2" where "reg1 != reg2" on a RMW intrinsic. + // + // For non-commutative intrinsics, we should have ensured that op2 was marked + // delay free in order to prevent it from getting assigned the same register + // as target. However, for commutative intrinsics, we can just swap the operands + // in order to have "reg2 = reg2 op reg1" which will end up producing the right code. + + noway_assert(node->OperIsCommutative()); + op2Reg = op1Reg; + op1Reg = targetReg; + } + if (category == HW_Category_MemoryStore) { emit->emitIns_AR_R(ins, simdSize, op2Reg, op1Reg, 0); @@ -148,6 +167,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) genHWIntrinsic_R_R_RM(node, ins); } break; + } + case 3: { assert(op1->OperIsList()); @@ -382,7 +403,23 @@ void CodeGen::genHWIntrinsic_R_R_RM(GenTreeHWIntrinsic* node, instruction ins) } else { - emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op2->gtRegNum); + regNumber op2Reg = op2->gtRegNum; + + if ((op1Reg != targetReg) && (op2Reg == targetReg) && node->isRMWHWIntrinsic(compiler)) + { + // We have "reg2 = reg1 op reg2" where "reg1 != reg2" on a RMW intrinsic. + // + // For non-commutative intrinsics, we should have ensured that op2 was marked + // delay free in order to prevent it from getting assigned the same register + // as target. However, for commutative intrinsics, we can just swap the operands + // in order to have "reg2 = reg2 op reg1" which will end up producing the right code. + + noway_assert(node->OperIsCommutative()); + op2Reg = op1Reg; + op1Reg = targetReg; + } + + emit->emitIns_SIMD_R_R_R(ins, simdSize, targetReg, op1Reg, op2Reg); } } @@ -507,7 +544,23 @@ void CodeGen::genHWIntrinsic_R_R_RM_I(GenTreeHWIntrinsic* node, instruction ins) } else { - emit->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op2->gtRegNum, ival); + regNumber op2Reg = op2->gtRegNum; + + if ((op1Reg != targetReg) && (op2Reg == targetReg) && node->isRMWHWIntrinsic(compiler)) + { + // We have "reg2 = reg1 op reg2" where "reg1 != reg2" on a RMW intrinsic. + // + // For non-commutative intrinsics, we should have ensured that op2 was marked + // delay free in order to prevent it from getting assigned the same register + // as target. However, for commutative intrinsics, we can just swap the operands + // in order to have "reg2 = reg2 op reg1" which will end up producing the right code. + + noway_assert(node->OperIsCommutative()); + op2Reg = op1Reg; + op1Reg = targetReg; + } + + emit->emitIns_SIMD_R_R_R_I(ins, simdSize, targetReg, op1Reg, op2Reg, ival); } } @@ -1181,6 +1234,7 @@ void CodeGen::genSSE42Intrinsic(GenTreeHWIntrinsic* node) case NI_SSE42_Crc32: if (op1Reg != targetReg) { + assert(op2Reg != targetReg); inst_RV_RV(INS_mov, targetReg, op1Reg, targetType, emitTypeSize(targetType)); } |