[llvm] [AArch64] Use ccmn to compare negative imm constants (PR #95825)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 17 11:39:04 PDT 2024


https://github.com/AtariDreams updated https://github.com/llvm/llvm-project/pull/95825

>From 990b8ff65bb744172f980bfe19245a113fc190a2 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 70792cef37384f061555fb42a0a06c93168117cd 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
---
 .../AArch64/GISel/AArch64InstructionSelector.cpp    | 13 ++++++++++---
 llvm/test/CodeGen/AArch64/arm64-ccmp.ll             |  3 +--
 llvm/test/CodeGen/AArch64/cmp-chains.ll             |  3 +--
 3 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 4a7c82b393c10..86dbe2037496d 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -4668,9 +4668,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 +4701,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.getSExtValue());
   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..7ca24f3eabdd0 100644
--- a/llvm/test/CodeGen/AArch64/cmp-chains.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-chains.ll
@@ -255,9 +255,8 @@ define i32 @neg_range_int(i32 %a, i32 %b, i32 %c) {
 ;
 ; 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:    ccmn w1, #3, #4, lt
 ; GISEL-NEXT:    csel w0, w1, w0, gt
 ; GISEL-NEXT:    ret
   %cmp = icmp sgt i32 %b, -3



More information about the llvm-commits mailing list