[llvm] [GIsel] import `(not (add X, -1)) -> (neg X)` to GlobalISel (PR #181640)

Luisa Cicolini via llvm-commits llvm-commits at lists.llvm.org
Thu Feb 19 10:49:09 PST 2026


https://github.com/luisacicolini updated https://github.com/llvm/llvm-project/pull/181640

>From 0aaa0801d8ae6cadc14b8e961a1ec7aba2e6c58f Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Mon, 16 Feb 2026 12:03:50 +0000
Subject: [PATCH 1/8] chore: rewrite

---
 .../CodeGen/GlobalISel/MachineIRBuilder.h     |  2 +-
 .../include/llvm/Target/GlobalISel/Combine.td |  8 +++++++
 .../AArch64/GlobalISel/combine-add.mir        | 22 +++++++++++++++++++
 .../AArch64/GlobalISel/combine-integer.mir    |  1 -
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 5114e979e58ea..7e3f11af779ae 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -2120,7 +2120,7 @@ class LLVM_ABI MachineIRBuilder {
                                 std::optional<unsigned> Flags = std::nullopt) {
     return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}, Flags);
   }
-
+  
   /// Build and insert \p Res = G_FABS \p Op0
   MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0,
                                 std::optional<unsigned> Flags = std::nullopt) {
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index f5c940bffc8fb..52312dc2b4603 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1946,6 +1946,13 @@ def APlusBMinusCPlusA : GICombineRule<
           (G_SUB $sub1, $B, $add1),
           (G_ADD $root, $A, $sub1)),
    (apply (G_SUB $root, $B, $C))>;
+   
+// fold (not (add X, -1)) -> (neg X)
+def NotAPlusNegOne: GICombineRule<
+   (defs root:$root),
+   (match (G_ADD $add, $A, -1),
+          (G_XOR $root, $add, -1)),
+   (apply (G_SUB $root, 0, $A))>;
 
 // fold (A+C1)-C2 -> A+(C1-C2)
 def APlusC1MinusC2: GICombineRule<
@@ -2008,6 +2015,7 @@ def integer_reassoc_combines: GICombineGroup<[
   AMinusBPlusBMinusC,
   APlusBMinusAplusC,
   APlusBMinusCPlusA,
+  NotAPlusNegOne,
   APlusC1MinusC2,
   C2MinusAPlusC1,
   AMinusC1MinusC2,
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
index 4656dbc4270de..3e2e031c8101a 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
@@ -514,3 +514,25 @@ body: |
     $x0 = COPY %mul
     RET_ReallyLR implicit $x0
 ...
+
+---
+name:            NotAPlusNegOne
+body: |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: NotAPlusNegOne
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %x:_(s64) = COPY $x0
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %xor:_(s64) = G_SUB [[C]], %x
+    ; CHECK-NEXT: $x0 = COPY %xor(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %x:_(s64) = COPY $x0
+    %neg_one:_(s64) = G_CONSTANT i64 -1
+    %add:_(s64) = G_ADD %x, %neg_one
+    %xor:_(s64) = G_XOR %add, %neg_one
+    $x0 = COPY %xor
+    RET_ReallyLR implicit $x0
+...
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index c9b24ad75ce27..9248bb995b3b6 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -412,4 +412,3 @@ body:             |
     %add:_(s64) = G_ADD %sub, %c2
     $x0 = COPY %add
     RET_ReallyLR implicit $x0
-

>From 726ae8ed8469ac38e5b243560a4e4eb50fbde711 Mon Sep 17 00:00:00 2001
From: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
Date: Mon, 16 Feb 2026 12:06:15 +0000
Subject: [PATCH 2/8] Apply suggestion from @luisacicolini

---
 llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 7e3f11af779ae..b554021f2899f 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -2120,7 +2120,6 @@ class LLVM_ABI MachineIRBuilder {
                                 std::optional<unsigned> Flags = std::nullopt) {
     return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}, Flags);
   }
-  
   /// Build and insert \p Res = G_FABS \p Op0
   MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0,
                                 std::optional<unsigned> Flags = std::nullopt) {

>From 2f6157f65864034114b344909f05a31e421159d2 Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Mon, 16 Feb 2026 12:07:12 +0000
Subject: [PATCH 3/8] chore: unwanted change

---
 llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 9248bb995b3b6..c9b24ad75ce27 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -412,3 +412,4 @@ body:             |
     %add:_(s64) = G_ADD %sub, %c2
     $x0 = COPY %add
     RET_ReallyLR implicit $x0
+

>From 8e7b77a7fcf0bf31ae09c5da7d104b5bd6079833 Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Mon, 16 Feb 2026 12:07:39 +0000
Subject: [PATCH 4/8] chore: unwanted change

---
 llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index b554021f2899f..7e3f11af779ae 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -2120,6 +2120,7 @@ class LLVM_ABI MachineIRBuilder {
                                 std::optional<unsigned> Flags = std::nullopt) {
     return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}, Flags);
   }
