Skip to content

[AArch64][GISel] Signed comparison using CMN is safe when the subtraction is nsw #150480

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

AZero13
Copy link
Contributor

@AZero13 AZero13 commented Jul 24, 2025

#141993 but for GISel, though for LHS, we now do the inverse compare, something that SelDAG does not do as of now but I will do in a future patch.

@llvmbot
Copy link
Member

llvmbot commented Jul 24, 2025

@llvm/pr-subscribers-llvm-globalisel

@llvm/pr-subscribers-backend-aarch64

Author: AZero13 (AZero13)

Changes

#141993 but for GISel, though for LHS, we now do the inverse compare, something that SelDAG does not do as of now but I will do in a future patch.


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

3 Files Affected:

  • (modified) llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp (+3-1)
  • (modified) llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp (+25-17)
  • (modified) llvm/test/CodeGen/AArch64/cmp-to-cmn.ll (+316-121)
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp b/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp
index 0b798509c26da..1a1507512c899 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64GlobalISelUtils.cpp
@@ -50,8 +50,10 @@ bool AArch64GISelUtils::isCMN(const MachineInstr *MaybeSub,
   //
   // %sub = G_SUB 0, %y
   // %cmp = G_ICMP eq/ne, %z, %sub
+  // or with signed comparisons with the no-signed-wrap flag set
   if (!MaybeSub || MaybeSub->getOpcode() != TargetOpcode::G_SUB ||
-      !CmpInst::isEquality(Pred))
+      (!CmpInst::isEquality(Pred) &&
+       !(CmpInst::isSigned(Pred) && MaybeSub->getFlag(MachineInstr::NoSWrap))))
     return false;
   auto MaybeZero =
       getIConstantVRegValWithLookThrough(MaybeSub->getOperand(1).getReg(), MRI);
diff --git a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
index 1381a9b70df87..61c1c84fbb4f0 100644
--- a/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/GISel/AArch64InstructionSelector.cpp
@@ -2506,12 +2506,12 @@ bool AArch64InstructionSelector::earlySelect(MachineInstr &I) {
         return false;
     }
     auto &PredOp = Cmp->getOperand(1);
-    auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
-    const AArch64CC::CondCode InvCC =
-        changeICMPPredToAArch64CC(CmpInst::getInversePredicate(Pred));
     MIB.setInstrAndDebugLoc(I);
     emitIntegerCompare(/*LHS=*/Cmp->getOperand(2),
                        /*RHS=*/Cmp->getOperand(3), PredOp, MIB);
+    auto Pred = static_cast<CmpInst::Predicate>(PredOp.getPredicate());
+    const AArch64CC::CondCode InvCC =
+        changeICMPPredToAArch64CC(CmpInst::getInversePredicate(Pred));
     emitCSINC(/*Dst=*/AddDst, /*Src =*/AddLHS, /*Src2=*/AddLHS, InvCC, MIB);
     I.eraseFromParent();
     return true;
@@ -3574,10 +3574,10 @@ bool AArch64InstructionSelector::select(MachineInstr &I) {
       return false;
     }
 
+    emitIntegerCompare(I.getOperand(2), I.getOperand(3), I.getOperand(1), MIB);
     auto Pred = static_cast<CmpInst::Predicate>(I.getOperand(1).getPredicate());
     const AArch64CC::CondCode InvCC =
         changeICMPPredToAArch64CC(CmpInst::getInversePredicate(Pred));
-    emitIntegerCompare(I.getOperand(2), I.getOperand(3), I.getOperand(1), MIB);
     emitCSINC(/*Dst=*/I.getOperand(0).getReg(), /*Src1=*/AArch64::WZR,
               /*Src2=*/AArch64::WZR, InvCC, MIB);
     I.eraseFromParent();
