[llvm] [GlobalISel] Add `sub(-1, x) -> (xor x, -1)` from SelectionDAG (PR #181014)

Osman Yasar via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 05:35:23 PDT 2026


https://github.com/osmanyasar05 updated https://github.com/llvm/llvm-project/pull/181014

>From 5fe279d14a529dedbff7a22d94fc5bd1dbf91a4b Mon Sep 17 00:00:00 2001
From: osmanyasar05 <osmanyas05 at gmail.com>
Date: Wed, 11 Feb 2026 20:50:53 +0000
Subject: [PATCH 1/5] add rewrite

---
 .../include/llvm/Target/GlobalISel/Combine.td |  8 ++++++-
 .../AArch64/GlobalISel/sub_minus_one.mir      | 22 +++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index f5c940bffc8fb..ba3ffffbbf7a0 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -359,6 +359,12 @@ def sub_to_add : GICombineRule<
          [{ return Helper.matchCombineSubToAdd(*${mi}, ${matchinfo}); }]),
   (apply [{ Helper.applyBuildFnNoErase(*${mi}, ${matchinfo}); }])>;
 
+// (sub -1, x) -> (xor x, -1)
+def sub_minus_one : GICombineRule<
+  (defs root:$root),
+  (match (G_SUB $root, -1, $op1)),
+  (apply (G_XOR $root, $op1, -1))>;
+
 // shl ([asz]ext x), y => zext (shl x, y), if shift does not overflow int
 def reduce_shl_of_extend_matchdata : GIDefMatchData<"RegisterImmPair">;
 def reduce_shl_of_extend : GICombineRule<
@@ -2296,7 +2302,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
     simplify_neg_minmax, combine_concat_vector,
     sext_trunc, zext_trunc, prefer_sign_combines, shuffle_combines,
     combine_use_vector_truncate, merge_combines, overflow_combines, 