+  
   /// Build and insert \p Res = G_FABS \p Op0
   MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0,
                                 std::optional<unsigned> Flags = std::nullopt) {

>From 55efe738a184af0931215fa119bdee0ab9741751 Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Mon, 16 Feb 2026 12:08:39 +0000
Subject: [PATCH 5/8] chore: update

---
 llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
index 7e3f11af779ae..5114e979e58ea 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
@@ -2120,7 +2120,7 @@ class LLVM_ABI MachineIRBuilder {
                                 std::optional<unsigned> Flags = std::nullopt) {
     return buildInstr(TargetOpcode::G_FNEG, {Dst}, {Src0}, Flags);
   }
-  
+
   /// Build and insert \p Res = G_FABS \p Op0
   MachineInstrBuilder buildFAbs(const DstOp &Dst, const SrcOp &Src0,
                                 std::optional<unsigned> Flags = std::nullopt) {

>From 9b28c4a01c01d8f0f013612e8b3f2aa354683b50 Mon Sep 17 00:00:00 2001
From: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
Date: Mon, 16 Feb 2026 12:18:06 +0000
Subject: [PATCH 6/8] Update llvm/include/llvm/Target/GlobalISel/Combine.td

---
 llvm/include/llvm/Target/GlobalISel/Combine.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 52312dc2b4603..1133b12485608 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1947,7 +1947,7 @@ def APlusBMinusCPlusA : GICombineRule<
           (G_ADD $root, $A, $sub1)),
    (apply (G_SUB $root, $B, $C))>;
    
-// fold (not (add X, -1)) -> (neg X)
+// fold (not (add X, -1)) -> (sub 0, X)
 def NotAPlusNegOne: GICombineRule<
    (defs root:$root),
    (match (G_ADD $add, $A, -1),

>From afc2eb642a6c9a2ab711f024b35a4fc58ab7afe1 Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Thu, 19 Feb 2026 18:46:55 +0000
Subject: [PATCH 7/8] add oneUse check

---
 llvm/include/llvm/Target/GlobalISel/Combine.td | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 1133b12485608..ef6837b2d4b21 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1951,7 +1951,8 @@ def APlusBMinusCPlusA : GICombineRule<
 def NotAPlusNegOne: GICombineRule<
    (defs root:$root),
    (match (G_ADD $add, $A, -1),
-          (G_XOR $root, $add, -1)),
+          (G_XOR $root, $add, -1, 
+          [{ return MRI.hasOneNonDBGUse(${add}.getReg()) }])),
    (apply (G_SUB $root, 0, $A))>;
 
 // fold (A+C1)-C2 -> A+(C1-C2)

>From f1ad3ec83cb09d28ece713ee76808669ea830529 Mon Sep 17 00:00:00 2001
From: luisacicolini <luisacicolini at gmail.com>
Date: Thu, 19 Feb 2026 18:48:51 +0000
Subject: [PATCH 8/8] fix build and add one test

---
 .../include/llvm/Target/GlobalISel/Combine.td |  4 +--
 .../AArch64/GlobalISel/combine-add.mir        | 26 ++++++++++++++++++-
 2 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index ef6837b2d4b21..b05718c220dc1 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1951,8 +1951,8 @@ def APlusBMinusCPlusA : GICombineRule<
 def NotAPlusNegOne: GICombineRule<
    (defs root:$root),
    (match (G_ADD $add, $A, -1),
-          (G_XOR $root, $add, -1, 
-          [{ return MRI.hasOneNonDBGUse(${add}.getReg()) }])),
+          (G_XOR $root, $add, -1),
+          [{ return MRI.hasOneNonDBGUse(${add}.getReg()) }]),
    (apply (G_SUB $root, 0, $A))>;
 
 // fold (A+C1)-C2 -> A+(C1-C2)
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
index 3e2e031c8101a..79cc8d820abdf 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add.mir
@@ -494,7 +494,7 @@ body: |
     ; CHECK-NEXT: %n:_(s64) = COPY $x2
     ; CHECK-NEXT: %z:_(s64) = COPY $x3
     ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %neg_y:_(s64) = G_SUB %zero, %y
+    ; CHECK-NEXT: %neg_y:_(s64) = G_SUB %zegit ro, %y
     ; CHECK-NEXT: %shl_neg:_(s64) = G_SHL %neg_y, %n(s64)
     ; CHECK-NEXT: %dst:_(s64) = G_ADD %shl_neg, %x
     ; CHECK-NEXT: %other:_(s64) = G_MUL %shl_neg, %z
@@ -536,3 +536,27 @@ body: |
     $x0 = COPY %xor
     RET_ReallyLR implicit $x0
 ...
+
+
+---
+name:            NotAPlusNegOne_multi
+body: |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: NotAPlusNegOne_multi
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %x:_(s64) = COPY $x0
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %xor:_(s64) = G_SUB [[C]], %x
+    ; CHECK-NEXT: $x0 = COPY %xor(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %x:_(s64) = COPY $x0
+    %neg_one:_(s64) = G_CONSTANT i64 -1
+    %add:_(s64) = G_ADD %x, %neg_one
+    %xor:_(s64) = G_XOR %add, %neg_one
+    %mul:_(s64) = G_MUL %xor, %mul
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0
+...



More information about the llvm-commits mailing list