[llvm] [RISCV] Lower SELECT's with one constant more efficiently using Zicond (PR #143581)

Ryan Buchner via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 11 11:04:07 PDT 2025


================
@@ -9073,19 +9078,36 @@ SDValue RISCVTargetLowering::lowerSELECT(SDValue Op, SelectionDAG &DAG) const {
         }
       }
 
-      const int TrueValCost = RISCVMatInt::getIntMatCost(
-          TrueVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
-      const int FalseValCost = RISCVMatInt::getIntMatCost(
-          FalseVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
-      bool IsCZERO_NEZ = TrueValCost <= FalseValCost;
-      SDValue LHSVal = DAG.getConstant(
-          IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal, DL, VT);
-      SDValue RHSVal =
-          DAG.getConstant(IsCZERO_NEZ ? TrueVal : FalseVal, DL, VT);
-      SDValue CMOV =
-          DAG.getNode(IsCZERO_NEZ ? RISCVISD::CZERO_NEZ : RISCVISD::CZERO_EQZ,
-                      DL, VT, LHSVal, CondV);
-      return DAG.getNode(ISD::ADD, DL, VT, CMOV, RHSVal);
+      bool IsCZERO_NEZ;
+      SDValue ConstVal, SubOp;
+      if (BothAreConstant) {
+        const APInt &TrueVal = TrueV->getAsAPIntVal();
+        const APInt &FalseVal = FalseV->getAsAPIntVal();
+        const int TrueValCost = RISCVMatInt::getIntMatCost(
+            TrueVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
+        const int FalseValCost = RISCVMatInt::getIntMatCost(
+            FalseVal, Subtarget.getXLen(), Subtarget, /*CompressionCost=*/true);
+        IsCZERO_NEZ = TrueValCost <= FalseValCost;
+
+        SubOp = DAG.getConstant(
+            IsCZERO_NEZ ? FalseVal - TrueVal : TrueVal - FalseVal, DL, VT);
+        ConstVal = DAG.getConstant(IsCZERO_NEZ ? TrueVal : FalseVal, DL, VT);
+      } else {
+        IsCZERO_NEZ = isa<ConstantSDNode>(TrueV);
+        ConstVal = IsCZERO_NEZ ? TrueV : FalseV;
+
+        SDValue &RegV = IsCZERO_NEZ ? FalseV : TrueV;
+        SubOp = DAG.getNode(ISD::SUB, DL, VT, RegV, ConstVal);
+      }
+      // The one constant case is only efficient is the constant fits into
+      // `ADDI`
+      if (BothAreConstant ||
+          isInt<12>(dyn_cast<ConstantSDNode>(ConstVal)->getSExtValue())) {
----------------
bababuck wrote:

Ended up adding a test for 2048 as well. How do you find the balance of not enough tests and too many tests (where it becomes impossible to manually verify the changes are expected).

https://github.com/llvm/llvm-project/pull/143581


More information about the llvm-commits mailing list