@@ -5096,11 +5096,11 @@ bool AArch64InstructionSelector::tryOptSelect(GSelect &I) {
 
   AArch64CC::CondCode CondCode;
   if (CondOpc == TargetOpcode::G_ICMP) {
+    emitIntegerCompare(CondDef->getOperand(2), CondDef->getOperand(3),
+                       CondDef->getOperand(1), MIB);
     auto Pred =
         static_cast<CmpInst::Predicate>(CondDef->getOperand(1).getPredicate());
     CondCode = changeICMPPredToAArch64CC(Pred);
-    emitIntegerCompare(CondDef->getOperand(2), CondDef->getOperand(3),
-                       CondDef->getOperand(1), MIB);
   } else {
     // Get the condition code for the select.
     auto Pred =
@@ -5148,18 +5148,7 @@ MachineInstr *AArch64InstructionSelector::tryFoldIntegerCompare(
   MachineInstr *LHSDef = getDefIgnoringCopies(LHS.getReg(), MRI);
   MachineInstr *RHSDef = getDefIgnoringCopies(RHS.getReg(), MRI);
   auto P = static_cast<CmpInst::Predicate>(Predicate.getPredicate());
-  // Given this:
-  //
-  // x = G_SUB 0, y
-  // G_ICMP x, z
-  //
-  // Produce this:
-  //
-  // cmn y, z
-  if (isCMN(LHSDef, P, MRI))
-    return emitCMN(LHSDef->getOperand(2), RHS, MIRBuilder);
 
-  // Same idea here, but with the RHS of the compare instead:
   //
   // Given this:
   //
@@ -5171,6 +5160,25 @@ MachineInstr *AArch64InstructionSelector::tryFoldIntegerCompare(
   // cmn z, y
   if (isCMN(RHSDef, P, MRI))
     return emitCMN(LHS, RHSDef->getOperand(2), MIRBuilder);
+  
+  // Same idea here, but with the LHS of the compare instead:
+  // Given this:
+  //
+  // x = G_SUB 0, y
+  // G_ICMP x, z
+  //
+  // Produce this:
+  //
+  // cmn y, z
+  // But be careful! We need to swap the predicate!
+  if (isCMN(LHSDef, P, MRI)) {
+    if (!CmpInst::isEquality(P)) {
+      P = CmpInst::getSwappedPredicate(P);
+      Predicate = MachineOperand::CreatePredicate(P);
+    }
+    return emitCMN(LHSDef->getOperand(2), RHS, MIRBuilder);
+  }
+
 
   // Given this:
   //
diff --git a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
index 5765e0acae269..a48e656dd2edd 100644
--- a/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
+++ b/llvm/test/CodeGen/AArch64/cmp-to-cmn.ll
@@ -1,14 +1,21 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
-; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,SDISEL
+; RUN: llc -mtriple=aarch64-unknown-linux-gnu < %s -global-isel | FileCheck %s --check-prefixes=CHECK,GISEL
 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
 target triple = "arm64"
 
 define i1 @test_EQ_IllEbT(i64 %a, i64 %b) {
-; CHECK-LABEL: test_EQ_IllEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x0, x1
-; CHECK-NEXT:    cset w0, eq
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_EQ_IllEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x0, x1
+; SDISEL-NEXT:    cset w0, eq
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_EQ_IllEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    cmn x1, x0
+; GISEL-NEXT:    cset w0, eq
+; GISEL-NEXT:    ret
 entry:
   %add = sub i64 0, %b
   %cmp = icmp eq i64 %add, %a
@@ -16,11 +23,19 @@ entry:
 }
 
 define i1 @test_EQ_IliEbT(i64 %a, i32 %b) {
-; CHECK-LABEL: test_EQ_IliEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x0, w1, sxtw
-; CHECK-NEXT:    cset w0, eq
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_EQ_IliEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x0, w1, sxtw
+; SDISEL-NEXT:    cset w0, eq
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_EQ_IliEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    // kill: def $w1 killed $w1 def $x1
+; GISEL-NEXT:    sxtw x8, w1
+; GISEL-NEXT:    cmn x8, x0
+; GISEL-NEXT:    cset w0, eq
+; GISEL-NEXT:    ret
 entry:
   %conv = sext i32 %b to i64
   %add = sub i64 0, %a
@@ -55,11 +70,19 @@ entry:
 }
 
 define i1 @test_EQ_IilEbT(i32 %a, i64 %b) {
-; CHECK-LABEL: test_EQ_IilEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x1, w0, sxtw
-; CHECK-NEXT:    cset w0, eq
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_EQ_IilEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x1, w0, sxtw
+; SDISEL-NEXT:    cset w0, eq
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_EQ_IilEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    // kill: def $w0 killed $w0 def $x0
+; GISEL-NEXT:    sxtw x8, w0
+; GISEL-NEXT:    cmn x8, x1
+; GISEL-NEXT:    cset w0, eq
+; GISEL-NEXT:    ret
 entry:
   %conv = sext i32 %a to i64
   %add = sub i64 0, %b
@@ -68,11 +91,17 @@ entry:
 }
 
 define i1 @test_EQ_IiiEbT(i32 %a, i32 %b) {
-; CHECK-LABEL: test_EQ_IiiEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn w0, w1
-; CHECK-NEXT:    cset w0, eq
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_EQ_IiiEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn w0, w1
+; SDISEL-NEXT:    cset w0, eq
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_EQ_IiiEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    cmn w1, w0
+; GISEL-NEXT:    cset w0, eq
+; GISEL-NEXT:    ret
 entry:
   %add = sub i32 0, %b
   %cmp = icmp eq i32 %add, %a
@@ -218,11 +247,17 @@ entry:
 }
 
 define i1 @test_NE_IllEbT(i64 %a, i64 %b) {
-; CHECK-LABEL: test_NE_IllEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x0, x1
-; CHECK-NEXT:    cset w0, ne
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_NE_IllEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x0, x1
+; SDISEL-NEXT:    cset w0, ne
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_NE_IllEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    cmn x1, x0
+; GISEL-NEXT:    cset w0, ne
+; GISEL-NEXT:    ret
 entry:
   %add = sub i64 0, %b
   %cmp = icmp ne i64 %add, %a
@@ -230,11 +265,19 @@ entry:
 }
 
 define i1 @test_NE_IliEbT(i64 %a, i32 %b) {
-; CHECK-LABEL: test_NE_IliEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x0, w1, sxtw
-; CHECK-NEXT:    cset w0, ne
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_NE_IliEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x0, w1, sxtw
+; SDISEL-NEXT:    cset w0, ne
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_NE_IliEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    // kill: def $w1 killed $w1 def $x1
+; GISEL-NEXT:    sxtw x8, w1
+; GISEL-NEXT:    cmn x8, x0
+; GISEL-NEXT:    cset w0, ne
+; GISEL-NEXT:    ret
 entry:
   %conv = sext i32 %b to i64
   %add = sub i64 0, %a
@@ -269,11 +312,19 @@ entry:
 }
 
 define i1 @test_NE_IilEbT(i32 %a, i64 %b) {
-; CHECK-LABEL: test_NE_IilEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn x1, w0, sxtw
-; CHECK-NEXT:    cset w0, ne
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_NE_IilEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn x1, w0, sxtw
+; SDISEL-NEXT:    cset w0, ne
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_NE_IilEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    // kill: def $w0 killed $w0 def $x0
+; GISEL-NEXT:    sxtw x8, w0
+; GISEL-NEXT:    cmn x8, x1
+; GISEL-NEXT:    cset w0, ne
+; GISEL-NEXT:    ret
 entry:
   %conv = sext i32 %a to i64
   %add = sub i64 0, %b
@@ -282,11 +333,17 @@ entry:
 }
 
 define i1 @test_NE_IiiEbT(i32 %a, i32 %b) {
-; CHECK-LABEL: test_NE_IiiEbT:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    cmn w0, w1
-; CHECK-NEXT:    cset w0, ne
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: test_NE_IiiEbT:
+; SDISEL:       // %bb.0: // %entry
+; SDISEL-NEXT:    cmn w0, w1
+; SDISEL-NEXT:    cset w0, ne
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: test_NE_IiiEbT:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    cmn w1, w0
+; GISEL-NEXT:    cset w0, ne
+; GISEL-NEXT:    ret
 entry:
   %add = sub i32 0, %b
   %cmp = icmp ne i32 %add, %a
@@ -444,161 +501,281 @@ define i1 @cmn_large_imm(i32 %a) {
 }
 
 define i1 @almost_immediate_neg_slt(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_slt:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, le
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_slt:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, le
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_slt:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #4097 // =0x1001
+; GISEL-NEXT:    movk w8, #65281, lsl #16
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, lt
+; GISEL-NEXT:    ret
   %cmp = icmp slt i32 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_slt_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_slt_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, le
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_slt_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, le
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_slt_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-61439 // =0xffffffffffff1001
+; GISEL-NEXT:    movk x8, #65281, lsl #16
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, lt
+; GISEL-NEXT:    ret
   %cmp = icmp slt i64 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sge(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_sge:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, gt
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sge:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, gt
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sge:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #4097 // =0x1001
+; GISEL-NEXT:    movk w8, #65281, lsl #16
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, ge
+; GISEL-NEXT:    ret
   %cmp = icmp sge i32 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sge_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_sge_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, gt
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sge_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, gt
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sge_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-61439 // =0xffffffffffff1001
+; GISEL-NEXT:    movk x8, #65281, lsl #16
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, ge
+; GISEL-NEXT:    ret
   %cmp = icmp sge i64 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_uge(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_uge:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, hi
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_uge:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, hi
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_uge:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #4097 // =0x1001
+; GISEL-NEXT:    movk w8, #65281, lsl #16
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, hs
+; GISEL-NEXT:    ret
   %cmp = icmp uge i32 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_uge_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_uge_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, hi
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_uge_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, hi
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_uge_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-61439 // =0xffffffffffff1001
+; GISEL-NEXT:    movk x8, #65281, lsl #16
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, hs
+; GISEL-NEXT:    ret
   %cmp = icmp uge i64 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_ult(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_ult:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, ls
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_ult:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, ls
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_ult:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #4097 // =0x1001
+; GISEL-NEXT:    movk w8, #65281, lsl #16
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, lo
+; GISEL-NEXT:    ret
   %cmp = icmp ult i32 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_ult_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_ult_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4079, lsl #12 // =16707584
-; CHECK-NEXT:    cset w0, ls
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_ult_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4079, lsl #12 // =16707584
+; SDISEL-NEXT:    cset w0, ls
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_ult_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-61439 // =0xffffffffffff1001
+; GISEL-NEXT:    movk x8, #65281, lsl #16
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, lo
+; GISEL-NEXT:    ret
   %cmp = icmp ult i64 %x, -16707583
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sle(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_sle:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, lt
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sle:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, lt
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sle:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #-16773121 // =0xff000fff
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, le
+; GISEL-NEXT:    ret
   %cmp = icmp sle i32 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sle_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_sle_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, lt
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sle_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, lt
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sle_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-16773121 // =0xffffffffff000fff
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, le
+; GISEL-NEXT:    ret
   %cmp = icmp sle i64 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sgt(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_sgt:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, ge
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sgt:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, ge
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sgt:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #-16773121 // =0xff000fff
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, gt
+; GISEL-NEXT:    ret
   %cmp = icmp sgt i32 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_sgt_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_sgt_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, ge
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_sgt_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, ge
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_sgt_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-16773121 // =0xffffffffff000fff
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, gt
+; GISEL-NEXT:    ret
   %cmp = icmp sgt i64 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_ule(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_ule:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, lo
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_ule:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, lo
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_ule:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov w8, #-16773121 // =0xff000fff
+; GISEL-NEXT:    cmp w0, w8
+; GISEL-NEXT:    cset w0, ls
+; GISEL-NEXT:    ret
   %cmp = icmp ule i32 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_ule_64(i64 %x) {
-; CHECK-LABEL: almost_immediate_neg_ule_64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn x0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, lo
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_ule_64:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn x0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, lo
+; SDISEL-NEXT:    ret
+;
+; GISEL-LABEL: almost_immediate_neg_ule_64:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mov x8, #-16773121 // =0xffffffffff000fff
+; GISEL-NEXT:    cmp x0, x8
+; GISEL-NEXT:    cset w0, ls
+; GISEL-NEXT:    ret
   %cmp = icmp ule i64 %x, -16773121
   ret i1 %cmp
 }
 
 define i1 @almost_immediate_neg_ugt(i32 %x) {
-; CHECK-LABEL: almost_immediate_neg_ugt:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    cmn w0, #4095, lsl #12 // =16773120
-; CHECK-NEXT:    cset w0, hs
-; CHECK-NEXT:    ret
+; SDISEL-LABEL: almost_immediate_neg_ugt:
+; SDISEL:       // %bb.0:
+; SDISEL-NEXT:    cmn w0, #4095, lsl #12 // =16773120
+; SDISEL-NEXT:    cset w0, hs
+; SDISEL-NE...
[truncated]

Copy link

github-actions bot commented Jul 24, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@AZero13 AZero13 force-pushed the gisel-cmn branch 2 times, most recently from 9db10a3 to 56216f1 Compare July 24, 2025 18:31
…tion is nsw

llvm#141993 but for GISel, though for LHS, we now do the inverse compare, something that SelDAG does not do as of now but I will do in a future patch.
@AZero13
Copy link
Contributor Author

AZero13 commented Jul 25, 2025

@davemgreen thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants