[JIT] ARM64 vector right-shift must dead-code eliminate if the constant is zero....
authorWill Smith <lol.tihan@gmail.com>
Wed, 9 Aug 2023 18:50:13 +0000 (11:50 -0700)
committerGitHub <noreply@github.com>
Wed, 9 Aug 2023 18:50:13 +0000 (11:50 -0700)
* ARM64 vector right-shift must dead-code eliminate if the constant is zero

* Update emitarm64.cpp

* Use proper size

* Formatting

* Formatting

* Fixing test

* Add comment

* Add comment

src/coreclr/jit/emitarm64.cpp
src/coreclr/jit/hwintrinsiccodegenarm64.cpp

index 1c38058..b4e8132 100644 (file)
@@ -5162,6 +5162,9 @@ void emitter::emitIns_R_R_I(
             assert(isVectorRegister(reg2));
             isRightShift = emitInsIsVectorRightShift(ins);
 
+            assert(!isRightShift ||
+                   (imm != 0 && "instructions for vector right-shift do not allow zero as an immediate value"));
+
             if (insOptsAnyArrangement(opt))
             {
                 // Vector operation
index 05ccf66..d3ba9ae 100644 (file)
@@ -335,29 +335,35 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node)
         {
             assert(hasImmediateOperand);
 
-            if (isRMW)
-            {
-                GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
-
-                HWIntrinsicImmOpHelper helper(this, intrin.op3, node);
+            auto emitShift = [&](GenTree* op, regNumber reg) {
+                HWIntrinsicImmOpHelper helper(this, op, node);
 
                 for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd())
                 {
                     const int shiftAmount = helper.ImmValue();
 
-                    GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op2Reg, shiftAmount, opt);
+                    if (shiftAmount == 0)
+                    {
+                        // TODO: Use emitIns_Mov instead.
+                        //       We do not use it currently because it will still elide the 'mov'
+                        //       even if 'canSkip' is false. We cannot elide the 'mov' here.
+                        GetEmitter()->emitIns_R_R_R(INS_mov, emitTypeSize(node), targetReg, reg, reg);
+                    }
+                    else
+                    {
+                        GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, reg, shiftAmount, opt);
+                    }
                 }
+            };
+
+            if (isRMW)
+            {
+                GetEmitter()->emitIns_Mov(INS_mov, emitTypeSize(node), targetReg, op1Reg, /* canSkip */ true);
+                emitShift(intrin.op3, op2Reg);
             }
             else
             {
-                HWIntrinsicImmOpHelper helper(this, intrin.op2, node);
-
-                for (helper.EmitBegin(); !helper.Done(); helper.EmitCaseEnd())
-                {
-                    const int shiftAmount = helper.ImmValue();
-
-                    GetEmitter()->emitIns_R_R_I(ins, emitSize, targetReg, op1Reg, shiftAmount, opt);
-                }
+                emitShift(intrin.op2, op1Reg);
             }
         }
         else