[llvm] [GIsel] import min/max rewrites (PR #188267)

Luisa Cicolini via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 11 02:07:15 PDT 2026


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

>From 5209235f7b8721011452de4348e361b7e78903b5 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 24 Mar 2026 15:16:34 +0000
Subject: [PATCH 01/33] chore: smax

---
 .../include/llvm/Target/GlobalISel/Combine.td | 14 ++++-
 .../AArch64/GlobalISel/combine-integer.mir    | 56 +++++++++++++++++++
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 959cd8b083d52..4c1879e82c9cf 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2044,6 +2044,17 @@ def AMinusC1PlusC2: GICombineRule<
    [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]),
    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
+// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
+def SubSmaxSub: GICombineRule<
+   (defs root:$root),
+   (match (G_SUB $sub, 0, $A),
+          (G_SMAX $max, $A, $sub),
+          (G_SUB $root, 0, $max):$root, 
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) 
+              && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+   (apply (G_SUB $sub1, 0, $A), 
+          (G_SMIN $root, $A, $sub1))>;
+   
 def integer_reassoc_combines: GICombineGroup<[
   APlusBMinusCMinusB,
   AMinusBMinusCMinusC,
@@ -2061,7 +2072,8 @@ def integer_reassoc_combines: GICombineGroup<[
   C2MinusAPlusC1,
   AMinusC1MinusC2,
   C1Minus2MinusC2,
-  AMinusC1PlusC2
+  AMinusC1PlusC2,
+  SubSmaxSub
 ]>;
 
 // fold (A+(shl (0-B), C)) -> (A-(shl B, C))
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 1100997321a09..8afdb96a0c97a 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -7,6 +7,7 @@ name:   APlusBMinusCMinusB
 body:             |
   bb.0:
     liveins: $x0, $x1, $x2
+
     ; CHECK-LABEL: name: APlusBMinusCMinusB
     ; CHECK: liveins: $x0, $x1, $x2
     ; CHECK-NEXT: {{  $}}
@@ -496,3 +497,58 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
+
+...
+---
+name:   ASubMax
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubMax
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, [[SUB]]
+    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0

>From 49a1378906d55b0444a75c811346e1112567b730 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 24 Mar 2026 15:31:04 +0000
Subject: [PATCH 02/33] umax conflicts with smax

---
 llvm/include/llvm/Target/GlobalISel/Combine.td     | 14 +++++++++++++-
 .../CodeGen/AArch64/GlobalISel/combine-integer.mir |  1 +
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 4c1879e82c9cf..998828a936ef3 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2054,6 +2054,17 @@ def SubSmaxSub: GICombineRule<
               && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
    (apply (G_SUB $sub1, 0, $A), 
           (G_SMIN $root, $A, $sub1))>;
+          
+// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
+def SubUmaxSub: GICombineRule<
+   (defs root:$root),
+   (match (G_SUB $sub, 0, $A),
+          (G_UMAX $max, $A, $sub),
+          (G_SUB $root, 0, $max):$root, 
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) 
+              && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+   (apply (G_SUB $sub1, 0, $A), 
+          (G_UMIN $root, $A, $sub1))>;
    
 def integer_reassoc_combines: GICombineGroup<[
   APlusBMinusCMinusB,
@@ -2073,7 +2084,8 @@ def integer_reassoc_combines: GICombineGroup<[
   AMinusC1MinusC2,
   C1Minus2MinusC2,
   AMinusC1PlusC2,
-  SubSmaxSub
+  SubSmaxSub, 
+  SubUmaxSub
 ]>;
 
 // fold (A+(shl (0-B), C)) -> (A-(shl B, C))
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 8afdb96a0c97a..d74c289aea4c9 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -552,3 +552,4 @@ body:             |
     %mul:_(s64) = G_MUL %max, %sub2
     $x0 = COPY %mul
     RET_ReallyLR implicit $x0
+

>From 652afe34cde3d9d21afd6f08e792109360424be8 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 9 Apr 2026 12:39:42 +0100
Subject: [PATCH 03/33] still breaks

---
 llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index c63ae08456172..cdc3afc3cd7e8 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -573,7 +573,9 @@ body:             |
     %mul:_(s64) = G_MUL %max, %sub2
     $x0 = COPY %mul
     RET_ReallyLR implicit $x0
-
+    
+...
+---
 name:   AMinusZeroMinusB_BV
 body:             |
   bb.0:

>From aa3f57d04cc5e840457d33ddcc7308e263342e1a Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 09:59:14 +0100
Subject: [PATCH 04/33] remove tests to figure out what is wrong

---
 .../AArch64/GlobalISel/combine-integer.mir    | 54 -------------------
 1 file changed, 54 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index cdc3afc3cd7e8..f77ab013e20f2 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -7,7 +7,6 @@ name:   APlusBMinusCMinusB
 body:             |
   bb.0:
     liveins: $x0, $x1, $x2
-
     ; CHECK-LABEL: name: APlusBMinusCMinusB
     ; CHECK: liveins: $x0, $x1, $x2
     ; CHECK-NEXT: {{  $}}
@@ -497,30 +496,6 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
-
-...
----
-name:   ASubMax
-body:             |
-  bb.0:
-    liveins: $x0
-
-
-    ; CHECK-LABEL: name: ASubMax
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, [[SUB]]
-    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_SMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
 ...
 ---
 name:   AMinusZeroMinusB
@@ -545,35 +520,6 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
-...
----
-name:   ASubMaxOneUse
-body:             |
-  bb.0:
-    liveins: $x0
-
-
-    ; CHECK-LABEL: name: ASubMaxOneUse
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
-    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
-    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
-    ; CHECK-NEXT: $x0 = COPY %mul(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_SMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    %mul:_(s64) = G_MUL %max, %sub2
-    $x0 = COPY %mul
-    RET_ReallyLR implicit $x0
-    
 ...
 ---
 name:   AMinusZeroMinusB_BV

>From f9a520722652ca95d5af0bc9f23f9de66cdee1de Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:29:21 +0100
Subject: [PATCH 05/33] test

---
 .../llvm/CodeGen/GlobalISel/CombinerHelper.h  |  3 ++
 .../include/llvm/Target/GlobalISel/Combine.td | 15 ++++---
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 43 +++++++++++++++++++
 .../AArch64/GlobalISel/combine-integer.mir    | 22 ++++++++++
 4 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 365bbaacfe055..29abb162d1834 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -1021,6 +1021,9 @@ class CombinerHelper {
   bool matchFoldAMinusC1PlusC2(const MachineInstr &MI,
                                BuildFnTy &MatchInfo) const;
 
+  bool matchFoldSubSmaxSub(const MachineInstr &MI,
+                               BuildFnTy &MatchInfo) const;
+                               
   bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
                      BuildFnTy &MatchInfo) const;
 
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 9717763e30a7a..16fdc926102b7 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2074,14 +2074,12 @@ def AMinusC1PlusC2: GICombineRule<
 
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubSmaxSub: GICombineRule<
-   (defs root:$root),
+   (defs root:$root, build_fn_matchinfo:$matchinfo),
    (match (G_SUB $sub, 0, $A),
           (G_SMAX $max, $A, $sub),
           (G_SUB $root, 0, $max):$root, 
-          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) 
-              && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
-   (apply (G_SUB $sub1, 0, $A), 
-          (G_SMIN $root, $A, $sub1))>;
+          [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
+   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
           
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubUmaxSub: GICombineRule<
@@ -2114,8 +2112,11 @@ def integer_reassoc_combines: GICombineGroup<[
   AMinusC1MinusC2,
   C1Minus2MinusC2,
   AMinusC1PlusC2,
+]>;
+
+def max_min_combines: GICombineGroup<[
   SubSmaxSub, 
-  SubUmaxSub
+  // SubUmaxSub
 ]>;
 
 // fold (A+(shl (0-B), C)) -> (A-(shl B, C))
@@ -2400,7 +2401,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
     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, sub_one_from_sub,
-    binop_with_neg, sub_minus_one]>;
+    binop_with_neg, sub_minus_one, max_min_combines]>;
 
 // 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/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 177170575fe07..db99b972eea34 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -8374,6 +8374,49 @@ bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
   return true;
 }
 
+bool CombinerHelper::matchFoldSubSmaxSub(const MachineInstr &MI,
+                                         BuildFnTy &MatchInfo) const {
+  // fold (sub 0, (smax X, (sub 0, X))) --> (smin X, (sub 0, X))
+  const GSub *Sub1 = cast<GSub>(&MI);
+
+  MachineInstr *MaxMI = MRI.getVRegDef(Sub1->getRHSReg());
+  if (!MaxMI || MaxMI->getOpcode() != TargetOpcode::G_SMAX)
+    return false;
+
+  MachineInstr *Sub2MI = MRI.getVRegDef(MaxMI->getOperand(2).getReg());
+  if (!Sub2MI || Sub2MI->getOpcode() != TargetOpcode::G_SUB)
+    return false;
+
+  // Verify Sub1 LHS == 0
+  auto MaybeCst1 = getIConstantVRegValWithLookThrough(Sub1->getLHSReg(), MRI);
+  if (!MaybeCst1 || !MaybeCst1->Value.isZero())
+    return false;
+
+  // Verify Sub2 LHS == 0
+  auto MaybeCst2 = getIConstantVRegValWithLookThrough(
+      Sub2MI->getOperand(1).getReg(), MRI);
+  if (!MaybeCst2 || !MaybeCst2->Value.isZero())
+    return false;
+
+  // Verify X is the same register in both smax and the inner sub
+  Register X = MaxMI->getOperand(1).getReg();
+  if (X != Sub2MI->getOperand(2).getReg())
+    return false;
+
+  if (!MRI.hasOneNonDBGUse(Sub2MI->getOperand(0).getReg()))
+    return false;
+  if (!MRI.hasOneNonDBGUse(MaxMI->getOperand(0).getReg()))
+    return false;
+
+  Register Dst = Sub1->getReg(0);
+  Register Sub2Result = Sub2MI->getOperand(0).getReg();
+
+  MatchInfo = [=](MachineIRBuilder &B) {
+    B.buildSMin(Dst, X, Sub2Result);
+  };
+  return true;
+}
+
 bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(
     const MachineInstr &MI, BuildFnTy &MatchInfo) const {
   const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index f77ab013e20f2..fd64e54e0773d 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -585,3 +585,25 @@ body:             |
     RET_ReallyLR implicit $q0
 
 ...
+---
+name:   ASubMax
+body:             |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: ASubMax
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, %sub1
+    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0

>From 4be9d442df6a8ef23af037093d30aa4d7f2317df Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:29:46 +0100
Subject: [PATCH 06/33] test

---
 .../AArch64/GlobalISel/combine-integer.mir    | 30 +++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index fd64e54e0773d..23dd6a7f3ed50 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -607,3 +607,33 @@ body:             |
     %sub2:_(s64) = G_SUB %zero, %max
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0
+    
\ No newline at end of file

>From 784f8c887ca27adb9d3d3dce84dbf94f6c029cf4 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:31:00 +0100
Subject: [PATCH 07/33] wip

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

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 23dd6a7f3ed50..10f41853ad9c5 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -615,7 +615,6 @@ body:             |
   bb.0:
     liveins: $x0
 
-
     ; CHECK-LABEL: name: ASubMaxOneUse
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}
@@ -628,7 +627,6 @@ body:             |
     ; CHECK-NEXT: $x0 = COPY %mul(s64)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %a:_(s64) = COPY $x0
-
     %zero:_(s64) = G_CONSTANT i64 0
     %sub1:_(s64) = G_SUB %zero, %a
     %max:_(s64) = G_SMAX %a, %sub1
@@ -636,4 +634,4 @@ body:             |
     %mul:_(s64) = G_MUL %max, %sub2
     $x0 = COPY %mul
     RET_ReallyLR implicit $x0
-    
\ No newline at end of file
+

>From b2e4a8a7b861500dc5d71fae45de3e7f9efb9f85 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:31:35 +0100
Subject: [PATCH 08/33] wip

---
 .../AArch64/GlobalISel/combine-integer.mir    | 57 ++++++++++++++++++-
 1 file changed, 54 insertions(+), 3 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 10f41853ad9c5..91f5961160b53 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -586,12 +586,12 @@ body:             |
 
 ...
 ---
-name:   ASubMax
+name:   ASubSMax
 body:             |
   bb.0:
     liveins: $x0
 
-    ; CHECK-LABEL: name: ASubMax
+    ; CHECK-LABEL: name: ASubSMax
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %a:_(s64) = COPY $x0
@@ -610,7 +610,7 @@ body:             |
 
 ...
 ---
-name:   ASubMaxOneUse
+name:   ASubSMaxOneUse
 body:             |
   bb.0:
     liveins: $x0
@@ -635,3 +635,54 @@ body:             |
     $x0 = COPY %mul
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   ASubUMax
+body:             |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: ASubMax
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, %sub1
+    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_UMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubUMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: ASubMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_UMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0
+

>From 87755bdd108ea9af9c6232d5eb20ed073c332b7f Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:52:57 +0100
Subject: [PATCH 09/33] no sense

---
 .../include/llvm/Target/GlobalISel/Combine.td |  6 +--
 .../AArch64/GlobalISel/combine-integer.mir    | 37 +++----------------
 2 files changed, 7 insertions(+), 36 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 16fdc926102b7..3c236c78ad6b7 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2086,9 +2086,7 @@ def SubUmaxSub: GICombineRule<
    (defs root:$root),
    (match (G_SUB $sub, 0, $A),
           (G_UMAX $max, $A, $sub),
-          (G_SUB $root, 0, $max):$root, 
-          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) 
-              && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+          (G_SUB $root, 0, $max):$root),
    (apply (G_SUB $sub1, 0, $A), 
           (G_UMIN $root, $A, $sub1))>;
    