-    truncsat_combines, lshr_of_trunc_of_lshr, ctls_combines, add_shift]>;
+    truncsat_combines, lshr_of_trunc_of_lshr, ctls_combines, add_shift, sub_minus_one]>;
 
 // A combine group used to for prelegalizer combiners at -O0. The combines in
 // this group have been selected based on experiments to balance code size and
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir b/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir
new file mode 100644
index 0000000000000..3a5ea7947b5d8
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir
@@ -0,0 +1,22 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner %s -o - | FileCheck %s
+
+---
+name:   sub_minus_one
+body:             |
+  bb.0:
+    liveins: $w0, $w1
+
+    ; CHECK-LABEL: name: sub_minus_one
+    ; CHECK: liveins: $w0, $w1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %c1:_(s64) = G_CONSTANT i64 -1
+    ; CHECK-NEXT: %sub:_(s64) = G_XOR %a, %c1
+    ; CHECK-NEXT: $x0 = COPY %sub(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %c1:_(s64) = G_CONSTANT i64 -1
+    %sub:_(s64) = G_SUB %c1, %a
+    $x0 = COPY %sub
+    RET_ReallyLR implicit $x0

>From 89c35f1a92e0f76e499bc3b6d7981a4dddd04491 Mon Sep 17 00:00:00 2001
From: osmanyasar05 <osmanyas05 at gmail.com>
Date: Wed, 11 Feb 2026 21:33:52 +0000
Subject: [PATCH 2/5] modify test

---
 .../CodeGen/AArch64/neon-bitwise-instructions.ll   | 14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
index 01aea72d77114..cf655eadf2df2 100644
--- a/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
+++ b/llvm/test/CodeGen/AArch64/neon-bitwise-instructions.ll
@@ -2848,15 +2848,11 @@ define <8 x i16> @pr149380(<4 x i16> %u1, <1 x i64> %u2, <8 x i16> %vqshlu_n169)
 ;
 ; CHECK-GI-LABEL: pr149380:
 ; CHECK-GI:       // %bb.0: // %entry
-; CHECK-GI-NEXT:    movi v0.2d, #0xffffffffffffffff
-; CHECK-GI-NEXT:    neg v1.8h, v2.8h
-; CHECK-GI-NEXT:    movi v3.8h, #1
-; CHECK-GI-NEXT:    neg v1.8h, v1.8h
-; CHECK-GI-NEXT:    sub v0.8h, v0.8h, v2.8h
-; CHECK-GI-NEXT:    and v1.16b, v1.16b, v2.16b
-; CHECK-GI-NEXT:    and v0.16b, v0.16b, v3.16b
-; CHECK-GI-NEXT:    orr v0.16b, v1.16b, v0.16b
-; CHECK-GI-NEXT:    sqadd v0.8h, v3.8h, v0.8h
+; CHECK-GI-NEXT:    neg v0.8h, v2.8h
+; CHECK-GI-NEXT:    movi v1.8h, #1
+; CHECK-GI-NEXT:    neg v0.8h, v0.8h
+; CHECK-GI-NEXT:    bif v0.16b, v1.16b, v2.16b
+; CHECK-GI-NEXT:    sqadd v0.8h, v1.8h, v0.8h
 ; CHECK-GI-NEXT:    ret
 entry:
   %mul.i = mul <8 x i16> %vqshlu_n169, < i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1 >

>From 43dfd59a2a4207e86432190986574798f5efc83b Mon Sep 17 00:00:00 2001
From: osmanyasar05 <osmanyas05 at gmail.com>
Date: Fri, 20 Feb 2026 16:28:59 +0000
Subject: [PATCH 3/5] vector tests, ll test

---
 .../AArch64/GlobalISel/sub_minus_one.mir      | 22 -------------------
 1 file changed, 22 deletions(-)
 delete mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir b/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir
deleted file mode 100644
index 3a5ea7947b5d8..0000000000000
--- a/llvm/test/CodeGen/AArch64/GlobalISel/sub_minus_one.mir
+++ /dev/null
@@ -1,22 +0,0 @@
-# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
-# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner %s -o - | FileCheck %s
-
----
-name:   sub_minus_one
-body:             |
-  bb.0:
-    liveins: $w0, $w1
-
-    ; CHECK-LABEL: name: sub_minus_one
-    ; CHECK: liveins: $w0, $w1
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %c1:_(s64) = G_CONSTANT i64 -1
-    ; CHECK-NEXT: %sub:_(s64) = G_XOR %a, %c1
-    ; CHECK-NEXT: $x0 = COPY %sub(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %c1:_(s64) = G_CONSTANT i64 -1
-    %sub:_(s64) = G_SUB %c1, %a
-    $x0 = COPY %sub
-    RET_ReallyLR implicit $x0

>From 8868743db7acfe3f82cdc3656856c1bb7db9390c Mon Sep 17 00:00:00 2001
From: osmanyasar05 <osmanyas05 at gmail.com>
Date: Fri, 20 Feb 2026 16:32:28 +0000
Subject: [PATCH 4/5] tests

---
 .../CodeGen/AArch64/GlobalISel/combine-sub.ll | 15 ++++++
 .../AArch64/GlobalISel/combine-sub.mir        | 46 +++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.mir

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
new file mode 100644
index 0000000000000..33b9b22699356
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
@@ -0,0 +1,15 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-unknown-unknown -global-isel | FileCheck %s --check-prefixes=GISEL
+
+; fold (sub -1, a) -> (xor a, -1)
+define i64 @sub_minus_one(i64 %a) {
+; GISEL-LABEL: sub_minus_one:
+; GISEL:       // %bb.0: // %entry
+; GISEL-NEXT:    mvn x0, x0
+; GISEL-NEXT:    ret
+entry:
+; fold (A - (0 - B)) to (A + B)
+  %sub1 = sub i64 -1, %a
+  ret i64 %sub1
+}
+
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.mir
new file mode 100644
index 0000000000000..57e5c253a7b6a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.mir
@@ -0,0 +1,46 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
+# RUN: llc -mtriple aarch64 -run-pass=aarch64-prelegalizer-combiner %s -o - | FileCheck %s
+
+---
+name:   sub_minus_one
+body:             |
+  bb.0:
+    liveins: $w0, $w1
+
+    ; CHECK-LABEL: name: sub_minus_one
+    ; CHECK: liveins: $w0, $w1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %c1:_(s64) = G_CONSTANT i64 -1
+    ; CHECK-NEXT: %sub:_(s64) = G_XOR %a, %c1
+    ; CHECK-NEXT: $x0 = COPY %sub(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %c1:_(s64) = G_CONSTANT i64 -1
+    %sub:_(s64) = G_SUB %c1, %a
+    $x0 = COPY %sub
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   sub_minus_one_vector
+body:             |
+  bb.0:
+    liveins: $x0, $x1
+
+    ; CHECK-LABEL: name: sub_minus_one_vector
+    ; CHECK: liveins: $x0, $x1
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(<4 x s16>) = COPY $x0
+    ; CHECK-NEXT: %neg_one:_(s16) = G_CONSTANT i16 -1
+    ; CHECK-NEXT: %c1:_(<4 x s16>) = G_BUILD_VECTOR %neg_one(s16), %neg_one(s16), %neg_one(s16), %neg_one(s16)
+    ; CHECK-NEXT: %sub:_(<4 x s16>) = G_XOR %a, %c1
+    ; CHECK-NEXT: $x0 = COPY %sub(<4 x s16>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(<4 x s16>) = COPY $x0
+    %neg_one:_(s16) = G_CONSTANT i16 -1
+    %c1:_(<4 x s16>) = G_BUILD_VECTOR %neg_one(s16), %neg_one(s16), %neg_one(s16), %neg_one(s16)
+    %sub:_(<4 x s16>) = G_SUB %c1, %a
+    $x0 = COPY %sub
+    RET_ReallyLR implicit $x0
+...

>From 7486a853814c8ba4aadd268fecff6399d3a5f460 Mon Sep 17 00:00:00 2001
From: osmanyasar05 <osmanyas05 at gmail.com>
Date: Wed, 25 Mar 2026 20:59:56 +0000
Subject: [PATCH 5/5] add .ll vector tests

---
 llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
index 380f37e64846a..211c68966ad51 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-sub.ll
@@ -13,6 +13,15 @@ entry:
   ret i64 %sub1
 }
 
+define <8 x i16> @sub_minus_one_vec(<8 x i16> %x) {
+; GISEL-LABEL: sub_minus_one_vec:
+; GISEL:       // %bb.0:
+; GISEL-NEXT:    mvn v0.16b, v0.16b
+; GISEL-NEXT:    ret
+  %sub1 = sub <8 x i16> <i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1, i16 -1>, %x
+  ret <8 x i16> %sub1
+}
+
 define i64 @sub_one_from_sub(i64 %a, i64 %b) {
 ; GISEL-LABEL: sub_one_from_sub:
 ; GISEL:       // %bb.0: // %entry



More information about the llvm-commits mailing list