[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