@@ -2116,7 +2114,7 @@ def integer_reassoc_combines: GICombineGroup<[
 
 def max_min_combines: GICombineGroup<[
   SubSmaxSub, 
-  // SubUmaxSub
+  SubUmaxSub
 ]>;
 
 // fold (A+(shl (0-B), C)) -> (A-(shl B, C))
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 91f5961160b53..8740c44ab0ec9 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -615,7 +615,7 @@ body:             |
   bb.0:
     liveins: $x0
 
-    ; CHECK-LABEL: name: ASubMaxOneUse
+    ; CHECK-LABEL: name: ASubSMaxOneUse
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %a:_(s64) = COPY $x0
@@ -642,13 +642,14 @@ body:             |
   bb.0:
     liveins: $x0
 
-    ; CHECK-LABEL: name: ASubMax
+
+    ; CHECK-LABEL: name: ASubUMax
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %a:_(s64) = COPY $x0
     ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, %sub1
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_UMIN %a, [[SUB]]
     ; CHECK-NEXT: $x0 = COPY %sub2(s64)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %a:_(s64) = COPY $x0
@@ -658,31 +659,3 @@ body:             |
     %sub2:_(s64) = G_SUB %zero, %max
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
-
-...
----
-name:   ASubUMaxOneUse
-body:             |
-  bb.0:
-    liveins: $x0
-
-    ; CHECK-LABEL: name: ASubMaxOneUse
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
-    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
-    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
-    ; CHECK-NEXT: $x0 = COPY %mul(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_UMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    %mul:_(s64) = G_MUL %max, %sub2
-    $x0 = COPY %mul
-    RET_ReallyLR implicit $x0
-

>From c6e602b9a042e39322f42196e841b6195d0b4e8e Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 11:57:19 +0100
Subject: [PATCH 10/33] use;

---
 .../include/llvm/Target/GlobalISel/Combine.td |  3 ++-
 .../AArch64/GlobalISel/combine-integer.mir    | 27 +++++++++++++++++++
 2 files changed, 29 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 3c236c78ad6b7..336d000becd76 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2086,7 +2086,8 @@ def SubUmaxSub: GICombineRule<
    (defs root:$root),
    (match (G_SUB $sub, 0, $A),
           (G_UMAX $max, $A, $sub),
-          (G_SUB $root, 0, $max):$root),
+          (G_SUB $root, 0, $max),
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
    (apply (G_SUB $sub1, 0, $A), 
           (G_UMIN $root, $A, $sub1))>;
    
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 8740c44ab0ec9..245633a6b3802 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -659,3 +659,30 @@ body:             |
     %sub2:_(s64) = G_SUB %zero, %max
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubUMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: ASubUMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_UMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_UMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0

>From 799c4b70e5d1e413c0c965cec04ed2feaf641e5f Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 13:12:48 +0100
Subject: [PATCH 11/33] reproduce

---
 .../include/llvm/Target/GlobalISel/Combine.td | 22 ++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 336d000becd76..07716c6a1a8fd 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2072,15 +2072,27 @@ def AMinusC1PlusC2: GICombineRule<
    [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]),
    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
+// with the manual implementation of the helper it works
+// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
+// def SubSmaxSub: GICombineRule<
+//    (defs root:$root, build_fn_matchinfo:$matchinfo),
+//    (match (G_SUB $sub, 0, $A),
+//           (G_SMAX $max, $A, $sub),
+//           (G_SUB $root, 0, $max):$root, 
+//           [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
+//    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+      
+// otherwise it crashes
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubSmaxSub: GICombineRule<
-   (defs root:$root, build_fn_matchinfo:$matchinfo),
+   (defs root:$root),
    (match (G_SUB $sub, 0, $A),
           (G_SMAX $max, $A, $sub),
-          (G_SUB $root, 0, $max):$root, 
-          [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
-   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
-          
+          (G_SUB $root, 0, $max),
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+   (apply (G_SUB $sub1, 0, $A), 
+          (G_SMIN $root, $A, $sub1))>;
+              
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubUmaxSub: GICombineRule<
    (defs root:$root),

>From 495a95aecc3e718d6574ed003c9ee7b92f62db53 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 10 Apr 2026 13:36:58 +0100
Subject: [PATCH 12/33] wip

---
 llvm/include/llvm/Target/GlobalISel/Combine.td | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 07716c6a1a8fd..c977e38b0fd33 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2089,7 +2089,8 @@ def SubSmaxSub: GICombineRule<
    (match (G_SUB $sub, 0, $A),
           (G_SMAX $max, $A, $sub),
           (G_SUB $root, 0, $max),
-          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
+                    MRI.hasOneNonDBGUse(${max}.getReg()); }]),
    (apply (G_SUB $sub1, 0, $A), 
           (G_SMIN $root, $A, $sub1))>;
               
@@ -2099,7 +2100,8 @@ def SubUmaxSub: GICombineRule<
    (match (G_SUB $sub, 0, $A),
           (G_UMAX $max, $A, $sub),
           (G_SUB $root, 0, $max),
-          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) && MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
+                    MRI.hasOneNonDBGUse(${max}.getReg()); }]),
    (apply (G_SUB $sub1, 0, $A), 
           (G_UMIN $root, $A, $sub1))>;
    

