[llvm] [AArch64] Optimize ANDS(CSET, CSET) to CCMP. (PR #174919)

via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 7 23:14:23 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: David Green (davemgreen)

<details>
<summary>Changes</summary>

We have existing optimizations for and(cset, cset) and or(cset, cset), converting them to more optimal ccmp chains. This makes use of the same optimization for ANDS instructions that do not require the result of the AND (i.e. TSTs). We generate a cset from a cset, for the flags produced by the ANDS. This will then be optimized away in many cases, leaving the ccmp and use of the flags.

---
Full diff: https://github.com/llvm/llvm-project/pull/174919.diff


4 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+20-2) 
- (modified) llvm/test/CodeGen/AArch64/arm64-ccmp.ll (+10-16) 
- (modified) llvm/test/CodeGen/AArch64/fcmp-fp128.ll (+2-4) 
- (modified) llvm/test/CodeGen/AArch64/stack-hazard.ll (+12-18) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 67984658b5110..fde212786b1cf 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -20508,7 +20508,7 @@ static SDValue performANDORCSELCombine(SDNode *N, SelectionDAG &DAG) {
   SDValue CCmp, Condition;
   unsigned NZCV;
 
-  if (N->getOpcode() == ISD::AND) {
+  if (N->getOpcode() == ISD::AND || N->getOpcode() == AArch64ISD::ANDS) {
     AArch64CC::CondCode InvCC0 = AArch64CC::getInvertedCondCode(CC0);
     Condition = getCondCode(DAG, InvCC0);
     NZCV = AArch64CC::getNZCVToSatisfyCondCode(CC1);
@@ -26733,6 +26733,24 @@ static SDValue performFlagSettingCombine(SDNode *N,
   return SDValue();
 }
 
+static SDValue performANDSCombine(SDNode *N,
+                                  TargetLowering::DAGCombinerInfo &DCI) {
+  SelectionDAG &DAG = DCI.DAG;
+  if (SDValue R = performFlagSettingCombine(N, DCI, ISD::AND))
+    return R;
+
+  // If we have no uses of the AND value, use performANDORCSELCombine to try to
+  // convert ANDS(CSET(CMP), CSET(CMP)) into CMP(CSET(CCMP(CMP))). The outer
+  // CMP(CSET should be removed by other combines, folded into the use of the
+  // CMP.
+  if (!N->hasAnyUseOfValue(0))
+    if (SDValue R = performANDORCSELCombine(N, DAG))
+      return DAG.getNode(AArch64ISD::SUBS, SDLoc(N), N->getVTList(), R,
+                         DAG.getConstant(0, SDLoc(N), N->getValueType(0)));
+
+  return SDValue();
+}
+
 static SDValue performSetCCPunpkCombine(SDNode *N, SelectionDAG &DAG) {
   // setcc_merge_zero pred
   //   (sign_extend (extract_subvector (setcc_merge_zero ... pred ...))), 0, ne
@@ -28378,7 +28396,7 @@ SDValue AArch64TargetLowering::PerformDAGCombine(SDNode *N,
   case ISD::TRUNCATE:
     return performTruncateCombine(N, DAG, DCI);
   case AArch64ISD::ANDS:
-    return performFlagSettingCombine(N, DCI, ISD::AND);
+    return performANDSCombine(N, DCI);
   case AArch64ISD::ADC:
     if (auto R = foldOverflowCheck(N, DAG, /* IsAdd */ true))
       return R;
diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
index 68ab8902767b3..71d26d25c0515 100644
--- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
@@ -936,14 +936,12 @@ define i32 @f128_select_and_olt_oge(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3,
 ; CHECK-SD-NEXT:    mov x20, x0
 ; CHECK-SD-NEXT:    stp q2, q3, [sp] ; 32-byte Folded Spill
 ; CHECK-SD-NEXT:    bl ___lttf2
-; CHECK-SD-NEXT:    cmp w0, #0
-; CHECK-SD-NEXT:    cset w21, mi
+; CHECK-SD-NEXT:    mov x21, x0
 ; CHECK-SD-NEXT:    ldp q0, q1, [sp] ; 32-byte Folded Reload
 ; CHECK-SD-NEXT:    bl ___getf2
 ; CHECK-SD-NEXT:    cmp w0, #0
-; CHECK-SD-NEXT:    cset w8, pl
-; CHECK-SD-NEXT:    tst w8, w21
-; CHECK-SD-NEXT:    csel w0, w20, w19, ne
+; CHECK-SD-NEXT:    ccmp w21, #0, #0, pl
+; CHECK-SD-NEXT:    csel w0, w20, w19, mi
 ; CHECK-SD-NEXT:    ldp x29, x30, [sp, #64] ; 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ldp x20, x19, [sp, #48] ; 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ldp x22, x21, [sp, #32] ; 16-byte Folded Reload
@@ -1050,23 +1048,19 @@ define i32 @deep_or2(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %x, i32 %y) {
 define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
 ; CHECK-SD-LABEL: multiccmp:
 ; CHECK-SD:       ; %bb.0: ; %entry
-; CHECK-SD-NEXT:    stp x22, x21, [sp, #-48]! ; 16-byte Folded Spill
-; CHECK-SD-NEXT:    stp x20, x19, [sp, #16] ; 16-byte Folded Spill
-; CHECK-SD-NEXT:    stp x29, x30, [sp, #32] ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    stp x20, x19, [sp, #-32]! ; 16-byte Folded Spill
+; CHECK-SD-NEXT:    stp x29, x30, [sp, #16] ; 16-byte Folded Spill
 ; CHECK-SD-NEXT:    mov x19, x5
 ; CHECK-SD-NEXT:    cmp w0, w1
-; CHECK-SD-NEXT:    cset w20, gt
-; CHECK-SD-NEXT:    cmp w2, w3
-; CHECK-SD-NEXT:    cset w21, ne
-; CHECK-SD-NEXT:    tst w20, w21
+; CHECK-SD-NEXT:    ccmp w2, w3, #4, gt
+; CHECK-SD-NEXT:    mrs x20, NZCV
 ; CHECK-SD-NEXT:    csel w0, w5, w4, ne
 ; CHECK-SD-NEXT:    bl _callee
-; CHECK-SD-NEXT:    tst w20, w21
+; CHECK-SD-NEXT:    msr NZCV, x20
 ; CHECK-SD-NEXT:    csel w0, w0, w19, ne
 ; CHECK-SD-NEXT:    bl _callee
-; CHECK-SD-NEXT:    ldp x29, x30, [sp, #32] ; 16-byte Folded Reload
-; CHECK-SD-NEXT:    ldp x20, x19, [sp, #16] ; 16-byte Folded Reload
-; CHECK-SD-NEXT:    ldp x22, x21, [sp], #48 ; 16-byte Folded Reload
+; CHECK-SD-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
+; CHECK-SD-NEXT:    ldp x20, x19, [sp], #32 ; 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ret
 ;
 ; CHECK-GI-LABEL: multiccmp:
diff --git a/llvm/test/CodeGen/AArch64/fcmp-fp128.ll b/llvm/test/CodeGen/AArch64/fcmp-fp128.ll
index baaa615f8ec23..d067d833a7e16 100644
--- a/llvm/test/CodeGen/AArch64/fcmp-fp128.ll
+++ b/llvm/test/CodeGen/AArch64/fcmp-fp128.ll
@@ -180,12 +180,10 @@ define double @one(fp128 %a, fp128 %b, double %d, double %e) {
 ; CHECK-SD-NEXT:    stp q0, q1, [sp] // 32-byte Folded Spill
 ; CHECK-SD-NEXT:    bl __eqtf2
 ; CHECK-SD-NEXT:    ldp q0, q1, [sp] // 32-byte Folded Reload
-; CHECK-SD-NEXT:    cmp w0, #0
-; CHECK-SD-NEXT:    cset w19, ne
+; CHECK-SD-NEXT:    mov w19, w0
 ; CHECK-SD-NEXT:    bl __unordtf2
 ; CHECK-SD-NEXT:    cmp w0, #0
-; CHECK-SD-NEXT:    cset w8, eq
-; CHECK-SD-NEXT:    tst w8, w19
+; CHECK-SD-NEXT:    ccmp w19, #0, #4, eq
 ; CHECK-SD-NEXT:    ldp x30, x19, [sp, #48] // 16-byte Folded Reload
 ; CHECK-SD-NEXT:    fcsel d0, d9, d8, ne
 ; CHECK-SD-NEXT:    ldp d9, d8, [sp, #32] // 16-byte Folded Reload
diff --git a/llvm/test/CodeGen/AArch64/stack-hazard.ll b/llvm/test/CodeGen/AArch64/stack-hazard.ll
index 000523de203fc..8a43720faf2a5 100644
--- a/llvm/test/CodeGen/AArch64/stack-hazard.ll
+++ b/llvm/test/CodeGen/AArch64/stack-hazard.ll
@@ -1737,12 +1737,11 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK0-NEXT:  .LBB27_2:
 ; CHECK0-NEXT:    ldp q0, q1, [sp] // 32-byte Folded Reload
 ; CHECK0-NEXT:    bl __lttf2
+; CHECK0-NEXT:    mov w22, w0
 ; CHECK0-NEXT:    tbz w21, #0, .LBB27_4
 ; CHECK0-NEXT:  // %bb.3:
 ; CHECK0-NEXT:    smstart sm
 ; CHECK0-NEXT:  .LBB27_4:
-; CHECK0-NEXT:    cmp w0, #0
-; CHECK0-NEXT:    cset w22, mi
 ; CHECK0-NEXT:    tbz w21, #0, .LBB27_6
 ; CHECK0-NEXT:  // %bb.5:
 ; CHECK0-NEXT:    smstop sm
@@ -1755,12 +1754,11 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK0-NEXT:  .LBB27_8:
 ; CHECK0-NEXT:    cmp w0, #0
 ; CHECK0-NEXT:    ldp x29, x30, [sp, #128] // 16-byte Folded Reload
-; CHECK0-NEXT:    cset w8, pl
-; CHECK0-NEXT:    ldp d9, d8, [sp, #112] // 16-byte Folded Reload
-; CHECK0-NEXT:    tst w8, w22
+; CHECK0-NEXT:    ccmp w22, #0, #0, pl
 ; CHECK0-NEXT:    ldp x22, x21, [sp, #160] // 16-byte Folded Reload
-; CHECK0-NEXT:    csel w0, w20, w19, ne
+; CHECK0-NEXT:    csel w0, w20, w19, mi
 ; CHECK0-NEXT:    ldp x20, x19, [sp, #176] // 16-byte Folded Reload
+; CHECK0-NEXT:    ldp d9, d8, [sp, #112] // 16-byte Folded Reload
 ; CHECK0-NEXT:    ldp d11, d10, [sp, #96] // 16-byte Folded Reload
 ; CHECK0-NEXT:    ldp d13, d12, [sp, #80] // 16-byte Folded Reload
 ; CHECK0-NEXT:    ldp d15, d14, [sp, #64] // 16-byte Folded Reload
@@ -1824,12 +1822,11 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK64-NEXT:  .LBB27_2:
 ; CHECK64-NEXT:    ldp q0, q1, [sp, #64] // 32-byte Folded Reload
 ; CHECK64-NEXT:    bl __lttf2
+; CHECK64-NEXT:    mov w22, w0
 ; CHECK64-NEXT:    tbz w21, #0, .LBB27_4
 ; CHECK64-NEXT:  // %bb.3:
 ; CHECK64-NEXT:    smstart sm
 ; CHECK64-NEXT:  .LBB27_4:
-; CHECK64-NEXT:    cmp w0, #0
-; CHECK64-NEXT:    cset w22, mi
 ; CHECK64-NEXT:    tbz w21, #0, .LBB27_6
 ; CHECK64-NEXT:  // %bb.5:
 ; CHECK64-NEXT:    smstop sm
@@ -1842,14 +1839,13 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK64-NEXT:  .LBB27_8:
 ; CHECK64-NEXT:    cmp w0, #0
 ; CHECK64-NEXT:    ldp x29, x30, [sp, #256] // 16-byte Folded Reload
-; CHECK64-NEXT:    cset w8, pl
-; CHECK64-NEXT:    ldp d9, d8, [sp, #176] // 16-byte Folded Reload
-; CHECK64-NEXT:    tst w8, w22
+; CHECK64-NEXT:    ccmp w22, #0, #0, pl
 ; CHECK64-NEXT:    ldp x22, x21, [sp, #288] // 16-byte Folded Reload
-; CHECK64-NEXT:    csel w0, w20, w19, ne
+; CHECK64-NEXT:    csel w0, w20, w19, mi
 ; CHECK64-NEXT:    ldp x20, x19, [sp, #304] // 16-byte Folded Reload
-; CHECK64-NEXT:    ldp d11, d10, [sp, #160] // 16-byte Folded Reload
+; CHECK64-NEXT:    ldp d9, d8, [sp, #176] // 16-byte Folded Reload
 ; CHECK64-NEXT:    ldr x28, [sp, #280] // 8-byte Reload
+; CHECK64-NEXT:    ldp d11, d10, [sp, #160] // 16-byte Folded Reload
 ; CHECK64-NEXT:    ldp d13, d12, [sp, #144] // 16-byte Folded Reload
 ; CHECK64-NEXT:    ldp d15, d14, [sp, #128] // 16-byte Folded Reload
 ; CHECK64-NEXT:    add sp, sp, #320
@@ -1922,12 +1918,11 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK1024-NEXT:    ldr q0, [sp, #1024] // 16-byte Reload
 ; CHECK1024-NEXT:    ldr q1, [sp, #1040] // 16-byte Reload
 ; CHECK1024-NEXT:    bl __lttf2
+; CHECK1024-NEXT:    mov w22, w0
 ; CHECK1024-NEXT:    tbz w21, #0, .LBB27_4
 ; CHECK1024-NEXT:  // %bb.3:
 ; CHECK1024-NEXT:    smstart sm
 ; CHECK1024-NEXT:  .LBB27_4:
-; CHECK1024-NEXT:    cmp w0, #0
-; CHECK1024-NEXT:    cset w22, mi
 ; CHECK1024-NEXT:    tbz w21, #0, .LBB27_6
 ; CHECK1024-NEXT:  // %bb.5:
 ; CHECK1024-NEXT:    smstop sm
@@ -1940,9 +1935,8 @@ define i32 @f128_libcall(fp128 %v0, fp128 %v1, fp128 %v2, fp128 %v3, i32 %a, i32
 ; CHECK1024-NEXT:    smstart sm
 ; CHECK1024-NEXT:  .LBB27_8:
 ; CHECK1024-NEXT:    cmp w0, #0
-; CHECK1024-NEXT:    cset w8, pl
-; CHECK1024-NEXT:    tst w8, w22
-; CHECK1024-NEXT:    csel w0, w20, w19, ne
+; CHECK1024-NEXT:    ccmp w22, #0, #0, pl
+; CHECK1024-NEXT:    csel w0, w20, w19, mi
 ; CHECK1024-NEXT:    add sp, sp, #1088
 ; CHECK1024-NEXT:    .cfi_def_cfa_offset 1152
 ; CHECK1024-NEXT:    ldp d9, d8, [sp, #48] // 16-byte Folded Reload

``````````

</details>


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


More information about the llvm-commits mailing list