[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:29 PDT 2026
https://github.com/SiliconA-Z created https://github.com/llvm/llvm-project/pull/191586
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
>From 7c673d7ff96069520b8481028daa3f39889e4ea8 Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Mon, 10 Nov 2025 21:12:46 -0500
Subject: [PATCH] [AArch64][SelectionDAG] Only fold into ands directly if AND
is one-use
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.
Peephole will catch the extra stray cases.
Fixes: #175453
---
.../Target/AArch64/AArch64ISelLowering.cpp | 18 +-
llvm/lib/Target/AArch64/AArch64InstrInfo.cpp | 98 ++++-
.../GlobalISel/split-wide-shifts-multiway.ll | 16 +-
.../CodeGen/AArch64/arm64-build-vector.ll | 3 +-
llvm/test/CodeGen/AArch64/arm64-ccmp.ll | 4 +-
llvm/test/CodeGen/AArch64/arm64-fp128.ll | 11 +-
llvm/test/CodeGen/AArch64/neg-selects.ll | 75 ++--
llvm/test/CodeGen/AArch64/peephole-and-tst.ll | 31 +-
.../CodeGen/AArch64/select-to-and-zext.ll | 61 +--
llvm/test/CodeGen/AArch64/select_const.ll | 380 ++++++------------
llvm/test/CodeGen/AArch64/sshl_sat.ll | 7 +-
11 files changed, 303 insertions(+), 401 deletions(-)
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: csinc w0, w8, wzr, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: from_i1_fail_bad_select0:
-; 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: csinc w0, w9, wzr, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: from_i1_fail_bad_select0:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csinc w0, w8, wzr, ne
+; CHECK-NEXT: ret
%masked = and i32 %y, 1
%r = select i1 %x, i32 %masked, i32 1
ret i32 %r
}
define i32 @from_i1_fail_bad_select1(i1 %x, i32 %y) {
-; CHECK-SD-LABEL: from_i1_fail_bad_select1:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: and w8, w1, #0x1
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: csel w0, wzr, w8, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: from_i1_fail_bad_select1:
-; 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, wzr, w9, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: from_i1_fail_bad_select1:
+; CHECK: // %bb.0:
+; CHECK-NEXT: and w8, w1, #0x1
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, wzr, w8, ne
+; CHECK-NEXT: ret
%masked = and i32 %y, 1
%r = select i1 %x, i32 0, i32 %masked
ret i32 %r
diff --git a/llvm/test/CodeGen/AArch64/select_const.ll b/llvm/test/CodeGen/AArch64/select_const.ll
index 0a73aed803415..e0aed4a0a1975 100644
--- a/llvm/test/CodeGen/AArch64/select_const.ll
+++ b/llvm/test/CodeGen/AArch64/select_const.ll
@@ -270,11 +270,10 @@ define i32 @select_C1_C2(i1 %cond) {
;
; CHECK-GI-LABEL: select_C1_C2:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #42 // =0x2a
-; CHECK-GI-NEXT: mov w10, #421 // =0x1a5
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w10, w9, ne
+; CHECK-GI-NEXT: mov w8, #42 // =0x2a
+; CHECK-GI-NEXT: mov w9, #421 // =0x1a5
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w9, w8, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i32 421, i32 42
ret i32 %sel
@@ -311,11 +310,10 @@ define i32 @select_C1_C2_signext(i1 signext %cond) {
;
; CHECK-GI-LABEL: select_C1_C2_signext:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #42 // =0x2a
-; CHECK-GI-NEXT: mov w10, #421 // =0x1a5
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w10, w9, ne
+; CHECK-GI-NEXT: mov w8, #42 // =0x2a
+; CHECK-GI-NEXT: mov w9, #421 // =0x1a5
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w9, w8, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i32 421, i32 42
ret i32 %sel
@@ -324,20 +322,12 @@ define i32 @select_C1_C2_signext(i1 signext %cond) {
; A binary operator with constant after the select should always get folded into the select.
define i8 @sel_constants_add_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_add_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov w8, #28 // =0x1c
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: csinc w0, w8, wzr, eq
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_add_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: mov w8, #28 // =0x1c
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: csinc w0, w8, wzr, eq
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_add_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #28 // =0x1c
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csinc w0, w8, wzr, eq
+; CHECK-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = add i8 %sel, 5
ret i8 %bo
@@ -354,11 +344,10 @@ define i8 @sel_constants_sub_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_sub_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-9 // =0xfffffff7
-; CHECK-GI-NEXT: mov w10, #18 // =0x12
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-9 // =0xfffffff7
+; CHECK-GI-NEXT: mov w9, #18 // =0x12
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = sub i8 %sel, 5
@@ -376,11 +365,10 @@ define i8 @sel_constants_sub_constant_sel_constants(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_sub_constant_sel_constants:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #9 // =0x9
-; CHECK-GI-NEXT: mov w10, #2 // =0x2
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #9 // =0x9
+; CHECK-GI-NEXT: mov w9, #2 // =0x2
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 3
%bo = sub i8 5, %sel
@@ -398,11 +386,10 @@ define i8 @sel_constants_mul_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_mul_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-4 // =0xfffffffc
-; CHECK-GI-NEXT: mov w10, #23 // =0x17
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w8, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-4 // =0xfffffffc
+; CHECK-GI-NEXT: mov w9, #23 // =0x17
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w8, w8, w9, ne
; CHECK-GI-NEXT: add w0, w8, w8, lsl #2
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
@@ -430,20 +417,12 @@ define i8 @sel_constants_sdiv_constant(i1 %cond) {
}
define i8 @sdiv_constant_sel_constants(i1 %cond) {
-; CHECK-SD-LABEL: sdiv_constant_sel_constants:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov w8, #5 // =0x5
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: csel w0, wzr, w8, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sdiv_constant_sel_constants:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: mov w8, #5 // =0x5
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: csel w0, wzr, w8, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sdiv_constant_sel_constants:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #5 // =0x5
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, wzr, w8, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, i8 121, i8 23
%bo = sdiv i8 120, %sel
ret i8 %bo
@@ -460,11 +439,10 @@ define i8 @sel_constants_udiv_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_udiv_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #50 // =0x32
-; CHECK-GI-NEXT: mov w10, #4 // =0x4
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #50 // =0x32
+; CHECK-GI-NEXT: mov w9, #4 // =0x4
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = udiv i8 %sel, 5
@@ -472,20 +450,12 @@ define i8 @sel_constants_udiv_constant(i1 %cond) {
}
define i8 @udiv_constant_sel_constants(i1 %cond) {
-; CHECK-SD-LABEL: udiv_constant_sel_constants:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov w8, #5 // =0x5
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: csel w0, wzr, w8, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: udiv_constant_sel_constants:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: mov w8, #5 // =0x5
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: csel w0, wzr, w8, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: udiv_constant_sel_constants:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #5 // =0x5
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, wzr, w8, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = udiv i8 120, %sel
ret i8 %bo
@@ -501,11 +471,10 @@ define i8 @sel_constants_srem_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_srem_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-4 // =0xfffffffc
-; CHECK-GI-NEXT: mov w10, #3 // =0x3
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-4 // =0xfffffffc
+; CHECK-GI-NEXT: mov w9, #3 // =0x3
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = srem i8 %sel, 5
@@ -523,11 +492,10 @@ define i8 @srem_constant_sel_constants(i1 %cond) {
;
; CHECK-GI-LABEL: srem_constant_sel_constants:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #120 // =0x78
-; CHECK-GI-NEXT: mov w10, #5 // =0x5
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #120 // =0x78
+; CHECK-GI-NEXT: mov w9, #5 // =0x5
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 121, i8 23
%bo = srem i8 120, %sel
@@ -563,11 +531,10 @@ define i8 @urem_constant_sel_constants(i1 %cond) {
;
; CHECK-GI-LABEL: urem_constant_sel_constants:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #120 // =0x78
-; CHECK-GI-NEXT: mov w10, #5 // =0x5
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #120 // =0x78
+; CHECK-GI-NEXT: mov w9, #5 // =0x5
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = urem i8 120, %sel
@@ -603,11 +570,10 @@ define i8 @sel_constants_or_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_or_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-3 // =0xfffffffd
-; CHECK-GI-NEXT: mov w10, #23 // =0x17
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-3 // =0xfffffffd
+; CHECK-GI-NEXT: mov w9, #23 // =0x17
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = or i8 %sel, 5
@@ -625,11 +591,10 @@ define i8 @sel_constants_xor_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_xor_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-7 // =0xfffffff9
-; CHECK-GI-NEXT: mov w10, #18 // =0x12
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-7 // =0xfffffff9
+; CHECK-GI-NEXT: mov w9, #18 // =0x12
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = xor i8 %sel, 5
@@ -647,11 +612,10 @@ define i8 @sel_constants_shl_constant(i1 %cond) {
;
; CHECK-GI-LABEL: sel_constants_shl_constant:
; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: mov w9, #-128 // =0xffffff80
-; CHECK-GI-NEXT: mov w10, #-32 // =0xffffffe0
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: csel w0, w9, w10, ne
+; CHECK-GI-NEXT: mov w8, #-128 // =0xffffff80
+; CHECK-GI-NEXT: mov w9, #-32 // =0xffffffe0
+; CHECK-GI-NEXT: tst w0, #0x1
+; CHECK-GI-NEXT: csel w0, w8, w9, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = shl i8 %sel, 5
@@ -681,20 +645,12 @@ define i8 @shl_constant_sel_constants(i1 %cond) {
}
define i8 @sel_constants_lshr_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_lshr_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov w8, #7 // =0x7
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: csel w0, w8, wzr, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_lshr_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: mov w8, #7 // =0x7
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: csel w0, w8, wzr, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_lshr_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov w8, #7 // =0x7
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: csel w0, w8, wzr, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, i8 -4, i8 23
%bo = lshr i8 %sel, 5
ret i8 %bo
@@ -756,112 +712,64 @@ define i8 @ashr_constant_sel_constants(i1 %cond) {
}
define double @sel_constants_fadd_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_fadd_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov x9, #7378697629483820646 // =0x6666666666666666
-; CHECK-SD-NEXT: adrp x8, .LCPI42_0
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: movk x9, #16444, lsl #48
-; CHECK-SD-NEXT: ldr d0, [x8, :lo12:.LCPI42_0]
-; CHECK-SD-NEXT: fmov d1, x9
-; CHECK-SD-NEXT: fcsel d0, d0, d1, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_fadd_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: mov x9, #7378697629483820646 // =0x6666666666666666
-; CHECK-GI-NEXT: adrp x8, .LCPI42_0
-; CHECK-GI-NEXT: movk x9, #16444, lsl #48
-; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI42_0]
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: fmov d1, x9
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: fcsel d0, d0, d1, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_fadd_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: mov x9, #7378697629483820646 // =0x6666666666666666
+; CHECK-NEXT: adrp x8, .LCPI42_0
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: movk x9, #16444, lsl #48
+; CHECK-NEXT: ldr d0, [x8, :lo12:.LCPI42_0]
+; CHECK-NEXT: fmov d1, x9
+; CHECK-NEXT: fcsel d0, d0, d1, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fadd double %sel, 5.1
ret double %bo
}
define double @sel_constants_fsub_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_fsub_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, .LCPI43_0
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: ldr d0, [x8, :lo12:.LCPI43_0]
-; CHECK-SD-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
-; CHECK-SD-NEXT: movk x8, #49186, lsl #48
-; CHECK-SD-NEXT: fmov d1, x8
-; CHECK-SD-NEXT: fcsel d0, d1, d0, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_fsub_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, .LCPI43_0
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI43_0]
-; CHECK-GI-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: movk x8, #49186, lsl #48
-; CHECK-GI-NEXT: fmov d1, x8
-; CHECK-GI-NEXT: fcsel d0, d1, d0, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_fsub_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, .LCPI43_0
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: ldr d0, [x8, :lo12:.LCPI43_0]
+; CHECK-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
+; CHECK-NEXT: movk x8, #49186, lsl #48
+; CHECK-NEXT: fmov d1, x8
+; CHECK-NEXT: fcsel d0, d1, d0, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fsub double %sel, 5.1
ret double %bo
}
define double @fsub_constant_sel_constants(i1 %cond) {
-; CHECK-SD-LABEL: fsub_constant_sel_constants:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, .LCPI44_0
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: ldr d0, [x8, :lo12:.LCPI44_0]
-; CHECK-SD-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
-; CHECK-SD-NEXT: movk x8, #16418, lsl #48
-; CHECK-SD-NEXT: fmov d1, x8
-; CHECK-SD-NEXT: fcsel d0, d1, d0, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: fsub_constant_sel_constants:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, .LCPI44_0
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI44_0]
-; CHECK-GI-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: movk x8, #16418, lsl #48
-; CHECK-GI-NEXT: fmov d1, x8
-; CHECK-GI-NEXT: fcsel d0, d1, d0, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: fsub_constant_sel_constants:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, .LCPI44_0
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: ldr d0, [x8, :lo12:.LCPI44_0]
+; CHECK-NEXT: mov x8, #3689348814741910323 // =0x3333333333333333
+; CHECK-NEXT: movk x8, #16418, lsl #48
+; CHECK-NEXT: fmov d1, x8
+; CHECK-NEXT: fcsel d0, d1, d0, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fsub double 5.1, %sel
ret double %bo
}
define double @sel_constants_fmul_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_fmul_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, .LCPI45_0
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: ldr d0, [x8, :lo12:.LCPI45_0]
-; CHECK-SD-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
-; CHECK-SD-NEXT: movk x8, #49204, lsl #48
-; CHECK-SD-NEXT: fmov d1, x8
-; CHECK-SD-NEXT: fcsel d0, d1, d0, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_fmul_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, .LCPI45_0
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI45_0]
-; CHECK-GI-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: movk x8, #49204, lsl #48
-; CHECK-GI-NEXT: fmov d1, x8
-; CHECK-GI-NEXT: fcsel d0, d1, d0, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_fmul_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, .LCPI45_0
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: ldr d0, [x8, :lo12:.LCPI45_0]
+; CHECK-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
+; CHECK-NEXT: movk x8, #49204, lsl #48
+; CHECK-NEXT: fmov d1, x8
+; CHECK-NEXT: fcsel d0, d1, d0, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fmul double %sel, 5.1
ret double %bo
@@ -882,10 +790,9 @@ define double @sel_constants_fdiv_constant(i1 %cond) {
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: adrp x8, .LCPI46_1
; CHECK-GI-NEXT: adrp x9, .LCPI46_0
+; CHECK-GI-NEXT: tst w0, #0x1
; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI46_1]
; CHECK-GI-NEXT: ldr d1, [x9, :lo12:.LCPI46_0]
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: tst w8, #0x1
; CHECK-GI-NEXT: fcsel d0, d1, d0, ne
; CHECK-GI-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
@@ -894,52 +801,30 @@ define double @sel_constants_fdiv_constant(i1 %cond) {
}
define double @fdiv_constant_sel_constants(i1 %cond) {
-; CHECK-SD-LABEL: fdiv_constant_sel_constants:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, .LCPI47_0
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: ldr d0, [x8, :lo12:.LCPI47_0]
-; CHECK-SD-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
-; CHECK-SD-NEXT: movk x8, #49140, lsl #48
-; CHECK-SD-NEXT: fmov d1, x8
-; CHECK-SD-NEXT: fcsel d0, d1, d0, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: fdiv_constant_sel_constants:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, .LCPI47_0
-; CHECK-GI-NEXT: and w9, w0, #0x1
-; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI47_0]
-; CHECK-GI-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
-; CHECK-GI-NEXT: tst w9, #0x1
-; CHECK-GI-NEXT: movk x8, #49140, lsl #48
-; CHECK-GI-NEXT: fmov d1, x8
-; CHECK-GI-NEXT: fcsel d0, d1, d0, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: fdiv_constant_sel_constants:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, .LCPI47_0
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: ldr d0, [x8, :lo12:.LCPI47_0]
+; CHECK-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
+; CHECK-NEXT: movk x8, #49140, lsl #48
+; CHECK-NEXT: fmov d1, x8
+; CHECK-NEXT: fcsel d0, d1, d0, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = fdiv double 5.1, %sel
ret double %bo
}
define double @sel_constants_frem_constant(i1 %cond) {
-; CHECK-SD-LABEL: sel_constants_frem_constant:
-; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: adrp x8, .LCPI48_0
-; CHECK-SD-NEXT: fmov d0, #-4.00000000
-; CHECK-SD-NEXT: tst w0, #0x1
-; CHECK-SD-NEXT: ldr d1, [x8, :lo12:.LCPI48_0]
-; CHECK-SD-NEXT: fcsel d0, d0, d1, ne
-; CHECK-SD-NEXT: ret
-;
-; CHECK-GI-LABEL: sel_constants_frem_constant:
-; CHECK-GI: // %bb.0:
-; CHECK-GI-NEXT: adrp x8, .LCPI48_0
-; CHECK-GI-NEXT: fmov d0, #-4.00000000
-; CHECK-GI-NEXT: ldr d1, [x8, :lo12:.LCPI48_0]
-; CHECK-GI-NEXT: and w8, w0, #0x1
-; CHECK-GI-NEXT: tst w8, #0x1
-; CHECK-GI-NEXT: fcsel d0, d0, d1, ne
-; CHECK-GI-NEXT: ret
+; CHECK-LABEL: sel_constants_frem_constant:
+; CHECK: // %bb.0:
+; CHECK-NEXT: adrp x8, .LCPI48_0
+; CHECK-NEXT: fmov d0, #-4.00000000
+; CHECK-NEXT: tst w0, #0x1
+; CHECK-NEXT: ldr d1, [x8, :lo12:.LCPI48_0]
+; CHECK-NEXT: fcsel d0, d0, d1, ne
+; CHECK-NEXT: ret
%sel = select i1 %cond, double -4.0, double 23.3
%bo = frem double %sel, 5.1
ret double %bo
@@ -960,10 +845,9 @@ define double @frem_constant_sel_constants(i1 %cond) {
; CHECK-GI-LABEL: frem_constant_sel_constants:
; CHECK-GI: // %bb.0:
; CHECK-GI-NEXT: adrp x8, .LCPI49_0
-; CHECK-GI-NEXT: and w9, w0, #0x1
+; CHECK-GI-NEXT: tst w0, #0x1
; CHECK-GI-NEXT: ldr d0, [x8, :lo12:.LCPI49_0]
; CHECK-GI-NEXT: mov x8, #7378697629483820646 // =0x6666666666666666
-; CHECK-GI-NEXT: tst w9, #0x1
; CHECK-GI-NEXT: movk x8, #16404, lsl #48
; CHECK-GI-NEXT: fmov d1, x8
; CHECK-GI-NEXT: fcsel d0, d0, d1, ne
diff --git a/llvm/test/CodeGen/AArch64/sshl_sat.ll b/llvm/test/CodeGen/AArch64/sshl_sat.ll
index be2b3e763733b..34f233135f002 100644
--- a/llvm/test/CodeGen/AArch64/sshl_sat.ll
+++ b/llvm/test/CodeGen/AArch64/sshl_sat.ll
@@ -142,12 +142,11 @@ define i16 @combine_shlsat_to_shl(i16 %x) nounwind {
define i16 @combine_shlsat_to_shl_no_fold(i16 %x) nounwind {
; CHECK-LABEL: combine_shlsat_to_shl_no_fold:
; CHECK: // %bb.0:
-; CHECK-NEXT: sxth w8, w0
-; CHECK-NEXT: mov w9, #-65536 // =0xffff0000
+; CHECK-NEXT: sbfiz w8, w0, #14, #16
; CHECK-NEXT: mov w10, #-2147483648 // =0x80000000
-; CHECK-NEXT: ands w8, w9, w8, lsl #14
-; CHECK-NEXT: cinv w10, w10, pl
+; CHECK-NEXT: ands w8, w8, #0xffff0000
; CHECK-NEXT: lsl w9, w8, #3
+; CHECK-NEXT: cinv w10, w10, pl
; CHECK-NEXT: cmp w8, w9, asr #3
; CHECK-NEXT: csel w8, w10, w9, ne
; CHECK-NEXT: asr w0, w8, #16
More information about the llvm-commits
mailing list