[llvm] [GlobalIsel] Combine G_ADD and G_SUB with constants (PR #97771)
Thorsten Schütt via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 5 09:07:04 PDT 2024
https://github.com/tschuett updated https://github.com/llvm/llvm-project/pull/97771
>From d9638080af13025e8cc9bfd2db99cf63f0cc8e08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Mon, 1 Jul 2024 20:25:58 +0200
Subject: [PATCH 1/5] [GlobalIsel] Combine G_ADD and G_SUB with constants
---
.../llvm/CodeGen/GlobalISel/CombinerHelper.h | 9 ++
.../include/llvm/Target/GlobalISel/Combine.td | 57 ++++++-
.../lib/CodeGen/GlobalISel/CombinerHelper.cpp | 150 ++++++++++++++++++
.../AArch64/GlobalISel/combine-add-of-sub.mir | 41 +++--
.../AArch64/GlobalISel/combine-integer.mir | 117 ++++++++++++++
5 files changed, 351 insertions(+), 23 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 05d7e882f5135..48b3c3c381763 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -892,6 +892,15 @@ class CombinerHelper {
bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI,
BuildFnTy &MatchInfo);
+ bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
+
+ bool matchFoldAMinusC2PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
private:
/// Checks for legality of an indexed variant of \p LdSt.
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 1f26132561cca..10028ce1a8aa6 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1747,6 +1747,56 @@ def APlusBMinusCPlusA : GICombineRule<
(G_ADD $root, $A, $sub1)),
(apply (G_SUB $root, $B, $C))>;
+// fold (A+C1)-C2 -> A+(C1-C2)
+def APlusC1MinusC2: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_CONSTANT $c2, $imm2),
+ (G_CONSTANT $c1, $imm1),
+ (G_ADD $add, $A, $c1),
+ (G_SUB $root, $add, $c2):$root,
+ [{ return Helper.matchFoldAPlusC1MinusC2(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
+// fold C2-(A+C1) -> (C2-C1)-A
+def C2MinusAPlusC1: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_CONSTANT $c2, $imm2),
+ (G_CONSTANT $c1, $imm1),
+ (G_ADD $add, $A, $c1),
+ (G_SUB $root, $c2, $add):$root,
+ [{ return Helper.matchFoldC2MinusAPlusC1(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
+// fold (A-C1)-C2 -> A-(C1+C2)
+def AMinusC1MinusC2: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_CONSTANT $c2, $imm2),
+ (G_CONSTANT $c1, $imm1),
+ (G_SUB $sub1, $A, $c1),
+ (G_SUB $root, $sub1, $c2):$root,
+ [{ return Helper.matchFoldAMinusC1MinusC2(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
+// fold (C1-A)-C2 -> (C1-C2)-A
+def C1Minus2MinusC2: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_CONSTANT $c2, $imm2),
+ (G_CONSTANT $c1, $imm1),
+ (G_SUB $sub1, $c1, $A),
+ (G_SUB $root, $sub1, $c2):$root,
+ [{ return Helper.matchFoldC1Minus2MinusC2(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
+// fold ((A-C1)+C2) -> (A+(C2-C1))
+def AMinusC2PlusC2: GICombineRule<
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (G_CONSTANT $c2, $imm2),
+ (G_CONSTANT $c1, $imm1),
+ (G_SUB $sub, $A, $c1),
+ (G_ADD $root, $sub, $c2):$root,
+ [{ return Helper.matchFoldAMinusC2PlusC2(*${root}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
+
def integer_reassoc_combines: GICombineGroup<[
ZeroMinusAPlusB,
APlusZeroMinusB,
@@ -1755,7 +1805,12 @@ def integer_reassoc_combines: GICombineGroup<[
AMinusBPlusCMinusA,
AMinusBPlusBMinusC,
APlusBMinusAplusC,
- APlusBMinusCPlusA
+ APlusBMinusCPlusA,
+ APlusC1MinusC2,
+ C2MinusAPlusC1,
+ AMinusC1MinusC2,
+ C1Minus2MinusC2,
+ AMinusC2PlusC2
]>;
def freeze_of_non_undef_non_poison : GICombineRule<
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index d930ab2984629..14382477a61dc 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7433,3 +7433,153 @@ void CombinerHelper::applyExpandFPowI(MachineInstr &MI, int64_t Exponent) {
Builder.buildCopy(Dst, *Res);
MI.eraseFromParent();
}
+
+bool CombinerHelper::matchFoldAPlusC1MinusC2(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ // fold (A+C1)-C2 -> A+(C1-C2)
+ const GSub *Sub = cast<GSub>(&MI);
+ GAdd *Add = cast<GAdd>(MRI.getVRegDef(Sub->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub->getRHSReg(), MRI);
+ if (!MaybeC2)
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC1 = getIConstantVRegVal(Add->getRHSReg(), MRI);
+ if (!MaybeC1)
+ return false;
+
+ Register Dst = Sub->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Const = B.buildConstant(DstTy, *MaybeC1 - *MaybeC2);
+ B.buildAdd(Dst, Add->getLHSReg(), Const);
+ };
+
+ return true;
+}
+
+bool CombinerHelper::matchFoldC2MinusAPlusC1(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ // fold C2-(A+C1) -> (C2-C1)-A
+ const GSub *Sub = cast<GSub>(&MI);
+ GAdd *Add = cast<GAdd>(MRI.getVRegDef(Sub->getRHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub->getLHSReg(), MRI);
+ if (!MaybeC2)
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC1 = getIConstantVRegVal(Add->getRHSReg(), MRI);
+ if (!MaybeC1)
+ return false;
+
+ Register Dst = Sub->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Const = B.buildConstant(DstTy, *MaybeC2 - *MaybeC1);
+ B.buildSub(Dst, Const, Add->getLHSReg());
+ };
+
+ return true;
+}
+
+bool CombinerHelper::matchFoldAMinusC1MinusC2(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ // fold (A-C1)-C2 -> A-(C1+C2)
+ const GSub *Sub1 = cast<GSub>(&MI);
+ GSub *Sub2 = cast<GSub>(MRI.getVRegDef(Sub1->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub1->getRHSReg(), MRI);
+ if (!MaybeC2)
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub2->getRHSReg(), MRI);
+ if (!MaybeC1)
+ return false;
+
+ Register Dst = Sub1->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Const = B.buildConstant(DstTy, *MaybeC1 + *MaybeC2);
+ B.buildSub(Dst, Sub2->getLHSReg(), Const);
+ };
+
+ return true;
+}
+
+bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ // fold (C1-A)-C2 -> (C1-C2)-A
+ const GSub *Sub1 = cast<GSub>(&MI);
+ GSub *Sub2 = cast<GSub>(MRI.getVRegDef(Sub1->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub1->getRHSReg(), MRI);
+ if (!MaybeC2)
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub2->getLHSReg(), MRI);
+ if (!MaybeC1)
+ return false;
+
+ Register Dst = Sub1->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Const = B.buildConstant(DstTy, *MaybeC1 - *MaybeC2);
+ B.buildSub(Dst, Sub2->getRHSReg(), Const);
+ };
+
+ return true;
+}
+
+bool CombinerHelper::matchFoldAMinusC2PlusC2(const MachineInstr &MI,
+ BuildFnTy &MatchInfo) {
+ // fold ((A-C1)+C2) -> (A+(C2-C1))
+ const GAdd *Add = cast<GAdd>(&MI);
+ GSub *Sub = cast<GSub>(MRI.getVRegDef(Add->getLHSReg()));
+
+ if (!MRI.hasOneNonDBGUse(Sub->getReg(0)))
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC2 = getIConstantVRegVal(Add->getRHSReg(), MRI);
+ if (!MaybeC2)
+ return false;
+
+ // Cannot fail due to pattern.
+ std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub->getRHSReg(), MRI);
+ if (!MaybeC1)
+ return false;
+
+ Register Dst = Add->getReg(0);
+ LLT DstTy = MRI.getType(Dst);
+
+ MatchInfo = [=](MachineIRBuilder &B) {
+ auto Const = B.buildConstant(DstTy, *MaybeC2 - *MaybeC1);
+ B.buildAdd(Dst, Sub->getLHSReg(), Const);
+ };
+
+ return true;
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir
index ac42d2da16d56..6bd1d996da85f 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-add-of-sub.mir
@@ -3,12 +3,12 @@
...
---
+# (x + y) - y -> x
name: simplify_to_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; (x + y) - y -> x
; CHECK-LABEL: name: simplify_to_x
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -23,12 +23,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# (x + y) - x -> y
name: simplify_to_y
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; (x + y) - x -> y
; CHECK-LABEL: name: simplify_to_y
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -43,12 +43,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# (x + 1) - 1 -> x
name: simplify_to_constant_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; (x + 1) - 1 -> x
; CHECK-LABEL: name: simplify_to_constant_x
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -64,12 +64,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# (x + y) - x -> y
name: simplify_to_constant_y
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; (x + y) - x -> y
; CHECK-LABEL: name: simplify_to_constant_y
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -85,12 +85,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# (x + y) - y -> x
name: vector_simplify_to_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $d0, $d1
- ; (x + y) - y -> x
; CHECK-LABEL: name: vector_simplify_to_x
; CHECK: liveins: $d0, $d1
; CHECK-NEXT: {{ $}}
@@ -105,12 +105,12 @@ body: |
RET_ReallyLR implicit $d0
...
---
+# (x + 1) - 1 -> x
name: splat_simplify_to_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $d0, $d1
- ; (x + 1) - 1 -> x
; CHECK-LABEL: name: splat_simplify_to_x
; CHECK: liveins: $d0, $d1
; CHECK-NEXT: {{ $}}
@@ -127,6 +127,7 @@ body: |
RET_ReallyLR implicit $d0
...
---
+# (x + y) - x -> y
name: unique_registers_no_fold
tracksRegLiveness: true
body: |
@@ -151,20 +152,18 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# (x + y) - x -> y
name: unique_constants_no_fold
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; (x + y) - x -> y
; CHECK-LABEL: name: unique_constants_no_fold
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
- ; CHECK-NEXT: %x1:_(s32) = G_CONSTANT i32 1
- ; CHECK-NEXT: %x2:_(s32) = G_CONSTANT i32 2
; CHECK-NEXT: %y:_(s32) = COPY $w1
- ; CHECK-NEXT: %add:_(s32) = G_ADD %y, %x1
- ; CHECK-NEXT: %sub:_(s32) = G_SUB %add, %x2
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+ ; CHECK-NEXT: %sub:_(s32) = G_ADD %y, [[C]]
; CHECK-NEXT: $w0 = COPY %sub(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x1:_(s32) = G_CONSTANT i32 1
@@ -176,12 +175,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# x - (y + x) -> 0 - y
name: simplify_to_neg_y
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; x - (y + x) -> 0 - y
; CHECK-LABEL: name: simplify_to_neg_y
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -198,12 +197,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# y - (y + x) -> 0 - x
name: simplify_to_neg_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; y - (y + x) -> 0 - x
; CHECK-LABEL: name: simplify_to_neg_x
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -220,12 +219,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# x - (y + x) -> 0 - y
name: simplify_to_neg_y_constant
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; x - (y + x) -> 0 - y
; CHECK-LABEL: name: simplify_to_neg_y_constant
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -243,12 +242,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# y - (y + x) -> 0 - x
name: simplify_to_neg_x_constant
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; y - (y + x) -> 0 - x
; CHECK-LABEL: name: simplify_to_neg_x_constant
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
@@ -266,12 +265,12 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# y - (y + x) -> 0 - x
name: vector_simplify_to_neg_x
tracksRegLiveness: true
body: |
bb.0:
liveins: $d0, $d1
- ; y - (y + x) -> 0 - x
; CHECK-LABEL: name: vector_simplify_to_neg_x
; CHECK: liveins: $d0, $d1
; CHECK-NEXT: {{ $}}
@@ -289,12 +288,12 @@ body: |
RET_ReallyLR implicit $d0
...
---
+# x - (y + x) -> 0 - y
name: vector_simplify_to_neg_y_constant
tracksRegLiveness: true
body: |
bb.0:
liveins: $d0, $d1
- ; x - (y + x) -> 0 - y
; CHECK-LABEL: name: vector_simplify_to_neg_y_constant
; CHECK: liveins: $d0, $d1
; CHECK-NEXT: {{ $}}
@@ -314,12 +313,12 @@ body: |
RET_ReallyLR implicit $d0
...
---
+# y - (y + x) -> 0 - x
name: unique_registers_neg_no_fold
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1, $w2
- ; y - (y + x) -> 0 - x
; CHECK-LABEL: name: unique_registers_neg_no_fold
; CHECK: liveins: $w0, $w1, $w2
; CHECK-NEXT: {{ $}}
@@ -339,20 +338,18 @@ body: |
RET_ReallyLR implicit $w0
...
---
+# x - (y + x) -> 0 - y
name: wrong_constant_neg_no_fold
tracksRegLiveness: true
body: |
bb.0:
liveins: $w0, $w1
- ; x - (y + x) -> 0 - y
; CHECK-LABEL: name: wrong_constant_neg_no_fold
; CHECK: liveins: $w0, $w1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %x1:_(s32) = G_CONSTANT i32 1
- ; CHECK-NEXT: %x2:_(s32) = G_CONSTANT i32 2
; CHECK-NEXT: %y:_(s32) = COPY $w1
- ; CHECK-NEXT: %add:_(s32) = G_ADD %y, %x1
- ; CHECK-NEXT: %sub:_(s32) = G_SUB %x2, %add
+ ; CHECK-NEXT: %sub:_(s32) = G_SUB %x1, %y
; CHECK-NEXT: $w0 = COPY %sub(s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%x1:_(s32) = G_CONSTANT i32 1
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index be33f9f7b284b..e1859ef26a713 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -250,3 +250,120 @@ body: |
%add:_(<2 x s64>) = G_ADD %a, %sub1
$q0 = COPY %add
RET_ReallyLR implicit $x0
+
+...
+---
+name: APlusC1MinusC2
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: APlusC1MinusC2
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -2
+ ; CHECK-NEXT: %sub:_(s64) = G_ADD %a, [[C]]
+ ; CHECK-NEXT: $x0 = COPY %sub(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s64) = COPY $x0
+ %c1:_(s64) = G_CONSTANT i64 5
+ %c2:_(s64) = G_CONSTANT i64 7
+ %add:_(s64) = G_ADD %a, %c1
+ %sub:_(s64) = G_SUB %add, %c2
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: C2MinusAPlusC1
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: C2MinusAPlusC1
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 5
+ ; CHECK-NEXT: %sub:_(s64) = G_SUB [[C]], %a
+ ; CHECK-NEXT: $x0 = COPY %sub(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s64) = COPY $x0
+ %c1:_(s64) = G_CONSTANT i64 4
+ %c2:_(s64) = G_CONSTANT i64 9
+ %add:_(s64) = G_ADD %a, %c1
+ %sub:_(s64) = G_SUB %c2, %add
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: AMinusC1MinusC2
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: AMinusC1MinusC2
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 71
+ ; CHECK-NEXT: %sub:_(s64) = G_SUB %a, [[C]]
+ ; CHECK-NEXT: $x0 = COPY %sub(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s64) = COPY $x0
+ %c1:_(s64) = G_CONSTANT i64 11
+ %c2:_(s64) = G_CONSTANT i64 60
+ %sub1:_(s64) = G_SUB %a, %c1
+ %sub:_(s64) = G_SUB %sub1, %c2
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
+...
+---
+name: C1Minus2MinusC2
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: C1Minus2MinusC2
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -49
+ ; CHECK-NEXT: %sub:_(s64) = G_SUB %a, [[C]]
+ ; CHECK-NEXT: $x0 = COPY %sub(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s64) = COPY $x0
+ %c1:_(s64) = G_CONSTANT i64 11
+ %c2:_(s64) = G_CONSTANT i64 60
+ %sub1:_(s64) = G_SUB %c1, %a
+ %sub:_(s64) = G_SUB %sub1, %c2
+ $x0 = COPY %sub
+ RET_ReallyLR implicit $x0
+
+
+...
+---
+name: AMinusC2PlusC2
+body: |
+ bb.0:
+ liveins: $w0, $w1
+
+ ; CHECK-LABEL: name: AMinusC2PlusC2
+ ; CHECK: liveins: $w0, $w1
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: %a:_(s64) = COPY $x0
+ ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 43
+ ; CHECK-NEXT: %add:_(s64) = G_ADD %a, [[C]]
+ ; CHECK-NEXT: $x0 = COPY %add(s64)
+ ; CHECK-NEXT: RET_ReallyLR implicit $x0
+ %a:_(s64) = COPY $x0
+ %c1:_(s64) = G_CONSTANT i64 13
+ %c2:_(s64) = G_CONSTANT i64 56
+ %sub:_(s64) = G_SUB %a, %c1
+ %add:_(s64) = G_ADD %sub, %c2
+ $x0 = COPY %add
+ RET_ReallyLR implicit $x0
+
>From dfaf3291d9ec18b0f7b206d8717b4fd5d0297bee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Fri, 5 Jul 2024 00:07:27 +0200
Subject: [PATCH 2/5] small fix
---
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 2 +-
llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 14382477a61dc..88441a5de62c7 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7548,7 +7548,7 @@ bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI,
MatchInfo = [=](MachineIRBuilder &B) {
auto Const = B.buildConstant(DstTy, *MaybeC1 - *MaybeC2);
- B.buildSub(Dst, Sub2->getRHSReg(), Const);
+ B.buildSub(Dst, Const, Sub2->getRHSReg());
};
return true;
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
index e1859ef26a713..2f10a497fa74c 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer.mir
@@ -332,7 +332,7 @@ body: |
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: %a:_(s64) = COPY $x0
; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -49
- ; CHECK-NEXT: %sub:_(s64) = G_SUB %a, [[C]]
+ ; CHECK-NEXT: %sub:_(s64) = G_SUB [[C]], %a
; CHECK-NEXT: $x0 = COPY %sub(s64)
; CHECK-NEXT: RET_ReallyLR implicit $x0
%a:_(s64) = COPY $x0
>From 3dbd3c250faaf3f050cf0e357dc3f3a41d3547a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Fri, 5 Jul 2024 08:27:42 +0200
Subject: [PATCH 3/5] IR test
---
.../AArch64/GlobalISel/combine-integer-ll.ll | 71 +++++++++++++++++++
1 file changed, 71 insertions(+)
create mode 100644 llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll
new file mode 100644
index 0000000000000..03dcbafd73e87
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-integer-ll.ll
@@ -0,0 +1,71 @@
+; 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 -global-isel-abort=2 -verify-machineinstrs %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+
+
+
+define i64 @APlusC1MinusC2(i64 %a) {
+; CHECK-LABEL: APlusC1MinusC2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: sub x0, x0, #1
+; CHECK-NEXT: ret
+entry:
+; fold (A+C1)-C2 -> A+(C1-C2)
+ %add1 = add i64 %a, 5
+ %sub1 = sub i64 %add1, 6
+ ret i64 %sub1
+}
+
+define i64 @C2MinusAPlusC1(i64 %a) {
+; CHECK-LABEL: C2MinusAPlusC1:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov w8, #3 // =0x3
+; CHECK-NEXT: sub x0, x8, x0
+; CHECK-NEXT: ret
+entry:
+; fold C2-(A+C1) -> (C2-C1)-A
+ %add1 = add i64 %a, 6
+ %sub1 = sub i64 9, %add1
+ ret i64 %sub1
+}
+
+define i64 @AMinusC1MinusC2(i64 %a) {
+; CHECK-LABEL: AMinusC1MinusC2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: sub x0, x0, #15
+; CHECK-NEXT: ret
+entry:
+; fold (A-C1)-C2 -> A-(C1+C2)
+ %sub2 = sub i64 %a, 6
+ %sub1 = sub i64 %sub2, 9
+ ret i64 %sub1
+}
+
+define i64 @C1Minus2MinusC2(i64 %a) {
+; CHECK-LABEL: C1Minus2MinusC2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: mov w8, #3 // =0x3
+; CHECK-NEXT: sub x0, x8, x0
+; CHECK-NEXT: ret
+entry:
+; fold (C1-A)-C2 -> (C1-C2)-A
+ %sub2 = sub i64 14, %a
+ %sub1 = sub i64 %sub2, 11
+ ret i64 %sub1
+}
+
+define i64 @AMinusC2PlusC2(i64 %a) {
+; CHECK-LABEL: AMinusC2PlusC2:
+; CHECK: // %bb.0: // %entry
+; CHECK-NEXT: sub x0, x0, #4
+; CHECK-NEXT: ret
+entry:
+; fold ((A-C1)+C2) -> (A+(C2-C1))
+ %sub1 = sub i64 %a, 21
+ %add1 = add i64 %sub1, 17
+ ret i64 %add1
+}
+
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK-GI: {{.*}}
+; CHECK-SD: {{.*}}
>From 490ef262a9a3733d3b42811b0abe614e6891f8bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Fri, 19 Jul 2024 14:23:01 +0200
Subject: [PATCH 4/5] removed comments
---
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 88441a5de62c7..553d23a9a5887 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7443,12 +7443,10 @@ bool CombinerHelper::matchFoldAPlusC1MinusC2(const MachineInstr &MI,
if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub->getRHSReg(), MRI);
if (!MaybeC2)
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC1 = getIConstantVRegVal(Add->getRHSReg(), MRI);
if (!MaybeC1)
return false;
@@ -7473,12 +7471,10 @@ bool CombinerHelper::matchFoldC2MinusAPlusC1(const MachineInstr &MI,
if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub->getLHSReg(), MRI);
if (!MaybeC2)
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC1 = getIConstantVRegVal(Add->getRHSReg(), MRI);
if (!MaybeC1)
return false;
@@ -7503,12 +7499,10 @@ bool CombinerHelper::matchFoldAMinusC1MinusC2(const MachineInstr &MI,
if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub1->getRHSReg(), MRI);
if (!MaybeC2)
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub2->getRHSReg(), MRI);
if (!MaybeC1)
return false;
@@ -7533,12 +7527,10 @@ bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI,
if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC2 = getIConstantVRegVal(Sub1->getRHSReg(), MRI);
if (!MaybeC2)
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub2->getLHSReg(), MRI);
if (!MaybeC1)
return false;
@@ -7563,12 +7555,10 @@ bool CombinerHelper::matchFoldAMinusC2PlusC2(const MachineInstr &MI,
if (!MRI.hasOneNonDBGUse(Sub->getReg(0)))
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC2 = getIConstantVRegVal(Add->getRHSReg(), MRI);
if (!MaybeC2)
return false;
- // Cannot fail due to pattern.
std::optional<APInt> MaybeC1 = getIConstantVRegVal(Sub->getRHSReg(), MRI);
if (!MaybeC1)
return false;
>From 89d058d444e5817ff1f1041130fb8967f8e293d4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thorsten=20Sch=C3=BCtt?= <schuett at gmail.com>
Date: Mon, 5 Aug 2024 18:06:28 +0200
Subject: [PATCH 5/5] small fix
---
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h | 3 ++-
llvm/include/llvm/Target/GlobalISel/Combine.td | 6 +++---
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp | 2 +-
3 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index 48b3c3c381763..c76a54ed26ed5 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -900,7 +900,8 @@ class CombinerHelper {
bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
- bool matchFoldAMinusC2PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
+ // fold ((A-C1)+C2) -> (A+(C2-C1))
+ bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
private:
/// Checks for legality of an indexed variant of \p LdSt.
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index 10028ce1a8aa6..54fb14d24b48e 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -1788,13 +1788,13 @@ def C1Minus2MinusC2: GICombineRule<
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
// fold ((A-C1)+C2) -> (A+(C2-C1))
-def AMinusC2PlusC2: GICombineRule<
+def AMinusC1PlusC2: GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (G_CONSTANT $c2, $imm2),
(G_CONSTANT $c1, $imm1),
(G_SUB $sub, $A, $c1),
(G_ADD $root, $sub, $c2):$root,
- [{ return Helper.matchFoldAMinusC2PlusC2(*${root}, ${matchinfo}); }]),
+ [{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
def integer_reassoc_combines: GICombineGroup<[
@@ -1810,7 +1810,7 @@ def integer_reassoc_combines: GICombineGroup<[
C2MinusAPlusC1,
AMinusC1MinusC2,
C1Minus2MinusC2,
- AMinusC2PlusC2
+ AMinusC1PlusC2
]>;
def freeze_of_non_undef_non_poison : GICombineRule<
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 553d23a9a5887..01b01ce525818 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -7546,7 +7546,7 @@ bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI,
return true;
}
-bool CombinerHelper::matchFoldAMinusC2PlusC2(const MachineInstr &MI,
+bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
BuildFnTy &MatchInfo) {
// fold ((A-C1)+C2) -> (A+(C2-C1))
const GAdd *Add = cast<GAdd>(&MI);
More information about the llvm-commits
mailing list