[llvm] [AArch64][SelectionDAG][Peephole] Only fold into ands directly if AND is one-use (PR #191586)

via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 10 19:09:57 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: SiliconA-Z

<details>
<summary>Changes</summary>

Otherwise, we can be too aggressive, and when it comes time to split along edges, we can end up duplicating more than we bargained for.

This works well for one-use because it works even if the cmp and and end up in different basic blocks.

Instead, move the optimization into peephole.

Peephole will catch the extra stray cases.

Fixes: #<!-- -->175453

---

Patch is 42.41 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/191586.diff


11 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64ISelLowering.cpp (+6-12) 
- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.cpp (+93-5) 
- (modified) llvm/test/CodeGen/AArch64/GlobalISel/split-wide-shifts-multiway.ll (+6-10) 
- (modified) llvm/test/CodeGen/AArch64/arm64-build-vector.ll (+1-2) 
- (modified) llvm/test/CodeGen/AArch64/arm64-ccmp.ll (+2-2) 
- (modified) llvm/test/CodeGen/AArch64/arm64-fp128.ll (+4-7) 
- (modified) llvm/test/CodeGen/AArch64/neg-selects.ll (+23-52) 
- (modified) llvm/test/CodeGen/AArch64/peephole-and-tst.ll (+12-19) 
- (modified) llvm/test/CodeGen/AArch64/select-to-and-zext.ll (+21-40) 
- (modified) llvm/test/CodeGen/AArch64/select_const.ll (+132-248) 
- (modified) llvm/test/CodeGen/AArch64/sshl_sat.ll (+3-4) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 4b6b0758006af..029f57f98279a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3911,19 +3911,13 @@ static SDValue emitComparison(SDValue LHS, SDValue RHS, ISD::CondCode CC,
     Opcode = AArch64ISD::ADDS;
     LHS = LHS.getOperand(1);
   } else if (isNullConstant(RHS) && !isUnsignedIntSetCC(CC)) {
-    if (LHS.getOpcode() == ISD::AND) {
+    if (LHS.getOpcode() == ISD::AND && LHS.hasOneUse()) {
       // Similarly, (CMP (and X, Y), 0) can be implemented with a TST
-      // (a.k.a. ANDS) except that the flags are only guaranteed to work for one
-      // of the signed comparisons.
-      const SDValue ANDSNode =
-          DAG.getNode(AArch64ISD::ANDS, DL, DAG.getVTList(VT, FlagsVT),
-                      LHS.getOperand(0), LHS.getOperand(1));
-      // Replace all users of (and X, Y) with newly generated (ands X, Y)
-      DAG.ReplaceAllUsesWith(LHS, ANDSNode);
-      return ANDSNode.getValue(1);
-    } else if (LHS.getOpcode() == AArch64ISD::ANDS) {
-      // Use result of ANDS
-      return LHS.getValue(1);
+      // (a.k.a. ANDS) except that the flags are only guaranteed to work for
+      // signed comparisons.
+      Opcode = AArch64ISD::ANDS;
+      RHS = LHS.getOperand(1);
+      LHS = LHS.getOperand(0);
     }
   }
 
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
index 4094526574d7a..a32c04b86a303 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.cpp
@@ -1592,13 +1592,12 @@ bool AArch64InstrInfo::analyzeCompare(const MachineInstr &MI, Register &SrcReg,
   case AArch64::ANDSWri:
   case AArch64::ANDSXri:
     // ANDS does not use the same encoding scheme as the others xxxS
-    // instructions.
+    // instructions. CmpMask holds the encoded logical immediate (operand 2),
+    // not decodeLogicalImmediate; CmpValue is 0 (TST-style).
     SrcReg = MI.getOperand(1).getReg();
     SrcReg2 = 0;
-    CmpMask = ~0;
-    CmpValue = AArch64_AM::decodeLogicalImmediate(
-                   MI.getOperand(2).getImm(),
-                   MI.getOpcode() == AArch64::ANDSWri ? 32 : 64);
+    CmpMask = MI.getOperand(2).getImm();
+    CmpValue = 0;
     return true;
   }
 
@@ -1917,6 +1916,91 @@ bool AArch64InstrInfo::optimizePTestInstr(
   return true;
 }
 
+/// \p EncodedLogicalImm is the immediate operand as stored on the MI (same
+/// encoding as analyzeCompare places in CmpMask for ANDSWri / ANDSXri).
+static bool isSuitableForLogicalImmAND(MachineInstr *MI, Register SrcReg,
+                                       int64_t EncodedLogicalImm,
+                                       unsigned BitSize, bool CommonUse) {
+  if (!MI)
+    return false;
+  assert(BitSize == 32 || BitSize == 64);
+  const unsigned Opc = MI->getOpcode();
+  if (Opc != (BitSize == 32 ? AArch64::ANDWri : AArch64::ANDXri))
+    return false;
+  if (!MI->getOperand(2).isImm())
+    return false;
+  if (MI->getOperand(2).getImm() != EncodedLogicalImm)
+    return false;
+  const unsigned RegOp = CommonUse ? 1 : 0;
+  if (!MI->getOperand(RegOp).isReg() || MI->getOperand(RegOp).getSubReg())
+    return false;
+  return MI->getOperand(RegOp).getReg() == SrcReg;
+}
+
+/// If CmpInstr is ANDSWri / ANDSXri whose GPR result is unused, and an earlier
+/// ANDWri / ANDXri in the same block applies the same logical immediate to the
+/// same source register, promote that AND to ANDS and erase CmpInstr.
+static bool tryFuseLogicalImmANDSWithPriorAND(
+    MachineInstr &CmpInstr, Register SrcReg, int64_t EncodedLogicalImm,
+    const MachineRegisterInfo *MRI, const AArch64InstrInfo &TII) {
+  const unsigned CmpOpc = CmpInstr.getOpcode();
+  if (CmpOpc != AArch64::ANDSWri && CmpOpc != AArch64::ANDSXri)
+    return false;
+  const unsigned BitSize = CmpOpc == AArch64::ANDSWri ? 32 : 64;
+  if (!CmpInstr.getOperand(2).isImm() ||
+      CmpInstr.getOperand(2).getImm() != EncodedLogicalImm)
+    return false;
+
+  MachineInstr *MI = MRI->getUniqueVRegDef(SrcReg);
+  if (!MI || !isSuitableForLogicalImmAND(MI, SrcReg, EncodedLogicalImm, BitSize,
+                                         false) ||
+      TII.isPredicated(*MI)) {
+    MI = nullptr;
+    for (MachineRegisterInfo::use_instr_iterator UI = MRI->use_instr_begin(SrcReg),
+                                                 UE = MRI->use_instr_end();
+         UI != UE; ++UI) {
+      if (UI->getParent() != CmpInstr.getParent())
+        continue;
+      MachineInstr *PotentialAND = &*UI;
+      if (!isSuitableForLogicalImmAND(PotentialAND, SrcReg, EncodedLogicalImm,
+                                      BitSize, true) ||
+          TII.isPredicated(*PotentialAND))
+        continue;
+      MI = PotentialAND;
+      break;
+    }
+    if (!MI)
+      return false;
+  }
+
+  MachineBasicBlock *MBB = CmpInstr.getParent();
+  if (MI->getParent() != MBB)
+    return false;
+  bool MIIsBeforeCmp = false;
+  for (auto It = std::next(MI->getIterator()); It != MBB->end(); ++It) {
+    if (&*It == &CmpInstr) {
+      MIIsBeforeCmp = true;
+      break;
+    }
+  }
+  if (!MIIsBeforeCmp)
+    return false;
+
+  const TargetRegisterInfo &TRI = TII.getRegisterInfo();
+  if (areCFlagsAccessedBetweenInstrs(MI, &CmpInstr, &TRI, AK_All))
+    return false;
+
+  const unsigned NewOpc =
+      BitSize == 32 ? AArch64::ANDSWri : AArch64::ANDSXri;
+  MI->setDesc(TII.get(NewOpc));
+  CmpInstr.eraseFromParent();
+  bool succeeded = UpdateOperandRegClass(*MI);
+  (void)succeeded;
+  assert(succeeded && "Some operands reg class are incompatible!");
+  MI->addRegisterDefined(AArch64::NZCV, &TRI);
+  return true;
+}
+
 /// Try to optimize a compare instruction. A compare instruction is an
 /// instruction which produces AArch64::NZCV. It can be truly compare
 /// instruction
@@ -1968,6 +2052,10 @@ bool AArch64InstrInfo::optimizeCompareInstr(
   if (!MRI->use_nodbg_empty(CmpInstr.getOperand(0).getReg()))
     return false;
 
+  if (CmpValue == 0 &&
+      tryFuseLogicalImmANDSWithPriorAND(CmpInstr, SrcReg, CmpMask, MRI, *this))
+    return true;
+
   if (CmpValue == 0 && substituteCmpToZero(CmpInstr, SrcReg, *MRI))
     return true;
   return (CmpValue == 0 || CmpValue == 1) &&
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/split-wide-shifts-multiway.ll b/llvm/test/CodeGen/AArch64/GlobalISel/split-wide-shifts-multiway.ll
index d669c49cb019b..8d05d8c833370 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/split-wide-shifts-multiway.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/split-wide-shifts-multiway.ll
@@ -437,8 +437,7 @@ define void @test_lshr_i512(ptr %result, ptr %input, i32 %shift) {
 ; GISEL-NEXT:    mov w8, w2
 ; GISEL-NEXT:    ldp x13, x2, [x1]
 ; GISEL-NEXT:    mov w9, #64 ; =0x40
-; GISEL-NEXT:    and x14, x8, #0x3f
-; GISEL-NEXT:    tst x8, #0x3f
+; GISEL-NEXT:    ands x14, x8, #0x3f
 ; GISEL-NEXT:    sub x17, x9, x14
 ; GISEL-NEXT:    ldp x5, x16, [x1, #16]
 ; GISEL-NEXT:    lsl x10, x2, x17
@@ -788,11 +787,10 @@ define void @test_ashr_i512(ptr %result, ptr %input, i32 %shift) {
 ; GISEL-NEXT:    mov w8, w2
 ; GISEL-NEXT:    ldp x14, x4, [x1]
 ; GISEL-NEXT:    mov w9, #64 ; =0x40
-; GISEL-NEXT:    and x16, x8, #0x3f
+; GISEL-NEXT:    ands x16, x8, #0x3f
 ; GISEL-NEXT:    lsr x10, x8, #6
 ; GISEL-NEXT:    sub x15, x9, x16
 ; GISEL-NEXT:    ldr x9, [x1, #56]
-; GISEL-NEXT:    tst x8, #0x3f
 ; GISEL-NEXT:    lsl x12, x4, x15
 ; GISEL-NEXT:    ldp x7, x3, [x1, #16]
 ; GISEL-NEXT:    lsr x13, x14, x16
@@ -2505,8 +2503,8 @@ define void @test_lshr_i1024(ptr %result, ptr %input, i32 %shift) {
 ; GISEL-NEXT:    mov w8, w2
 ; GISEL-NEXT:    ldp x20, x16, [x1]
 ; GISEL-NEXT:    mov w9, #64 ; =0x40
-; GISEL-NEXT:    and x14, x8, #0x3f
-; GISEL-NEXT:    tst x8, #0x3f
+; GISEL-NEXT:    ands x14, x8, #0x3f
+; GISEL-NEXT:    str x0, [sp, #296] ; 8-byte Spill
 ; GISEL-NEXT:    sub x15, x9, x14
 ; GISEL-NEXT:    ldp x12, x13, [x1, #16]
 ; GISEL-NEXT:    lsl x10, x16, x15
@@ -2530,10 +2528,9 @@ define void @test_lshr_i1024(ptr %result, ptr %input, i32 %shift) {
 ; GISEL-NEXT:    ldp x12, x16, [x1, #32]
 ; GISEL-NEXT:    csel x10, x11, x10, eq
 ; GISEL-NEXT:    tst x8, #0x3f
-; GISEL-NEXT:    str x0, [sp, #296] ; 8-byte Spill
+; GISEL-NEXT:    str x13, [sp, #216] ; 8-byte Spill
 ; GISEL-NEXT:    csel x11, xzr, x24, eq
 ; GISEL-NEXT:    cmp x9, #2
-; GISEL-NEXT:    str x13, [sp, #216] ; 8-byte Spill
 ; GISEL-NEXT:    lsl x23, x12, x15
 ; GISEL-NEXT:    orr x11, x26, x11
 ; GISEL-NEXT:    stp x12, x16, [sp, #176] ; 16-byte Folded Spill
@@ -3730,12 +3727,11 @@ define void @test_ashr_i1024(ptr %result, ptr %input, i32 %shift) {
 ; GISEL-NEXT:    mov w8, w2
 ; GISEL-NEXT:    mov w9, #64 ; =0x40
 ; GISEL-NEXT:    ldp x7, x0, [x1]
-; GISEL-NEXT:    and x15, x8, #0x3f
+; GISEL-NEXT:    ands x15, x8, #0x3f
 ; GISEL-NEXT:    sub x14, x9, x15
 ; GISEL-NEXT:    ldr x28, [x1, #120]
 ; GISEL-NEXT:    lsr x10, x8, #6
 ; GISEL-NEXT:    ldp x17, x16, [x1, #16]
-; GISEL-NEXT:    tst x8, #0x3f
 ; GISEL-NEXT:    lsl x9, x0, x14
 ; GISEL-NEXT:    lsr x12, x7, x15
 ; GISEL-NEXT:    asr x11, x28, #63
diff --git a/llvm/test/CodeGen/AArch64/arm64-build-vector.ll b/llvm/test/CodeGen/AArch64/arm64-build-vector.ll
index 914f431866cce..030d7892845e9 100644
--- a/llvm/test/CodeGen/AArch64/arm64-build-vector.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-build-vector.ll
@@ -136,8 +136,7 @@ define <1 x double> @convert_single_fp_vector_constant(i1 %cmp) {
 ; CHECK-GI:       // %bb.0: // %entry
 ; CHECK-GI-NEXT:    movi d0, #0000000000000000
 ; CHECK-GI-NEXT:    fmov d1, #1.00000000
-; CHECK-GI-NEXT:    and w8, w0, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
+; CHECK-GI-NEXT:    tst w0, #0x1
 ; CHECK-GI-NEXT:    fcsel d0, d1, d0, ne
 ; CHECK-GI-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
index 71d26d25c0515..4058820789656 100644
--- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
@@ -1053,10 +1053,10 @@ define i32 @multiccmp(i32 %s0, i32 %s1, i32 %s2, i32 %s3, i32 %x, i32 %y) #0 {
 ; CHECK-SD-NEXT:    mov x19, x5
 ; CHECK-SD-NEXT:    cmp w0, w1
 ; CHECK-SD-NEXT:    ccmp w2, w3, #4, gt
-; CHECK-SD-NEXT:    mrs x20, NZCV
+; CHECK-SD-NEXT:    cset w20, ne
 ; CHECK-SD-NEXT:    csel w0, w5, w4, ne
 ; CHECK-SD-NEXT:    bl _callee
-; CHECK-SD-NEXT:    msr NZCV, x20
+; CHECK-SD-NEXT:    cmp w20, #0
 ; CHECK-SD-NEXT:    csel w0, w0, w19, ne
 ; CHECK-SD-NEXT:    bl _callee
 ; CHECK-SD-NEXT:    ldp x29, x30, [sp, #16] ; 16-byte Folded Reload
diff --git a/llvm/test/CodeGen/AArch64/arm64-fp128.ll b/llvm/test/CodeGen/AArch64/arm64-fp128.ll
index c4f91c66fb9a6..6101125675f7f 100644
--- a/llvm/test/CodeGen/AArch64/arm64-fp128.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-fp128.ll
@@ -296,13 +296,12 @@ define fp128 @test_select(i1 %cond, fp128 %lhs, fp128 %rhs) {
 ;
 ; CHECK-GI-LABEL: test_select:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w0, #0x1
+; CHECK-GI-NEXT:    tst w0, #0x1
 ; CHECK-GI-NEXT:    mov d2, v0.d[1]
 ; CHECK-GI-NEXT:    mov d3, v1.d[1]
-; CHECK-GI-NEXT:    tst w8, #0x1
 ; CHECK-GI-NEXT:    fcsel d0, d0, d1, ne
-; CHECK-GI-NEXT:    fcsel d1, d2, d3, ne
 ; CHECK-GI-NEXT:    fmov x8, d0
+; CHECK-GI-NEXT:    fcsel d1, d2, d3, ne
 ; CHECK-GI-NEXT:    mov v0.d[0], x8
 ; CHECK-GI-NEXT:    fmov x8, d1
 ; CHECK-GI-NEXT:    mov v0.d[1], x8
@@ -1146,13 +1145,11 @@ define <2 x fp128> @vec_select(<2 x i1> %cond, <2 x fp128> %lhs, <2 x fp128> %rh
 ; CHECK-GI-LABEL: vec_select:
 ; CHECK-GI:       // %bb.0:
 ; CHECK-GI-NEXT:    // kill: def $d0 killed $d0 def $q0
-; CHECK-GI-NEXT:    mov w8, v0.s[1]
-; CHECK-GI-NEXT:    fmov w9, s0
 ; CHECK-GI-NEXT:    mov d5, v1.d[1]
 ; CHECK-GI-NEXT:    mov d6, v3.d[1]
-; CHECK-GI-NEXT:    and w9, w9, #0x1
+; CHECK-GI-NEXT:    mov w8, v0.s[1]
+; CHECK-GI-NEXT:    fmov w9, s0
 ; CHECK-GI-NEXT:    tst w9, #0x1
-; CHECK-GI-NEXT:    and w8, w8, #0x1
 ; CHECK-GI-NEXT:    fcsel d0, d1, d3, ne
 ; CHECK-GI-NEXT:    fcsel d3, d5, d6, ne
 ; CHECK-GI-NEXT:    tst w8, #0x1
diff --git a/llvm/test/CodeGen/AArch64/neg-selects.ll b/llvm/test/CodeGen/AArch64/neg-selects.ll
index f656fc2e62040..380a092dbba33 100644
--- a/llvm/test/CodeGen/AArch64/neg-selects.ll
+++ b/llvm/test/CodeGen/AArch64/neg-selects.ll
@@ -11,10 +11,9 @@ define i32 @neg_select_neg(i32 %a, i32 %b, i1 %bb) {
 ;
 ; CHECK-GI-LABEL: neg_select_neg:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    neg w9, w0
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csneg w8, w9, w1, ne
+; CHECK-GI-NEXT:    neg w8, w0
+; CHECK-GI-NEXT:    tst w2, #0x1
+; CHECK-GI-NEXT:    csneg w8, w8, w1, ne
 ; CHECK-GI-NEXT:    neg w0, w8
 ; CHECK-GI-NEXT:    ret
   %nega = sub i32 0, %a
@@ -25,18 +24,11 @@ define i32 @neg_select_neg(i32 %a, i32 %b, i1 %bb) {
 }
 
 define i32 @negneg_select_nega(i32 %a, i32 %b, i1 %bb) {
-; CHECK-SD-LABEL: negneg_select_nega:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    tst w2, #0x1
-; CHECK-SD-NEXT:    csneg w0, w1, w0, eq
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: negneg_select_nega:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csneg w0, w1, w0, eq
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: negneg_select_nega:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    tst w2, #0x1
+; CHECK-NEXT:    csneg w0, w1, w0, eq
+; CHECK-NEXT:    ret
   %nega = sub i32 0, %a
   %sel = select i1 %bb, i32 %nega, i32 %b
   %nsel = sub i32 0, %sel
@@ -53,8 +45,7 @@ define i32 @neg_select_nega(i32 %a, i32 %b, i1 %bb) {
 ;
 ; CHECK-GI-LABEL: neg_select_nega:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
+; CHECK-GI-NEXT:    tst w2, #0x1
 ; CHECK-GI-NEXT:    csneg w8, w1, w0, eq
 ; CHECK-GI-NEXT:    neg w0, w8
 ; CHECK-GI-NEXT:    ret
@@ -73,8 +64,7 @@ define i32 @neg_select_negb(i32 %a, i32 %b, i1 %bb) {
 ;
 ; CHECK-GI-LABEL: neg_select_negb:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
+; CHECK-GI-NEXT:    tst w2, #0x1
 ; CHECK-GI-NEXT:    csneg w8, w0, w1, ne
 ; CHECK-GI-NEXT:    neg w0, w8
 ; CHECK-GI-NEXT:    ret
@@ -85,47 +75,28 @@ define i32 @neg_select_negb(i32 %a, i32 %b, i1 %bb) {
 }
 
 define i32 @neg_select_ab(i32 %a, i32 %b, i1 %bb) {
-; CHECK-SD-LABEL: neg_select_ab:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    tst w2, #0x1
-; CHECK-SD-NEXT:    csel w8, w0, w1, ne
-; CHECK-SD-NEXT:    neg w0, w8
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: neg_select_ab:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csel w8, w0, w1, ne
-; CHECK-GI-NEXT:    neg w0, w8
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: neg_select_ab:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    tst w2, #0x1
+; CHECK-NEXT:    csel w8, w0, w1, ne
+; CHECK-NEXT:    neg w0, w8
+; CHECK-NEXT:    ret
   %sel = select i1 %bb, i32 %a, i32 %b
   %res = sub i32 0, %sel
   ret i32 %res
 }
 
 define i32 @neg_select_nega_with_use(i32 %a, i32 %b, i1 %bb) {
-; CHECK-SD-LABEL: neg_select_nega_with_use:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    tst w2, #0x1
-; CHECK-SD-NEXT:    neg w8, w0
-; CHECK-SD-NEXT:    csneg w9, w1, w0, eq
-; CHECK-SD-NEXT:    sub w0, w8, w9
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: neg_select_nega_with_use:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w2, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    neg w8, w0
-; CHECK-GI-NEXT:    csneg w9, w1, w0, eq
-; CHECK-GI-NEXT:    sub w0, w8, w9
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: neg_select_nega_with_use:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    tst w2, #0x1
+; CHECK-NEXT:    neg w8, w0
+; CHECK-NEXT:    csneg w9, w1, w0, eq
+; CHECK-NEXT:    sub w0, w8, w9
+; CHECK-NEXT:    ret
   %nega = sub i32 0, %a
   %sel = select i1 %bb, i32 %nega, i32 %b
   %nsel = sub i32 0, %sel
   %res = add i32 %nsel, %nega
   ret i32 %res
 }
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
index 74b0e69d1b05b..d955310e09c7f 100644
--- a/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
+++ b/llvm/test/CodeGen/AArch64/peephole-and-tst.ll
@@ -180,18 +180,11 @@ do.end:                                           ; preds = %4
 }
 
 define i64 @test_and1(i64 %x, i64 %y) {
-; CHECK-SD-LABEL: test_and1:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    ands x8, x0, #0x3
-; CHECK-SD-NEXT:    csel x0, x8, x1, eq
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: test_and1:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and x8, x0, #0x3
-; CHECK-GI-NEXT:    tst x0, #0x3
-; CHECK-GI-NEXT:    csel x0, x8, x1, eq
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: test_and1:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    ands x8, x0, #0x3
+; CHECK-NEXT:    csel x0, x8, x1, eq
+; CHECK-NEXT:    ret
   %a = and i64 %x, 3
   %c = icmp eq i64 %a, 0
   %s = select i1 %c, i64 %a, i64 %y
@@ -219,12 +212,12 @@ define i64 @test_and3(i64 %x, i64 %y) {
 ; CHECK-SD-NEXT:    .cfi_offset w19, -8
 ; CHECK-SD-NEXT:    .cfi_offset w20, -16
 ; CHECK-SD-NEXT:    .cfi_offset w30, -32
-; CHECK-SD-NEXT:    mov x20, x0
+; CHECK-SD-NEXT:    and x20, x0, #0x3
 ; CHECK-SD-NEXT:    mov x0, xzr
 ; CHECK-SD-NEXT:    mov x19, x1
 ; CHECK-SD-NEXT:    bl callee
-; CHECK-SD-NEXT:    ands x8, x20, #0x3
-; CHECK-SD-NEXT:    csel x0, x8, x19, eq
+; CHECK-SD-NEXT:    cmp x20, #0
+; CHECK-SD-NEXT:    csel x0, x20, x19, eq
 ; CHECK-SD-NEXT:    ldp x20, x19, [sp, #16] // 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ldr x30, [sp], #32 // 8-byte Folded Reload
 ; CHECK-SD-NEXT:    ret
@@ -262,11 +255,11 @@ define i64 @test_and_4(i64 %x, i64 %y) {
 ; CHECK-SD-NEXT:    .cfi_def_cfa_offset 16
 ; CHECK-SD-NEXT:    .cfi_offset w19, -8
 ; CHECK-SD-NEXT:    .cfi_offset w30, -16
-; CHECK-SD-NEXT:    mov x19, x0
-; CHECK-SD-NEXT:    ands x0, x0, #0x3
+; CHECK-SD-NEXT:    and x19, x0, #0x3
+; CHECK-SD-NEXT:    mov x0, x19
 ; CHECK-SD-NEXT:    bl callee
-; CHECK-SD-NEXT:    ands x8, x19, #0x3
-; CHECK-SD-NEXT:    csel x0, x8, x0, eq
+; CHECK-SD-NEXT:    cmp x19, #0
+; CHECK-SD-NEXT:    csel x0, x19, x0, eq
 ; CHECK-SD-NEXT:    ldp x30, x19, [sp], #16 // 16-byte Folded Reload
 ; CHECK-SD-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/AArch64/select-to-and-zext.ll b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
index a980c960f8678..51c1ee02a7f3a 100644
--- a/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
+++ b/llvm/test/CodeGen/AArch64/select-to-and-zext.ll
@@ -38,10 +38,9 @@ define i32 @from_i1(i1 %x, i32 %y) {
 ;
 ; CHECK-GI-LABEL: from_i1:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w0, #0x1
-; CHECK-GI-NEXT:    and w9, w1, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csel w0, w9, wzr, ne
+; CHECK-GI-NEXT:    and w8, w1, #0x1
+; CHECK-GI-NEXT:    tst w0, #0x1
+; CHECK-GI-NEXT:    csel w0, w8, wzr, ne
 ; CHECK-GI-NEXT:    ret
   %masked = and i32 %y, 1
   %r = select i1 %x, i32 %masked, i32 0
@@ -57,10 +56,9 @@ define i32 @from_trunc_i8(i8 %xx, i32 %y) {
 ;
 ; CHECK-GI-LABEL: from_trunc_i8:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w0, #0x1
-; CHECK-GI-NEXT:    and w9, w1, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csel w0, w9, wzr, ne
+; CHECK-GI-NEXT:    and w8, w1, #0x1
+; CHECK-GI-NEXT:    tst w0, #0x1
+; CHECK-GI-NEXT:    csel w0, w8, wzr, ne
 ; CHECK-GI-NEXT:    ret
   %masked = and i32 %y, 1
   %x = trunc i8 %xx to i1
@@ -77,10 +75,9 @@ define i32 @from_trunc_i64(i64 %xx, i32 %y) {
 ;
 ; CHECK-GI-LABEL: from_trunc_i64:
 ; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    and w8, w0, #0x1
-; CHECK-GI-NEXT:    and w9, w1, #0x1
-; CHECK-GI-NEXT:    tst w8, #0x1
-; CHECK-GI-NEXT:    csel w0, w9, wzr, ne
+; CHECK-GI-NEXT:    and w8, w1, #0x1
+; CHECK-GI-NEXT:    tst w0, #0x1
+; CHECK-GI-NEXT:    csel w0, w8, wzr, ne
 ; CHECK-GI-NEXT:    ret
   %masked = and i32 %y, 1
   %x = trunc i64 %xx to i1
@@ -89,40 +86,24 @@ define i32 @from_trunc_i64(i64 %xx, i32 %y) {
 }
 
 define i32 @from_i1_fail_bad_select0(i1 %x, i32 %y) {
-; CHECK-SD-LABEL: from_i1_fail_bad_select0:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    and w8, w1, #0x1
-; CHECK-SD-NEXT:    tst w0, #0x1
-; CHECK-SD-NEXT:   ...
[truncated]

``````````

</details>


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


More information about the llvm-commits mailing list