[llvm] [AArch64] Use ccmn to compare negative imm constants (PR #95825)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 14:34:45 PDT 2024
https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/95825
>From e71b2469f3ae9a8c3dc6b81ff7c20934ba7cba4f Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Mon, 17 Jun 2024 14:25:39 -0400
Subject: [PATCH 1/2] Pre-commit test (NFC)
---
llvm/test/CodeGen/AArch64/cmp-chains.ll | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index 1d9f39e518593..51b3fab43fe79 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -242,5 +242,30 @@ define i32 @true_or3(i32 %0, i32 %1, i32 %2) {
%9 = zext i1 %8 to i32
ret i32 %9
}
+
+; (b > -3 && a < c)
+define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) {
+; SDISEL-LABEL: neg_range_int:
+; SDISEL: // %bb.0:
+; SDISEL-NEXT: cmp w0, w2
+; SDISEL-NEXT: mov w8, #-3 // =0xfffffffd
+; SDISEL-NEXT: ccmp w1, w8, #4, lt
+; SDISEL-NEXT: csel w0, w1, w0, gt
+; SDISEL-NEXT: ret
+;
+; GISEL-LABEL: neg_range_int:
+; GISEL: // %bb.0:
+; GISEL-NEXT: mov w8, #-3 // =0xfffffffd
+; GISEL-NEXT: cmp w0, w2
+; GISEL-NEXT: ccmp w1, w8, #4, lt
+; GISEL-NEXT: csel w0, w1, w0, gt
+; GISEL-NEXT: ret
+ %cmp = icmp sgt i32 %b, -3
+ %cmp1 = icmp slt i32 %a, %c
+ %or.cond = and i1 %cmp, %cmp1
+ %retval.0 = select i1 %or.cond, i32 %b, i32 %a
+ ret i32 %retval.0
+}
+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; CHECK: {{.*}}
>From b5bb28765bac4568dfebe1dac998df2c1233d265 Mon Sep 17 00:00:00 2001
From: Rose <gfunni234 at gmail.com>
Date: Mon, 17 Jun 2024 14:28:44 -0400
Subject: [PATCH 2/2] [AArch64] Use ccmn to compare negative imm constants
Because ccmn is like a + b, it works when using cmp but with values that when negated are in the range of 1 through 31.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 6 +++++
.../GISel/AArch64InstructionSelector.cpp | 14 +++++++----
llvm/test/CodeGen/AArch64/arm64-ccmp.ll | 3 +--
llvm/test/CodeGen/AArch64/cmp-chains.ll | 23 +++++--------------
4 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index 35871cc5ade7f..b39c3dea2b9bd 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -3443,6 +3443,12 @@ static SDValue emitConditionalComparison(SDValue LHS, SDValue RHS,
Opcode = AArch64ISD::CCMN;
RHS = RHS.getOperand(1);
}
+ } else if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(RHS)) {
+ APInt imm = Const->getAPIntValue();
+ if (imm.isNegative() && imm.sgt(-32)) {
+ Opcode = AArch64ISD::CCMN;
+ RHS = DAG.getConstant(imm.abs(), DL, Const->getValueType(0));
+ }
}
if (Opcode == 0)
Opcode = AArch64ISD::CCMP;
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 4a7c82b393c10..412176f9ed9c3 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4660,7 +4660,6 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
Register LHS, Register RHS, CmpInst::Predicate CC,
AArch64CC::CondCode Predicate, AArch64CC::CondCode OutCC,
MachineIRBuilder &MIB) const {
- // TODO: emit CMN as an optimization.
auto &MRI = *MIB.getMRI();
LLT OpTy = MRI.getType(LHS);
unsigned CCmpOpc;
@@ -4668,9 +4667,14 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
if (CmpInst::isIntPredicate(CC)) {
assert(OpTy.getSizeInBits() == 32 || OpTy.getSizeInBits() == 64);
C = getIConstantVRegValWithLookThrough(RHS, MRI);
- if (C && C->Value.ult(32))
- CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
- else
+ if (C && (C->Value.slt(32) && C->Value.sgt(-32))) {
+ if (C->Value.ult(32))
+ CCmpOpc =
+ OpTy.getSizeInBits() == 32 ? AArch64::CCMPWi : AArch64::CCMPXi;
+ else
+ CCmpOpc =
+ OpTy.getSizeInBits() == 32 ? AArch64::CCMNWi : AArch64::CCMNXi;
+ } else
CCmpOpc = OpTy.getSizeInBits() == 32 ? AArch64::CCMPWr : AArch64::CCMPXr;
} else {
assert(OpTy.getSizeInBits() == 16 || OpTy.getSizeInBits() == 32 ||
@@ -4696,6 +4700,8 @@ MachineInstr *AArch64InstructionSelector::emitConditionalComparison(
MIB.buildInstr(CCmpOpc, {}, {LHS});
if (CCmpOpc == AArch64::CCMPWi || CCmpOpc == AArch64::CCMPXi)
CCmp.addImm(C->Value.getZExtValue());
+ else if (CCmpOpc == AArch64::CCMNWi || CCmpOpc == AArch64::CCMNXi)
+ CCmp.addImm(C->Value.abs().getZExtValue());
else
CCmp.addReg(RHS);
CCmp.addImm(NZCV).addImm(Predicate);
diff --git a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
index 5d3b2d3649e1b..b6702bba1598c 100644
--- a/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-ccmp.ll
@@ -706,10 +706,9 @@ define i32 @select_noccmp3(i32 %v0, i32 %v1, i32 %v2) {
; GISEL: ; %bb.0:
; GISEL-NEXT: mov w8, #99 ; =0x63
; GISEL-NEXT: sub w9, w0, #45
-; GISEL-NEXT: mov w10, #-23 ; =0xffffffe9
; GISEL-NEXT: cmp w0, #77
; GISEL-NEXT: ccmp w0, w8, #4, ne
-; GISEL-NEXT: ccmp w9, w10, #2, eq
+; GISEL-NEXT: ccmn w9, #23, #2, eq
; GISEL-NEXT: ccmp w0, #14, #0, lo
; GISEL-NEXT: csel w0, w1, w2, hs
; GISEL-NEXT: ret
diff --git a/llvm/test/CodeGen/AArch64/cmp-chains.ll b/llvm/test/CodeGen/AArch64/cmp-chains.ll
index 51b3fab43fe79..14cb0c82b1c03 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -245,21 +245,12 @@ define i32 @true_or3(i32 %0, i32 %1, i32 %2) {
; (b > -3 && a < c)
define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) {
-; SDISEL-LABEL: neg_range_int:
-; SDISEL: // %bb.0:
-; SDISEL-NEXT: cmp w0, w2
-; SDISEL-NEXT: mov w8, #-3 // =0xfffffffd
-; SDISEL-NEXT: ccmp w1, w8, #4, lt
-; SDISEL-NEXT: csel w0, w1, w0, gt
-; SDISEL-NEXT: ret
-;
-; GISEL-LABEL: neg_range_int:
-; GISEL: // %bb.0:
-; GISEL-NEXT: mov w8, #-3 // =0xfffffffd
-; GISEL-NEXT: cmp w0, w2
-; GISEL-NEXT: ccmp w1, w8, #4, lt
-; GISEL-NEXT: csel w0, w1, w0, gt
-; GISEL-NEXT: ret
+; CHECK-LABEL: neg_range_int:
+; CHECK: // %bb.0:
+; CHECK-NEXT: cmp w0, w2
+; CHECK-NEXT: ccmn w1, #3, #4, lt
+; CHECK-NEXT: csel w0, w1, w0, gt
+; CHECK-NEXT: ret
%cmp = icmp sgt i32 %b, -3
%cmp1 = icmp slt i32 %a, %c
%or.cond = and i1 %cmp, %cmp1
@@ -267,5 +258,3 @@ define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) {
ret i32 %retval.0
}
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
More information about the llvm-commits
mailing list