[llvm] [ARM] Have custom lowering for ucmp and scmp (PR #149315)

David Green via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 3 01:51:47 PDT 2025


================
@@ -10614,6 +10624,181 @@ SDValue ARMTargetLowering::LowerFP_TO_BF16(SDValue Op,
   return DAG.getBitcast(MVT::i32, Res);
 }
 
+SDValue ARMTargetLowering::LowerSCMP(SDValue Op, SelectionDAG &DAG) const {
+  SDLoc dl(Op);
+  SDValue LHS = Op.getOperand(0);
+  SDValue RHS = Op.getOperand(1);
+
+  // For the ARM assembly pattern:
+  // subs r0, r0, r1   ; subtract RHS from LHS and set flags
+  // movgt r0, #1      ; if LHS > RHS, set result to 1
+  // mvnlt r0, #0      ; if LHS < RHS, set result to -1 (mvn #0 = -1)
+  //                   ; if LHS == RHS, result remains 0 from the subs
+
+  // Optimization: if RHS is a subtraction against 0, use ADDC instead of SUBC
+  // Check if RHS is (0 - something), and if so use ADDC with LHS + something
+  SDValue SubResult, Flags;
+  bool CanUseAdd = false;
+  SDValue AddOperand;
+
+  // Check if RHS is a subtraction against 0: (0 - X)
+  if (RHS.getOpcode() == ISD::SUB) {
+    SDValue SubLHS = RHS.getOperand(0);
+    SDValue SubRHS = RHS.getOperand(1);
+
+    // Check if it's 0 - X
+    if (isNullConstant(SubLHS)) {
+      // For SCMP: only if X is known to never be INT_MIN (to avoid overflow)
+      if (RHS->getFlags().hasNoSignedWrap() || !DAG.computeKnownBits(SubRHS)
+                                                    .getSignedMinValue()
+                                                    .isMinSignedValue()) {
+        CanUseAdd = true;
+        AddOperand = SubRHS; // Replace RHS with X, so we do LHS + X instead of
+                             // LHS - (0 - X)
+      }
+    }
+  }
+
+  if (CanUseAdd) {
+    // Use ADDC: LHS + AddOperand (where RHS was 0 - AddOperand)
+    SDValue AddWithFlags = DAG.getNode(
+        ARMISD::ADDC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, AddOperand);
+    SubResult = AddWithFlags.getValue(0); // The addition result
+    Flags = AddWithFlags.getValue(1);     // The flags from ADDS
+  } else {
+    // Use ARMISD::SUBC to generate SUBS instruction (subtract with flags)
+    SDValue SubWithFlags = DAG.getNode(
+        ARMISD::SUBC, dl, DAG.getVTList(MVT::i32, FlagsVT), LHS, RHS);
+    SubResult = SubWithFlags.getValue(0); // The subtraction result
+    Flags = SubWithFlags.getValue(1);     // The flags from SUBS
+  }
+
+  // Constants for conditional moves
+  SDValue One = DAG.getConstant(1, dl, MVT::i32);
+  SDValue MinusOne = DAG.getAllOnesConstant(dl, MVT::i32);
+
+  // movgt: if greater than, set to 1
+  SDValue GTCond = DAG.getConstant(ARMCC::GT, dl, MVT::i32);
+  SDValue Result1 =
+      DAG.getNode(ARMISD::CMOV, dl, MVT::i32, SubResult, One, GTCond, Flags);
+
+  // mvnlt: if less than, set to -1 (equivalent to mvn #0)
+  SDValue LTCond = DAG.getConstant(ARMCC::LT, dl, MVT::i32);
+  SDValue Result2 =
+      DAG.getNode(ARMISD::CMOV, dl, MVT::i32, Result1, MinusOne, LTCond, Flags);
+
+  if (Op.getValueType() != MVT::i32)
+    Result2 = DAG.getSExtOrTrunc(Result2, dl, Op.getValueType());
+
+  return Result2;
+}
+
+SDValue ARMTargetLowering::LowerUCMP(SDValue Op, SelectionDAG &DAG) const {
----------------
davemgreen wrote:

It looks like LowerSCMP and LowerUCMP could share most of their code.

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


More information about the llvm-commits mailing list