[llvm] [AArch64] Improve lowering of scalar abs(sub(a, b)). (PR #151180)

Ricardo Jesus via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 30 07:14:23 PDT 2025


================
@@ -7118,12 +7118,21 @@ SDValue AArch64TargetLowering::LowerABS(SDValue Op, SelectionDAG &DAG) const {
     return LowerToPredicatedOp(Op, DAG, AArch64ISD::ABS_MERGE_PASSTHRU);
 
   SDLoc DL(Op);
-  SDValue Neg = DAG.getNode(ISD::SUB, DL, VT, DAG.getConstant(0, DL, VT),
-                            Op.getOperand(0));
-  // Generate SUBS & CSEL.
-  SDValue Cmp = DAG.getNode(AArch64ISD::SUBS, DL, DAG.getVTList(VT, FlagsVT),
-                            Op.getOperand(0), DAG.getConstant(0, DL, VT));
-  return DAG.getNode(AArch64ISD::CSEL, DL, VT, Op.getOperand(0), Neg,
+  SDValue Val = Op.getOperand(0);
+  SDValue Neg = DAG.getNegative(Val, DL, VT);
+  SDValue Cmp;
+
+  // For abs(sub(lhs, rhs)), we can compare lhs and rhs directly. This allows
+  // reusing the subs operation for the calculation and comparison.
+  if (Val.getOpcode() == ISD::SUB)
+    Cmp = DAG.getNode(AArch64ISD::SUBS, DL, DAG.getVTList(VT, FlagsVT),
+                      Val.getOperand(0), Val.getOperand(1));
+  else
----------------
rj-jesus wrote:

The reason I didn't implement this more generally, which I forgot to document, was because I think `subs(sub(a,b), 0) -> subs(a,b)` isn't valid for any use of the flags set by `subs(x, 0)`, and specifically should be invalid for users of the overflow flags C/V (right?). This should be valid here because we only require the N flag for AArch64CC::PL.

I think it would be possible to implement this as a general DAG combine, but we'd need to ensure the users of the `subs` (or hypothetically other flag-setting ops) only use the N/Z flags. Is this what you had in mind, or did I miss anything? 

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


More information about the llvm-commits mailing list