>From 06252af1870dec0c451e9d8b3066b7d6b1971e68 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 14 May 2026 14:09:11 +0100
Subject: [PATCH 13/33] format

---
 .../llvm/CodeGen/GlobalISel/CombinerHelper.h  | 22 +++++++++----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index ebffafa308a4b..7ac0cfc9c3294 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -133,9 +133,7 @@ class CombinerHelper {
 
   GISelValueTracking *getValueTracking() const { return VT; }
 
-  MachineIRBuilder &getBuilder() const {
-    return Builder;
-  }
+  MachineIRBuilder &getBuilder() const { return Builder; }
 
   const TargetInstrInfo &getTII() const { return *TII; }
 
@@ -173,8 +171,10 @@ class CombinerHelper {
   /// is a legal integer constant type on the target.
   bool isConstantLegalOrBeforeLegalizer(const LLT Ty) const;
 
-  /// MachineRegisterInfo::replaceRegWith() and inform the observer of the changes
-  void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg, Register ToReg) const;
+  /// MachineRegisterInfo::replaceRegWith() and inform the observer of the
+  /// changes
+  void replaceRegWith(MachineRegisterInfo &MRI, Register FromReg,
+                      Register ToReg) const;
 
   /// Replace a single register operand with a new register and inform the
   /// observer of the changes.
@@ -518,12 +518,13 @@ class CombinerHelper {
   bool matchEqualDefs(const MachineOperand &MOP1,
                       const MachineOperand &MOP2) const;
 
-  /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value equal to
+  /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value
+  /// equal to
   /// \p C.
   bool matchConstantOp(const MachineOperand &MOP, int64_t C) const;
 
-  /// Return true if \p MOP is defined by a G_FCONSTANT or splat with a value exactly
-  /// equal to \p C.
+  /// Return true if \p MOP is defined by a G_FCONSTANT or splat with a value
+  /// exactly equal to \p C.
   bool matchConstantFPOp(const MachineOperand &MOP, double C) const;
 
   /// @brief Checks if constant at \p ConstIdx is larger than \p MI 's bitwidth
@@ -1040,9 +1041,8 @@ class CombinerHelper {
   bool matchFoldAMinusC1PlusC2(const MachineInstr &MI,
                                BuildFnTy &MatchInfo) const;
 
-  bool matchFoldSubSmaxSub(const MachineInstr &MI,
-                               BuildFnTy &MatchInfo) const;
-                               
+  bool matchFoldSubSmaxSub(const MachineInstr &MI, BuildFnTy &MatchInfo) const;
+
   bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
                      BuildFnTy &MatchInfo) const;
 

>From 4c0e25ed42a253312e6d75b63d86f55321b86b5b Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 14 May 2026 14:09:31 +0100
Subject: [PATCH 14/33] format

---
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 70 +++++++++----------
 1 file changed, 34 insertions(+), 36 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 67495ec4372d7..8ffbc4093594e 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -135,7 +135,7 @@ isBigEndian(const SmallDenseMap<int64_t, int64_t, 8> &MemOffset2Idx,
   if (Width < 2)
     return std::nullopt;
   bool BigEndian = true, LittleEndian = true;
-  for (unsigned MemOffset = 0; MemOffset < Width; ++ MemOffset) {
+  for (unsigned MemOffset = 0; MemOffset < Width; ++MemOffset) {
     auto MemOffsetAndIdx = MemOffset2Idx.find(MemOffset);
     if (MemOffsetAndIdx == MemOffset2Idx.end())
       return std::nullopt;
@@ -764,10 +764,9 @@ bool CombinerHelper::matchCombineExtendingLoads(
   // and emit a variant of (extend (trunc X)) for the others according to the
   // relative type sizes. At the same time, pick an extend to use based on the
   // extend involved in the chosen type.
-  unsigned PreferredOpcode =
-      isa<GLoad>(&MI)
-          ? TargetOpcode::G_ANYEXT
-          : isa<GSExtLoad>(&MI) ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
+  unsigned PreferredOpcode = isa<GLoad>(&MI)       ? TargetOpcode::G_ANYEXT
+                             : isa<GSExtLoad>(&MI) ? TargetOpcode::G_SEXT
+                                                   : TargetOpcode::G_ZEXT;
   Preferred = {LLT(), PreferredOpcode, nullptr};
   for (auto &UseMI : MRI.use_nodbg_instructions(LoadReg)) {
     if (UseMI.getOpcode() == TargetOpcode::G_SEXT ||
@@ -1593,7 +1592,7 @@ void CombinerHelper::applyCombineDivRem(MachineInstr &MI,
   Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM
                               : TargetOpcode::G_UDIVREM,
                      {DestDivReg, DestRemReg},
-                     { FirstInst->getOperand(1), FirstInst->getOperand(2) });
+                     {FirstInst->getOperand(1), FirstInst->getOperand(2)});
   MI.eraseFromParent();
   OtherMI->eraseFromParent();
 }
@@ -2066,7 +2065,8 @@ bool CombinerHelper::matchCommuteShift(MachineInstr &MI,
 
   auto *SrcDef = MRI.getVRegDef(SrcReg);
   assert((SrcDef->getOpcode() == TargetOpcode::G_ADD ||
-          SrcDef->getOpcode() == TargetOpcode::G_OR) && "Unexpected op");
+          SrcDef->getOpcode() == TargetOpcode::G_OR) &&
+         "Unexpected op");
   LLT SrcTy = MRI.getType(SrcReg);
   MatchInfo = [=](MachineIRBuilder &B) {
     auto S1 = B.buildShl(SrcTy, X, ShiftReg);
@@ -2468,7 +2468,8 @@ bool CombinerHelper::matchCombineShiftToUnmerge(MachineInstr &MI,
                                                 unsigned &ShiftVal) const {
   assert((MI.getOpcode() == TargetOpcode::G_SHL ||
           MI.getOpcode() == TargetOpcode::G_LSHR ||
-          MI.getOpcode() == TargetOpcode::G_ASHR) && "Expected a shift");
+          MI.getOpcode() == TargetOpcode::G_ASHR) &&
+         "Expected a shift");
 
   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
   if (Ty.isVector()) // TODO:
@@ -2511,8 +2512,10 @@ void CombinerHelper::applyCombineShiftToUnmerge(
     //   dst = G_MERGE_VALUES (G_LSHR hi, C - 32), 0
 
     if (NarrowShiftAmt != 0) {
-      Narrowed = Builder.buildLShr(HalfTy, Narrowed,
-        Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
+      Narrowed = Builder
+                     .buildLShr(HalfTy, Narrowed,
+                                Builder.buildConstant(HalfTy, NarrowShiftAmt))
+                     .getReg(0);
     }
 
     auto Zero = Builder.buildConstant(HalfTy, 0);
@@ -2524,17 +2527,18 @@ void CombinerHelper::applyCombineShiftToUnmerge(
     //   lo, hi = G_UNMERGE_VALUES x
     //   dst = G_MERGE_VALUES 0, (G_SHL hi, C - 32)
     if (NarrowShiftAmt != 0) {
-      Narrowed = Builder.buildShl(HalfTy, Narrowed,
-        Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
+      Narrowed = Builder
+                     .buildShl(HalfTy, Narrowed,
+                               Builder.buildConstant(HalfTy, NarrowShiftAmt))
+                     .getReg(0);
     }
 
     auto Zero = Builder.buildConstant(HalfTy, 0);
     Builder.buildMergeLikeInstr(DstReg, {Zero, Narrowed});
   } else {
     assert(MI.getOpcode() == TargetOpcode::G_ASHR);
-    auto Hi = Builder.buildAShr(
-      HalfTy, Unmerge.getReg(1),
-      Builder.buildConstant(HalfTy, HalfSize - 1));
+    auto Hi = Builder.buildAShr(HalfTy, Unmerge.getReg(1),
+                                Builder.buildConstant(HalfTy, HalfSize - 1));
 
     if (ShiftVal == HalfSize) {
       // (G_ASHR i64:x, 32) ->
@@ -2547,9 +2551,9 @@ void CombinerHelper::applyCombineShiftToUnmerge(
       //   G_MERGE_VALUES %narrowed, %narrowed
       Builder.buildMergeLikeInstr(DstReg, {Hi, Hi});
     } else {
-      auto Lo = Builder.buildAShr(
-        HalfTy, Unmerge.getReg(1),
-        Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
+      auto Lo =
+          Builder.buildAShr(HalfTy, Unmerge.getReg(1),
+                            Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
 
       // (G_ASHR i64:x, C) ->, for C >= 32
       //   G_MERGE_VALUES (G_ASHR hi_32(x), C - 32), (G_ASHR hi_32(x), 31)
@@ -3423,9 +3427,7 @@ bool CombinerHelper::matchOverlappingAnd(
   Register R;
   int64_t C1;
   int64_t C2;
-  if (!mi_match(
-          Dst, MRI,
-          m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
+  if (!mi_match(Dst, MRI, m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
     return false;
 
   MatchInfo = [=](MachineIRBuilder &B) {
@@ -4247,8 +4249,8 @@ CombinerHelper::findLoadOffsetsForLoadOrCombine(
   // pattern.
   assert(Loads.size() == RegsToVisit.size() &&
          "Expected to find a load for each register?");
-  assert(EarliestLoad != LatestLoad && EarliestLoad &&
-         LatestLoad && "Expected at least two loads?");
+  assert(EarliestLoad != LatestLoad && EarliestLoad && LatestLoad &&
+         "Expected at least two loads?");
 
   // Check if there are any stores, calls, etc. between any of the loads. If
   // there are, then we can't safely perform the combine.
@@ -4347,10 +4349,9 @@ bool CombinerHelper::matchLoadOrCombine(
   // load x[i+1] -> byte 0 ---> wide_load x[i]
   // load x[i+2] -> byte 1
   const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
-  const unsigned ZeroByteOffset =
-      *IsBigEndian
-          ? bigEndianByteAt(NumLoadsInTy, 0)
-          : littleEndianByteAt(NumLoadsInTy, 0);
+  const unsigned ZeroByteOffset = *IsBigEndian
+                                      ? bigEndianByteAt(NumLoadsInTy, 0)
+                                      : littleEndianByteAt(NumLoadsInTy, 0);
   auto ZeroOffsetIdx = MemOffset2Idx.find(ZeroByteOffset);
   if (ZeroOffsetIdx == MemOffset2Idx.end() ||
       ZeroOffsetIdx->second != LowestIdx)
@@ -4667,7 +4668,8 @@ bool CombinerHelper::matchFunnelShiftToRotate(MachineInstr &MI) const {
     return false;
   unsigned RotateOpc =
       Opc == TargetOpcode::G_FSHL ? TargetOpcode::G_ROTL : TargetOpcode::G_ROTR;
-  return isLegalOrBeforeLegalizer({RotateOpc, {MRI.getType(X), MRI.getType(Y)}});
+  return isLegalOrBeforeLegalizer(
+      {RotateOpc, {MRI.getType(X), MRI.getType(Y)}});
 }
 
 void CombinerHelper::applyFunnelShiftToRotate(MachineInstr &MI) const {
@@ -4980,9 +4982,7 @@ bool CombinerHelper::matchBitfieldExtractFromShrAnd(
 
   // If the shift subsumes the mask, emit the 0 directly.
   if (0 == (SMask >> ShrAmt)) {
-    MatchInfo = [=](MachineIRBuilder &B) {
-      B.buildConstant(Dst, 0);
-    };
+    MatchInfo = [=](MachineIRBuilder &B) { B.buildConstant(Dst, 0); };
     return true;
   }
 
@@ -8440,8 +8440,8 @@ bool CombinerHelper::matchFoldSubSmaxSub(const MachineInstr &MI,
     return false;
 
   // Verify Sub2 LHS == 0
-  auto MaybeCst2 = getIConstantVRegValWithLookThrough(
-      Sub2MI->getOperand(1).getReg(), MRI);
+  auto MaybeCst2 =
+      getIConstantVRegValWithLookThrough(Sub2MI->getOperand(1).getReg(), MRI);
   if (!MaybeCst2 || !MaybeCst2->Value.isZero())
     return false;
 
@@ -8458,9 +8458,7 @@ bool CombinerHelper::matchFoldSubSmaxSub(const MachineInstr &MI,
   Register Dst = Sub1->getReg(0);
   Register Sub2Result = Sub2MI->getOperand(0).getReg();
 
-  MatchInfo = [=](MachineIRBuilder &B) {
-    B.buildSMin(Dst, X, Sub2Result);
-  };
+  MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(Dst, X, Sub2Result); };
   return true;
 }
 

>From feef965faf8e13d14fe32eaeee3c8b4de0789a40 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 14 May 2026 15:04:49 +0100
Subject: [PATCH 15/33] manual impl

---
 .../include/llvm/Target/GlobalISel/Combine.td | 32 +++++++++----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 6245efbc45a11..5d1948e52dfd2 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2106,25 +2106,25 @@ def AMinusC1PlusC2: GICombineRule<
 
 // with the manual implementation of the helper it works
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
-// def SubSmaxSub: GICombineRule<
-//    (defs root:$root, build_fn_matchinfo:$matchinfo),
-//    (match (G_SUB $sub, 0, $A),
-//           (G_SMAX $max, $A, $sub),
-//           (G_SUB $root, 0, $max):$root, 
-//           [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
-//    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
-      
-// otherwise it crashes
-// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubSmaxSub: GICombineRule<
-   (defs root:$root),
+   (defs root:$root, build_fn_matchinfo:$matchinfo),
    (match (G_SUB $sub, 0, $A),
           (G_SMAX $max, $A, $sub),
-          (G_SUB $root, 0, $max),
-          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
-                    MRI.hasOneNonDBGUse(${max}.getReg()); }]),
-   (apply (G_SUB $sub1, 0, $A), 
-          (G_SMIN $root, $A, $sub1))>;
+          (G_SUB $root, 0, $max):$root, 
+          [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
+   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+      
+// otherwise it crashes
+// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
+// def SubSmaxSub: GICombineRule<
+//    (defs root:$root),
+//    (match (G_SUB $sub, 0, $A),
+//           (G_SMAX $max, $A, $sub),
+//           (G_SUB $root, 0, $max),
+//           [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
+//                     MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+//    (apply (G_SUB $sub1, 0, $A), 
+//           (G_SMIN $root, $A, $sub1))>;
               
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubUmaxSub: GICombineRule<

>From 553a6f3f78da9691b185958c8f70b39bb05ecedf Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 5 Jun 2026 14:36:35 +0100
Subject: [PATCH 16/33] wip

---
 .../include/llvm/Target/GlobalISel/Combine.td | 23 +++++--------------
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 5d1948e52dfd2..6f40fba4679a5 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2104,27 +2104,16 @@ def AMinusC1PlusC2: GICombineRule<
    [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]),
    (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
 
-// with the manual implementation of the helper it works
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubSmaxSub: GICombineRule<
-   (defs root:$root, build_fn_matchinfo:$matchinfo),
+   (defs root:$root),
    (match (G_SUB $sub, 0, $A),
           (G_SMAX $max, $A, $sub),
-          (G_SUB $root, 0, $max):$root, 
-          [{ return Helper.matchFoldSubSmaxSub(*${root}, ${matchinfo}); }]),
-   (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
-      
-// otherwise it crashes
-// (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
-// def SubSmaxSub: GICombineRule<
-//    (defs root:$root),
-//    (match (G_SUB $sub, 0, $A),
-//           (G_SMAX $max, $A, $sub),
-//           (G_SUB $root, 0, $max),
-//           [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
-//                     MRI.hasOneNonDBGUse(${max}.getReg()); }]),
-//    (apply (G_SUB $sub1, 0, $A), 
-//           (G_SMIN $root, $A, $sub1))>;
+          (G_SUB $root, 0, $max),
+          [{ return MRI.hasOneNonDBGUse(${sub}.getReg()) &&
+                    MRI.hasOneNonDBGUse(${max}.getReg()); }]),
+   (apply (G_SUB $sub1, 0, $A), 
+          (G_SMIN $root, $A, $sub1))>;
               
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubUmaxSub: GICombineRule<

>From 5042454b7c61852cdac3be67b0c603cdb7fa5d26 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Fri, 5 Jun 2026 14:53:15 +0100
Subject: [PATCH 17/33] IT WORKS

---
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 41 -------------------
 .../AArch64/GlobalISel/combine-integer.mir    |  6 ++-
 2 files changed, 4 insertions(+), 43 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index d0ee853181fb1..fc00b2f166120 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -8485,47 +8485,6 @@ bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
   return true;
 }
 
-bool CombinerHelper::matchFoldSubSmaxSub(const MachineInstr &MI,
-                                         BuildFnTy &MatchInfo) const {
-  // fold (sub 0, (smax X, (sub 0, X))) --> (smin X, (sub 0, X))
-  const GSub *Sub1 = cast<GSub>(&MI);
-
-  MachineInstr *MaxMI = MRI.getVRegDef(Sub1->getRHSReg());
-  if (!MaxMI || MaxMI->getOpcode() != TargetOpcode::G_SMAX)
-    return false;
-
-  MachineInstr *Sub2MI = MRI.getVRegDef(MaxMI->getOperand(2).getReg());
-  if (!Sub2MI || Sub2MI->getOpcode() != TargetOpcode::G_SUB)
-    return false;
-
-  // Verify Sub1 LHS == 0
-  auto MaybeCst1 = getIConstantVRegValWithLookThrough(Sub1->getLHSReg(), MRI);
-  if (!MaybeCst1 || !MaybeCst1->Value.isZero())
-    return false;
-
-  // Verify Sub2 LHS == 0
-  auto MaybeCst2 =
-      getIConstantVRegValWithLookThrough(Sub2MI->getOperand(1).getReg(), MRI);
-  if (!MaybeCst2 || !MaybeCst2->Value.isZero())
-    return false;
-
-  // Verify X is the same register in both smax and the inner sub
-  Register X = MaxMI->getOperand(1).getReg();
-  if (X != Sub2MI->getOperand(2).getReg())
-    return false;
-
-  if (!MRI.hasOneNonDBGUse(Sub2MI->getOperand(0).getReg()))
-    return false;
-  if (!MRI.hasOneNonDBGUse(MaxMI->getOperand(0).getReg()))
-    return false;
-
-  Register Dst = Sub1->getReg(0);
-  Register Sub2Result = Sub2MI->getOperand(0).getReg();
-
-  MatchInfo = [=](MachineIRBuilder &B) { B.buildSMin(Dst, X, Sub2Result); };
-  return true;
-}
-
 bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(
     const MachineInstr &MI, BuildFnTy &MatchInfo) const {
   const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 245633a6b3802..9621ef21300cf 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -596,8 +596,8 @@ body:             |
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: %a:_(s64) = COPY $x0
     ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, %sub1
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, [[SUB]]
     ; CHECK-NEXT: $x0 = COPY %sub2(s64)
     ; CHECK-NEXT: RET_ReallyLR implicit $x0
     %a:_(s64) = COPY $x0
@@ -615,6 +615,7 @@ body:             |
   bb.0:
     liveins: $x0
 
+
     ; CHECK-LABEL: name: ASubSMaxOneUse
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}
@@ -667,6 +668,7 @@ body:             |
   bb.0:
     liveins: $x0
 
+
     ; CHECK-LABEL: name: ASubUMaxOneUse
     ; CHECK: liveins: $x0
     ; CHECK-NEXT: {{  $}}

>From 3021982f5225774df8d4ce579269468603072eb5 Mon Sep 17 00:00:00 2001
From: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
Date: Fri, 5 Jun 2026 14:59:54 +0100
Subject: [PATCH 18/33] Apply suggestions from code review

Co-authored-by: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
---
 .../llvm/CodeGen/GlobalISel/CombinerHelper.h  |  7 ++-
 .../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 58 +++++++++----------
 2 files changed, 33 insertions(+), 32 deletions(-)

diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index b0e048c0b6d9a..aa61310994a67 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -133,7 +133,9 @@ class CombinerHelper {
 
   GISelValueTracking *getValueTracking() const { return VT; }
 
-  MachineIRBuilder &getBuilder() const { return Builder; }
+  MachineIRBuilder &getBuilder() const {
+    return Builder;
+  }
 
   const TargetInstrInfo &getTII() const { return *TII; }
 
@@ -550,8 +552,7 @@ class CombinerHelper {
   LLVM_ABI bool matchEqualDefs(const MachineOperand &MOP1,
                                const MachineOperand &MOP2) const;
 
-  /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value
-  /// equal to
+  /// Return true if \p MOP is defined by a G_CONSTANT or splat with a value equal to
   /// \p C.
   LLVM_ABI bool matchConstantOp(const MachineOperand &MOP, int64_t C) const;
 
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index fc00b2f166120..76e23906d7041 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -135,7 +135,7 @@ isBigEndian(const SmallDenseMap<int64_t, int64_t, 8> &MemOffset2Idx,
   if (Width < 2)
     return std::nullopt;
   bool BigEndian = true, LittleEndian = true;
-  for (unsigned MemOffset = 0; MemOffset < Width; ++MemOffset) {
+  for (unsigned MemOffset = 0; MemOffset < Width; ++ MemOffset) {
     auto MemOffsetAndIdx = MemOffset2Idx.find(MemOffset);
     if (MemOffsetAndIdx == MemOffset2Idx.end())
       return std::nullopt;
@@ -819,9 +819,10 @@ bool CombinerHelper::matchCombineExtendingLoads(
   // and emit a variant of (extend (trunc X)) for the others according to the
   // relative type sizes. At the same time, pick an extend to use based on the
   // extend involved in the chosen type.
-  unsigned PreferredOpcode = isa<GLoad>(&MI)       ? TargetOpcode::G_ANYEXT
-                             : isa<GSExtLoad>(&MI) ? TargetOpcode::G_SEXT
-                                                   : TargetOpcode::G_ZEXT;
+  unsigned PreferredOpcode =
+      isa<GLoad>(&MI)
+          ? TargetOpcode::G_ANYEXT
+          : isa<GSExtLoad>(&MI) ? TargetOpcode::G_SEXT : TargetOpcode::G_ZEXT;
   Preferred = {LLT(), PreferredOpcode, nullptr};
   for (auto &UseMI : MRI.use_nodbg_instructions(LoadReg)) {
     if (UseMI.getOpcode() == TargetOpcode::G_SEXT ||
@@ -1656,7 +1657,7 @@ void CombinerHelper::applyCombineDivRem(MachineInstr &MI,
   Builder.buildInstr(IsSigned ? TargetOpcode::G_SDIVREM
                               : TargetOpcode::G_UDIVREM,
                      {DestDivReg, DestRemReg},
-                     {FirstInst->getOperand(1), FirstInst->getOperand(2)});
+                     { FirstInst->getOperand(1), FirstInst->getOperand(2) });
   MI.eraseFromParent();
   OtherMI->eraseFromParent();
 }
@@ -2129,8 +2130,7 @@ bool CombinerHelper::matchCommuteShift(MachineInstr &MI,
 
   auto *SrcDef = MRI.getVRegDef(SrcReg);
   assert((SrcDef->getOpcode() == TargetOpcode::G_ADD ||
-          SrcDef->getOpcode() == TargetOpcode::G_OR) &&
-         "Unexpected op");
+          SrcDef->getOpcode() == TargetOpcode::G_OR) && "Unexpected op");
   LLT SrcTy = MRI.getType(SrcReg);
   MatchInfo = [=](MachineIRBuilder &B) {
     auto S1 = B.buildShl(SrcTy, X, ShiftReg);
@@ -2532,8 +2532,7 @@ bool CombinerHelper::matchCombineShiftToUnmerge(MachineInstr &MI,
                                                 unsigned &ShiftVal) const {
   assert((MI.getOpcode() == TargetOpcode::G_SHL ||
           MI.getOpcode() == TargetOpcode::G_LSHR ||
-          MI.getOpcode() == TargetOpcode::G_ASHR) &&
-         "Expected a shift");
+          MI.getOpcode() == TargetOpcode::G_ASHR) && "Expected a shift");
 
   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
   if (Ty.isVector()) // TODO:
@@ -2576,10 +2575,8 @@ void CombinerHelper::applyCombineShiftToUnmerge(
     //   dst = G_MERGE_VALUES (G_LSHR hi, C - 32), 0
 
     if (NarrowShiftAmt != 0) {
-      Narrowed = Builder
-                     .buildLShr(HalfTy, Narrowed,
-                                Builder.buildConstant(HalfTy, NarrowShiftAmt))
-                     .getReg(0);
+      Narrowed = Builder.buildLShr(HalfTy, Narrowed,
+        Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
     }
 
     auto Zero = Builder.buildConstant(HalfTy, 0);
@@ -2591,18 +2588,17 @@ void CombinerHelper::applyCombineShiftToUnmerge(
     //   lo, hi = G_UNMERGE_VALUES x
     //   dst = G_MERGE_VALUES 0, (G_SHL hi, C - 32)
     if (NarrowShiftAmt != 0) {
-      Narrowed = Builder
-                     .buildShl(HalfTy, Narrowed,
-                               Builder.buildConstant(HalfTy, NarrowShiftAmt))
-                     .getReg(0);
+      Narrowed = Builder.buildShl(HalfTy, Narrowed,
+        Builder.buildConstant(HalfTy, NarrowShiftAmt)).getReg(0);
     }
 
     auto Zero = Builder.buildConstant(HalfTy, 0);
     Builder.buildMergeLikeInstr(DstReg, {Zero, Narrowed});
   } else {
     assert(MI.getOpcode() == TargetOpcode::G_ASHR);
-    auto Hi = Builder.buildAShr(HalfTy, Unmerge.getReg(1),
-                                Builder.buildConstant(HalfTy, HalfSize - 1));
+    auto Hi = Builder.buildAShr(
+      HalfTy, Unmerge.getReg(1),
+      Builder.buildConstant(HalfTy, HalfSize - 1));
 
     if (ShiftVal == HalfSize) {
       // (G_ASHR i64:x, 32) ->
@@ -2615,9 +2611,9 @@ void CombinerHelper::applyCombineShiftToUnmerge(
       //   G_MERGE_VALUES %narrowed, %narrowed
       Builder.buildMergeLikeInstr(DstReg, {Hi, Hi});
     } else {
-      auto Lo =
-          Builder.buildAShr(HalfTy, Unmerge.getReg(1),
-                            Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
+      auto Lo = Builder.buildAShr(
+        HalfTy, Unmerge.getReg(1),
+        Builder.buildConstant(HalfTy, ShiftVal - HalfSize));
 
       // (G_ASHR i64:x, C) ->, for C >= 32
       //   G_MERGE_VALUES (G_ASHR hi_32(x), C - 32), (G_ASHR hi_32(x), 31)
@@ -3491,7 +3487,9 @@ bool CombinerHelper::matchOverlappingAnd(
   Register R;
   int64_t C1;
   int64_t C2;
-  if (!mi_match(Dst, MRI, m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
+  if (!mi_match(
+          Dst, MRI,
+          m_GAnd(m_GAnd(m_Reg(R), m_ICst(C1)), m_ICst(C2))))
     return false;
 
   MatchInfo = [=](MachineIRBuilder &B) {
@@ -4413,9 +4411,10 @@ bool CombinerHelper::matchLoadOrCombine(
   // load x[i+1] -> byte 0 ---> wide_load x[i]
   // load x[i+2] -> byte 1
   const unsigned NumLoadsInTy = WideMemSizeInBits / NarrowMemSizeInBits;
-  const unsigned ZeroByteOffset = *IsBigEndian
-                                      ? bigEndianByteAt(NumLoadsInTy, 0)
-                                      : littleEndianByteAt(NumLoadsInTy, 0);
+  const unsigned ZeroByteOffset =
+      *IsBigEndian
+          ? bigEndianByteAt(NumLoadsInTy, 0)
+          : littleEndianByteAt(NumLoadsInTy, 0);
   auto ZeroOffsetIdx = MemOffset2Idx.find(ZeroByteOffset);
   if (ZeroOffsetIdx == MemOffset2Idx.end() ||
       ZeroOffsetIdx->second != LowestIdx)
@@ -4732,8 +4731,7 @@ bool CombinerHelper::matchFunnelShiftToRotate(MachineInstr &MI) const {
     return false;
   unsigned RotateOpc =
       Opc == TargetOpcode::G_FSHL ? TargetOpcode::G_ROTL : TargetOpcode::G_ROTR;
-  return isLegalOrBeforeLegalizer(
-      {RotateOpc, {MRI.getType(X), MRI.getType(Y)}});
+  return isLegalOrBeforeLegalizer({RotateOpc, {MRI.getType(X), MRI.getType(Y)}});
 }
 
 void CombinerHelper::applyFunnelShiftToRotate(MachineInstr &MI) const {
@@ -5046,7 +5044,9 @@ bool CombinerHelper::matchBitfieldExtractFromShrAnd(
 
   // If the shift subsumes the mask, emit the 0 directly.
   if (0 == (SMask >> ShrAmt)) {
-    MatchInfo = [=](MachineIRBuilder &B) { B.buildConstant(Dst, 0); };
+    MatchInfo = [=](MachineIRBuilder &B) {
+      B.buildConstant(Dst, 0);
+    };
     return true;
   }
 

>From d833aa8369c298258f7aa512d4d6e3786ac31b8a Mon Sep 17 00:00:00 2001
From: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
Date: Fri, 5 Jun 2026 15:02:48 +0100
Subject: [PATCH 19/33] Apply suggestion from @luisacicolini

---
 llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 76e23906d7041..88b68d7685c63 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -4311,8 +4311,8 @@ CombinerHelper::findLoadOffsetsForLoadOrCombine(
   // pattern.
   assert(Loads.size() == RegsToVisit.size() &&
          "Expected to find a load for each register?");
-  assert(EarliestLoad != LatestLoad && EarliestLoad && LatestLoad &&
-         "Expected at least two loads?");
+  assert(EarliestLoad != LatestLoad && EarliestLoad &&
+         LatestLoad && "Expected at least two loads?");
 
   // Check if there are any stores, calls, etc. between any of the loads. If
   // there are, then we can't safely perform the combine.

>From 0d529afceecefda89ea23c0cb5a25664e3192974 Mon Sep 17 00:00:00 2001
From: Luisa Cicolini <48860705+luisacicolini at users.noreply.github.com>
Date: Fri, 5 Jun 2026 16:02:34 +0100
Subject: [PATCH 20/33] Update llvm/include/llvm/Target/GlobalISel/Combine.td

Co-authored-by: Osman Yasar <osmanyas05 at gmail.com>
---
 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 797b4fe9c6096..0d7292f0de2fe 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2193,7 +2193,7 @@ def integer_reassoc_combines: GICombineGroup<[
   C2MinusAPlusC1,
   AMinusC1MinusC2,
   C1Minus2MinusC2,
-  AMinusC1PlusC2,
+  AMinusC1PlusC2
 ]>;
 
 def max_min_combines: GICombineGroup<[

>From ceeb7a0c1594fe623f8369f835e24cd7843a8f77 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Mon, 8 Jun 2026 18:02:15 +0100
Subject: [PATCH 21/33] test

---
 .../AArch64/GlobalISel/combine-integer.mir    | 104 -----------------
 .../AArch64/GlobalISel/combine-smax-smin.mir  | 106 ++++++++++++++++++
 2 files changed, 106 insertions(+), 104 deletions(-)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index 9621ef21300cf..55c0cb2559f37 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -584,107 +584,3 @@ body:             |
     $q0 = COPY %sub2
     RET_ReallyLR implicit $q0
 
-...
----
-name:   ASubSMax
-body:             |
-  bb.0:
-    liveins: $x0
-
-    ; CHECK-LABEL: name: ASubSMax
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, [[SUB]]
-    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_SMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    $x0 = COPY %sub2
-    RET_ReallyLR implicit $x0
-
-...
----
-name:   ASubSMaxOneUse
-body:             |
-  bb.0:
-    liveins: $x0
-
-
-    ; CHECK-LABEL: name: ASubSMaxOneUse
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
-    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
-    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
-    ; CHECK-NEXT: $x0 = COPY %mul(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_SMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    %mul:_(s64) = G_MUL %max, %sub2
-    $x0 = COPY %mul
-    RET_ReallyLR implicit $x0
-
-...
----
-name:   ASubUMax
-body:             |
-  bb.0:
-    liveins: $x0
-
-
-    ; CHECK-LABEL: name: ASubUMax
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %sub2:_(s64) = G_UMIN %a, [[SUB]]
-    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_UMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    $x0 = COPY %sub2
-    RET_ReallyLR implicit $x0
-
-...
----
-name:   ASubUMaxOneUse
-body:             |
-  bb.0:
-    liveins: $x0
-
-
-    ; CHECK-LABEL: name: ASubUMaxOneUse
-    ; CHECK: liveins: $x0
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: %a:_(s64) = COPY $x0
-    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
-    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
-    ; CHECK-NEXT: %max:_(s64) = G_UMAX %a, %sub1
-    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
-    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
-    ; CHECK-NEXT: $x0 = COPY %mul(s64)
-    ; CHECK-NEXT: RET_ReallyLR implicit $x0
-    %a:_(s64) = COPY $x0
-    %zero:_(s64) = G_CONSTANT i64 0
-    %sub1:_(s64) = G_SUB %zero, %a
-    %max:_(s64) = G_UMAX %a, %sub1
-    %sub2:_(s64) = G_SUB %zero, %max
-    %mul:_(s64) = G_MUL %max, %sub2
-    $x0 = COPY %mul
-    RET_ReallyLR implicit $x0
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir
new file mode 100644
index 0000000000000..d91159ebdacef
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir
@@ -0,0 +1,106 @@
+# 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:   ASubSMax
+body:             |
+  bb.0:
+    liveins: $x0
+
+    ; CHECK-LABEL: name: ASubSMax
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_SMIN %a, [[SUB]]
+    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubSMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubSMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_SMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_SMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubUMax
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubUMax
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %sub2:_(s64) = G_UMIN %a, [[SUB]]
+    ; CHECK-NEXT: $x0 = COPY %sub2(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_UMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    $x0 = COPY %sub2
+    RET_ReallyLR implicit $x0
+
+...
+---
+name:   ASubUMaxOneUse
+body:             |
+  bb.0:
+    liveins: $x0
+
+
+    ; CHECK-LABEL: name: ASubUMaxOneUse
+    ; CHECK: liveins: $x0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(s64) = COPY $x0
+    ; CHECK-NEXT: %zero:_(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: %sub1:_(s64) = G_SUB %zero, %a
+    ; CHECK-NEXT: %max:_(s64) = G_UMAX %a, %sub1
+    ; CHECK-NEXT: %sub2:_(s64) = G_SUB %zero, %max
+    ; CHECK-NEXT: %mul:_(s64) = G_MUL %max, %sub2
+    ; CHECK-NEXT: $x0 = COPY %mul(s64)
+    ; CHECK-NEXT: RET_ReallyLR implicit $x0
+    %a:_(s64) = COPY $x0
+    %zero:_(s64) = G_CONSTANT i64 0
+    %sub1:_(s64) = G_SUB %zero, %a
+    %max:_(s64) = G_UMAX %a, %sub1
+    %sub2:_(s64) = G_SUB %zero, %max
+    %mul:_(s64) = G_MUL %max, %sub2
+    $x0 = COPY %mul
+    RET_ReallyLR implicit $x0

>From be8340fda444dd189e4b77defa57ad6b3e050e38 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Mon, 8 Jun 2026 18:19:29 +0100
Subject: [PATCH 22/33] test

---
 .../AArch64/GlobalISel/combine-max-min.ll     | 31 +++++++++++++++++++
 ...bine-smax-smin.mir => combine-max-min.mir} |  0
 2 files changed, 31 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
 rename llvm/test/CodeGen/AArch64/GlobalISel/{combine-smax-smin.mir => combine-max-min.mir} (100%)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
new file mode 100644
index 0000000000000..3135d3432fd41
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
@@ -0,0 +1,31 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+declare i64 @llvm.smax.i64(i64, i64)
+declare i64 @llvm.umax.i64(i64, i64)
+
+; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
+define i64 @ASubSMax(i64 %a) {
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  ret i64 %sub2
+}
+
+; Extra use of %max blocks the combine.
+define i64 @ASubSMaxOneUse(i64 %a) {
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  %mul = mul i64 %max, %sub2
+  ret i64 %mul
+}
+
+; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
+define i64 @ASubUMax(i64 %a) {
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.umax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  ret i64 %sub2
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir
similarity index 100%
rename from llvm/test/CodeGen/AArch64/GlobalISel/combine-smax-smin.mir
rename to llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir

>From 7ca991db432699d1767a5d362afc6fc290dbe775 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Mon, 8 Jun 2026 19:28:19 +0100
Subject: [PATCH 23/33] test

---
 .../AArch64/GlobalISel/combine-max-min.ll     | 35 ++++++++++++++++++-
 1 file changed, 34 insertions(+), 1 deletion(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
index 3135d3432fd41..8eff477d34249 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
@@ -7,6 +7,19 @@ declare i64 @llvm.umax.i64(i64, i64)
 
 ; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
 define i64 @ASubSMax(i64 %a) {
+; CHECK-SD-LABEL: ASubSMax:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    neg x8, x0
+; CHECK-SD-NEXT:    cmp x0, x8
+; CHECK-SD-NEXT:    cneg x0, x0, gt
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: ASubSMax:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    neg x8, x0
+; CHECK-GI-NEXT:    cmp x0, x8
+; CHECK-GI-NEXT:    cneg x0, x0, ge
+; CHECK-GI-NEXT:    ret
   %sub1 = sub i64 0, %a
   %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
   %sub2 = sub i64 0, %max
@@ -15,6 +28,13 @@ define i64 @ASubSMax(i64 %a) {
 
 ; Extra use of %max blocks the combine.
 define i64 @ASubSMaxOneUse(i64 %a) {
+; CHECK-LABEL: ASubSMaxOneUse:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg x8, x0
+; CHECK-NEXT:    cmp x0, x8
+; CHECK-NEXT:    cneg x8, x0, le
+; CHECK-NEXT:    mneg x0, x8, x8
+; CHECK-NEXT:    ret
   %sub1 = sub i64 0, %a
   %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
   %sub2 = sub i64 0, %max
@@ -24,8 +44,21 @@ define i64 @ASubSMaxOneUse(i64 %a) {
 
 ; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
 define i64 @ASubUMax(i64 %a) {
+; CHECK-SD-LABEL: ASubUMax:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    neg x8, x0
+; CHECK-SD-NEXT:    cmp x0, x8
+; CHECK-SD-NEXT:    cneg x0, x0, hi
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: ASubUMax:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    neg x8, x0
+; CHECK-GI-NEXT:    cmp x0, x8
+; CHECK-GI-NEXT:    cneg x0, x0, hs
+; CHECK-GI-NEXT:    ret
   %sub1 = sub i64 0, %a
   %max = call i64 @llvm.umax.i64(i64 %a, i64 %sub1)
   %sub2 = sub i64 0, %max
   ret i64 %sub2
-}
\ No newline at end of file
+}

>From 99411e4aab32cd891724dd2ee2a3c44615810f2f Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 11:52:42 +0100
Subject: [PATCH 24/33] unrelated 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 55c0cb2559f37..a258d378ef350 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -584,3 +584,4 @@ body:             |
     $q0 = COPY %sub2
     RET_ReallyLR implicit $q0
 
+

>From b1fefd177d9c37b8995606c0ce1986928358ad11 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 11:53:34 +0100
Subject: [PATCH 25/33] unrelated change

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

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index a258d378ef350..fc9a683ed3df4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -583,5 +583,3 @@ body:             |
     %sub2:_(<4 x s32>) = G_SUB %a, %sub1
     $q0 = COPY %sub2
     RET_ReallyLR implicit $q0
-
-

>From 8ae6ff372c18c4a00f6c3221133aa79a93ae7131 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 11:54:22 +0100
Subject: [PATCH 26/33] unrelated change

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

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index fc9a683ed3df4..a258d378ef350 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -583,3 +583,5 @@ body:             |
     %sub2:_(<4 x s32>) = G_SUB %a, %sub1
     $q0 = COPY %sub2
     RET_ReallyLR implicit $q0
+
+

>From 5f7db557c5bb4ff77c3c029b7b224c20d18be7bf Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 11:54:44 +0100
Subject: [PATCH 27/33] unrelated change

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

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index a258d378ef350..f77ab013e20f2 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -584,4 +584,4 @@ body:             |
     $q0 = COPY %sub2
     RET_ReallyLR implicit $q0
 
-
+...

>From a5f1f111aebe758d0b745e7378dfca0e51bc7576 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 13:36:29 +0100
Subject: [PATCH 28/33] vec tests

---
 .../AArch64/GlobalISel/combine-max-min.mir    | 52 +++++++++++++++++++
 1 file changed, 52 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir
index d91159ebdacef..4c505f77e1bc4 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.mir
@@ -24,6 +24,32 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   ASubSMaxVec
+body:             |
+  bb.0:
+    liveins: $q0
+
+    ; CHECK-LABEL: name: ASubSMaxVec
+    ; CHECK: liveins: $q0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(<4 x s32>) = COPY $q0
+    ; CHECK-NEXT: %c:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: %c1:_(<4 x s32>) = G_BUILD_VECTOR %c(s32), %c(s32), %c(s32), %c(s32)
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB %c1, %a
+    ; CHECK-NEXT: %sub2:_(<4 x s32>) = G_SMIN %a, [[SUB]]
+    ; CHECK-NEXT: $q0 = COPY %sub2(<4 x s32>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %a:_(<4 x s32>) = COPY $q0
+    %c:_(s32) = G_CONSTANT i32 0
+    %c1:_(<4 x s32>) = G_BUILD_VECTOR %c(s32), %c(s32), %c(s32), %c(s32)
+    %sub1:_(<4 x s32>) = G_SUB %c1, %a
+    %max:_(<4 x s32>) = G_SMAX %a, %sub1
+    %sub2:_(<4 x s32>) = G_SUB %c1, %max
+    $q0 = COPY %sub2
+    RET_ReallyLR implicit $q0
+
 ...
 ---
 name:   ASubSMaxOneUse
@@ -77,6 +103,32 @@ body:             |
     $x0 = COPY %sub2
     RET_ReallyLR implicit $x0
 
+...
+---
+name:   ASubUMaxVec
+body:             |
+  bb.0:
+    liveins: $q0
+
+    ; CHECK-LABEL: name: ASubUMaxVec
+    ; CHECK: liveins: $q0
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: %a:_(<4 x s32>) = COPY $q0
+    ; CHECK-NEXT: %c:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: %c1:_(<4 x s32>) = G_BUILD_VECTOR %c(s32), %c(s32), %c(s32), %c(s32)
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(<4 x s32>) = G_SUB %c1, %a
+    ; CHECK-NEXT: %sub2:_(<4 x s32>) = G_UMIN %a, [[SUB]]
+    ; CHECK-NEXT: $q0 = COPY %sub2(<4 x s32>)
+    ; CHECK-NEXT: RET_ReallyLR implicit $q0
+    %a:_(<4 x s32>) = COPY $q0
+    %c:_(s32) = G_CONSTANT i32 0
+    %c1:_(<4 x s32>) = G_BUILD_VECTOR %c(s32), %c(s32), %c(s32), %c(s32)
+    %sub1:_(<4 x s32>) = G_SUB %c1, %a
+    %max:_(<4 x s32>) = G_UMAX %a, %sub1
+    %sub2:_(<4 x s32>) = G_SUB %c1, %max
+    $q0 = COPY %sub2
+    RET_ReallyLR implicit $q0
+
 ...
 ---
 name:   ASubUMaxOneUse

>From 6b62057373e5230cbf48df2f510c87c239db0e83 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Tue, 9 Jun 2026 13:38:45 +0100
Subject: [PATCH 29/33] vec tests ll

---
 .../AArch64/GlobalISel/combine-max-min.ll     | 28 +++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
index 8eff477d34249..5c95996195f64 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
@@ -4,6 +4,8 @@
 
 declare i64 @llvm.smax.i64(i64, i64)
 declare i64 @llvm.umax.i64(i64, i64)
+declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
+declare <4 x i32> @llvm.umax.v4i32(<4 x i32>, <4 x i32>)
 
 ; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
 define i64 @ASubSMax(i64 %a) {
@@ -42,6 +44,19 @@ define i64 @ASubSMaxOneUse(i64 %a) {
   ret i64 %mul
 }
 
+; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
+define <4 x i32> @ASubSMaxVec(<4 x i32> %a) {
+; CHECK-LABEL: ASubSMaxVec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v1.4s, v0.4s
+; CHECK-NEXT:    smin v0.4s, v0.4s, v1.4s
+; CHECK-NEXT:    ret
+  %sub1 = sub <4 x i32> zeroinitializer, %a
+  %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %sub1)
+  %sub2 = sub <4 x i32> zeroinitializer, %max
+  ret <4 x i32> %sub2
+}
+
 ; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
 define i64 @ASubUMax(i64 %a) {
 ; CHECK-SD-LABEL: ASubUMax:
@@ -62,3 +77,16 @@ define i64 @ASubUMax(i64 %a) {
   %sub2 = sub i64 0, %max
   ret i64 %sub2
 }
+
+; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
+define <4 x i32> @ASubUMaxVec(<4 x i32> %a) {
+; CHECK-LABEL: ASubUMaxVec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v1.4s, v0.4s
+; CHECK-NEXT:    umin v0.4s, v0.4s, v1.4s
+; CHECK-NEXT:    ret
+  %sub1 = sub <4 x i32> zeroinitializer, %a
+  %max = call <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %sub1)
+  %sub2 = sub <4 x i32> zeroinitializer, %max
+  ret <4 x i32> %sub2
+}

>From 1882b03fff5372259530ccbfcf94f4090b6ecf65 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 11 Jun 2026 10:01:57 +0100
Subject: [PATCH 30/33] move test

---
 llvm/test/CodeGen/AArch64/{GlobalISel => }/combine-max-min.ll | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename llvm/test/CodeGen/AArch64/{GlobalISel => }/combine-max-min.ll (100%)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/combine-max-min.ll
similarity index 100%
rename from llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
rename to llvm/test/CodeGen/AArch64/combine-max-min.ll

>From 208c8f8fbbb7f7533464fd5f6cd5a1bef286e0a5 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 11 Jun 2026 10:05:31 +0100
Subject: [PATCH 31/33] fix comment

---
 .../AArch64/GlobalISel/combine-max-min.ll     | 92 +++++++++++++++++++
 1 file changed, 92 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
new file mode 100644
index 0000000000000..5fb32e57fa94a
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
@@ -0,0 +1,92 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc -global-isel=0 -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -global-isel -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+declare i64 @llvm.smax.i64(i64, i64)
+declare i64 @llvm.umax.i64(i64, i64)
+declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
+declare <4 x i32> @llvm.umax.v4i32(<4 x i32>, <4 x i32>)
+
+; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
+define i64 @ASubSMax(i64 %a) {
+; CHECK-SD-LABEL: ASubSMax:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    neg x8, x0
+; CHECK-SD-NEXT:    cmp x0, x8
+; CHECK-SD-NEXT:    cneg x0, x0, gt
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: ASubSMax:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    neg x8, x0
+; CHECK-GI-NEXT:    cmp x0, x8
+; CHECK-GI-NEXT:    cneg x0, x0, ge
+; CHECK-GI-NEXT:    ret
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  ret i64 %sub2
+}
+
+; Extra use of %max blocks the combine.
+define i64 @ASubSMaxOneUse(i64 %a) {
+; CHECK-LABEL: ASubSMaxOneUse:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg x8, x0
+; CHECK-NEXT:    cmp x0, x8
+; CHECK-NEXT:    cneg x8, x0, le
+; CHECK-NEXT:    mneg x0, x8, x8
+; CHECK-NEXT:    ret
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.smax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  %mul = mul i64 %max, %sub2
+  ret i64 %mul
+}
+
+; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
+define <4 x i32> @ASubSMaxVec(<4 x i32> %a) {
+; CHECK-LABEL: ASubSMaxVec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v1.4s, v0.4s
+; CHECK-NEXT:    smin v0.4s, v0.4s, v1.4s
+; CHECK-NEXT:    ret
+  %sub1 = sub <4 x i32> zeroinitializer, %a
+  %max = call <4 x i32> @llvm.smax.v4i32(<4 x i32> %a, <4 x i32> %sub1)
+  %sub2 = sub <4 x i32> zeroinitializer, %max
+  ret <4 x i32> %sub2
+}
+
+; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
+define i64 @ASubUMax(i64 %a) {
+; CHECK-SD-LABEL: ASubUMax:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    neg x8, x0
+; CHECK-SD-NEXT:    cmp x0, x8
+; CHECK-SD-NEXT:    cneg x0, x0, hi
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: ASubUMax:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    neg x8, x0
+; CHECK-GI-NEXT:    cmp x0, x8
+; CHECK-GI-NEXT:    cneg x0, x0, hs
+; CHECK-GI-NEXT:    ret
+  %sub1 = sub i64 0, %a
+  %max = call i64 @llvm.umax.i64(i64 %a, i64 %sub1)
+  %sub2 = sub i64 0, %max
+  ret i64 %sub2
+}
+
+; 0 - umax(a, 0 - a)  ->  umin(a, 0 - a)
+define <4 x i32> @ASubUMaxVec(<4 x i32> %a) {
+; CHECK-LABEL: ASubUMaxVec:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    neg v1.4s, v0.4s
+; CHECK-NEXT:    umin v0.4s, v0.4s, v1.4s
+; CHECK-NEXT:    ret
+  %sub1 = sub <4 x i32> zeroinitializer, %a
+  %max = call <4 x i32> @llvm.umax.v4i32(<4 x i32> %a, <4 x i32> %sub1)
+  %sub2 = sub <4 x i32> zeroinitializer, %max
+  ret <4 x i32> %sub2
+}

>From 4e2b1fe5586bc37c657017044eeaac229c3bde5a Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 11 Jun 2026 10:05:44 +0100
Subject: [PATCH 32/33] fix comment

---
 llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
index 5fb32e57fa94a..c4da01e26c0e6 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-max-min.ll
@@ -2,11 +2,6 @@
 ; RUN: llc -global-isel=0 -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -global-isel -mtriple=aarch64 < %s | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
-declare i64 @llvm.smax.i64(i64, i64)
-declare i64 @llvm.umax.i64(i64, i64)
-declare <4 x i32> @llvm.smax.v4i32(<4 x i32>, <4 x i32>)
-declare <4 x i32> @llvm.umax.v4i32(<4 x i32>, <4 x i32>)
-
 ; 0 - smax(a, 0 - a)  ->  smin(a, 0 - a)   (i.e. -abs(a))
 define i64 @ASubSMax(i64 %a) {
 ; CHECK-SD-LABEL: ASubSMax:

>From 1bac0301cb98714dd6f5cd35b8af2335242b4c60 Mon Sep 17 00:00:00 2001
From: luisacicolini <lc985 at cam.ac.uk>
Date: Thu, 11 Jun 2026 10:06:42 +0100
Subject: [PATCH 33/33] remove wspace

---
 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 0d7292f0de2fe..c448a00068006 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -2162,7 +2162,7 @@ def SubSmaxSub: GICombineRule<
                     MRI.hasOneNonDBGUse(${max}.getReg()); }]),
    (apply (G_SUB $sub1, 0, $A), 
           (G_SMIN $root, $A, $sub1))>;
-              
+
 // (sub 0, (max X, (sub 0, X))) --> (min X, (sub 0, X))
 def SubUmaxSub: GICombineRule<
    (defs root:$root),



More information about the llvm-commits mailing list