Skip to content

Commit 6b77531

Browse files
author
Thorsten Schütt
authored
[GlobalIsel] Combine G_ADD and G_SUB with constants (#97771)
1 parent edf45e4 commit 6b77531

File tree

8 files changed

+399
-23
lines changed

8 files changed

+399
-23
lines changed

llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -892,6 +892,16 @@ class CombinerHelper {
892892

893893
bool matchCastOfSelect(const MachineInstr &Cast, const MachineInstr &SelectMI,
894894
BuildFnTy &MatchInfo);
895+
bool matchFoldAPlusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
896+
897+
bool matchFoldC2MinusAPlusC1(const MachineInstr &MI, BuildFnTy &MatchInfo);
898+
899+
bool matchFoldAMinusC1MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
900+
901+
bool matchFoldC1Minus2MinusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
902+
903+
// fold ((A-C1)+C2) -> (A+(C2-C1))
904+
bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
895905

896906
private:
897907
/// Checks for legality of an indexed variant of \p LdSt.

llvm/include/llvm/CodeGen/GlobalISel/Utils.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/IR/DebugLoc.h"
2323
#include "llvm/Support/Alignment.h"
2424
#include "llvm/Support/Casting.h"
25+
2526
#include <cstdint>
2627

2728
namespace llvm {
@@ -178,6 +179,9 @@ std::optional<APInt> getIConstantVRegVal(Register VReg,
178179
std::optional<int64_t> getIConstantVRegSExtVal(Register VReg,
179180
const MachineRegisterInfo &MRI);
180181

182+
/// \p VReg is defined by a G_CONSTANT, return the corresponding value.
183+
APInt getIConstantFromReg(Register VReg, const MachineRegisterInfo &MRI);
184+
181185
/// Simple struct used to hold a constant integer value and a virtual
182186
/// register.
183187
struct ValueAndVReg {

llvm/include/llvm/Target/GlobalISel/Combine.td

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,56 @@ def APlusBMinusCPlusA : GICombineRule<
17471747
(G_ADD $root, $A, $sub1)),
17481748
(apply (G_SUB $root, $B, $C))>;
17491749

1750+
// fold (A+C1)-C2 -> A+(C1-C2)
1751+
def APlusC1MinusC2: GICombineRule<
1752+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1753+
(match (G_CONSTANT $c2, $imm2),
1754+
(G_CONSTANT $c1, $imm1),
1755+
(G_ADD $add, $A, $c1),
1756+
(G_SUB $root, $add, $c2):$root,
1757+
[{ return Helper.matchFoldAPlusC1MinusC2(*${root}, ${matchinfo}); }]),
1758+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1759+
1760+
// fold C2-(A+C1) -> (C2-C1)-A
1761+
def C2MinusAPlusC1: GICombineRule<
1762+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1763+
(match (G_CONSTANT $c2, $imm2),
1764+
(G_CONSTANT $c1, $imm1),
1765+
(G_ADD $add, $A, $c1),
1766+
(G_SUB $root, $c2, $add):$root,
1767+
[{ return Helper.matchFoldC2MinusAPlusC1(*${root}, ${matchinfo}); }]),
1768+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1769+
1770+
// fold (A-C1)-C2 -> A-(C1+C2)
1771+
def AMinusC1MinusC2: GICombineRule<
1772+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1773+
(match (G_CONSTANT $c2, $imm2),
1774+
(G_CONSTANT $c1, $imm1),
1775+
(G_SUB $sub1, $A, $c1),
1776+
(G_SUB $root, $sub1, $c2):$root,
1777+
[{ return Helper.matchFoldAMinusC1MinusC2(*${root}, ${matchinfo}); }]),
1778+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1779+
1780+
// fold (C1-A)-C2 -> (C1-C2)-A
1781+
def C1Minus2MinusC2: GICombineRule<
1782+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1783+
(match (G_CONSTANT $c2, $imm2),
1784+
(G_CONSTANT $c1, $imm1),
1785+
(G_SUB $sub1, $c1, $A),
1786+
(G_SUB $root, $sub1, $c2):$root,
1787+
[{ return Helper.matchFoldC1Minus2MinusC2(*${root}, ${matchinfo}); }]),
1788+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1789+
1790+
// fold ((A-C1)+C2) -> (A+(C2-C1))
1791+
def AMinusC1PlusC2: GICombineRule<
1792+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1793+
(match (G_CONSTANT $c2, $imm2),
1794+
(G_CONSTANT $c1, $imm1),
1795+
(G_SUB $sub, $A, $c1),
1796+
(G_ADD $root, $sub, $c2):$root,
1797+
[{ return Helper.matchFoldAMinusC1PlusC2(*${root}, ${matchinfo}); }]),
1798+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1799+
17501800
def integer_reassoc_combines: GICombineGroup<[
17511801
ZeroMinusAPlusB,
17521802
APlusZeroMinusB,
@@ -1755,7 +1805,12 @@ def integer_reassoc_combines: GICombineGroup<[
17551805
AMinusBPlusCMinusA,
17561806
AMinusBPlusBMinusC,
17571807
APlusBMinusAplusC,
1758-
APlusBMinusCPlusA
1808+
APlusBMinusCPlusA,
1809+
APlusC1MinusC2,
1810+
C2MinusAPlusC1,
1811+
AMinusC1MinusC2,
1812+
C1Minus2MinusC2,
1813+
AMinusC1PlusC2
17591814
]>;
17601815

17611816
def freeze_of_non_undef_non_poison : GICombineRule<

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7433,3 +7433,118 @@ void CombinerHelper::applyExpandFPowI(MachineInstr &MI, int64_t Exponent) {
74337433
Builder.buildCopy(Dst, *Res);
74347434
MI.eraseFromParent();
74357435
}
7436+
7437+
bool CombinerHelper::matchFoldAPlusC1MinusC2(const MachineInstr &MI,
7438+
BuildFnTy &MatchInfo) {
7439+
// fold (A+C1)-C2 -> A+(C1-C2)
7440+
const GSub *Sub = cast<GSub>(&MI);
7441+
GAdd *Add = cast<GAdd>(MRI.getVRegDef(Sub->getLHSReg()));
7442+
7443+
if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
7444+
return false;
7445+
7446+
APInt C2 = getIConstantFromReg(Sub->getRHSReg(), MRI);
7447+
APInt C1 = getIConstantFromReg(Add->getRHSReg(), MRI);
7448+
7449+
Register Dst = Sub->getReg(0);
7450+
LLT DstTy = MRI.getType(Dst);
7451+
7452+
MatchInfo = [=](MachineIRBuilder &B) {
7453+
auto Const = B.buildConstant(DstTy, C1 - C2);
7454+
B.buildAdd(Dst, Add->getLHSReg(), Const);
7455+
};
7456+
7457+
return true;
7458+
}
7459+
7460+
bool CombinerHelper::matchFoldC2MinusAPlusC1(const MachineInstr &MI,
7461+
BuildFnTy &MatchInfo) {
7462+
// fold C2-(A+C1) -> (C2-C1)-A
7463+
const GSub *Sub = cast<GSub>(&MI);
7464+
GAdd *Add = cast<GAdd>(MRI.getVRegDef(Sub->getRHSReg()));
7465+
7466+
if (!MRI.hasOneNonDBGUse(Add->getReg(0)))
7467+
return false;
7468+
7469+
APInt C2 = getIConstantFromReg(Sub->getLHSReg(), MRI);
7470+
APInt C1 = getIConstantFromReg(Add->getRHSReg(), MRI);
7471+
7472+
Register Dst = Sub->getReg(0);
7473+
LLT DstTy = MRI.getType(Dst);
7474+
7475+
MatchInfo = [=](MachineIRBuilder &B) {
7476+
auto Const = B.buildConstant(DstTy, C2 - C1);
7477+
B.buildSub(Dst, Const, Add->getLHSReg());
7478+
};
7479+
7480+
return true;
7481+
}
7482+
7483+
bool CombinerHelper::matchFoldAMinusC1MinusC2(const MachineInstr &MI,
7484+
BuildFnTy &MatchInfo) {
7485+
// fold (A-C1)-C2 -> A-(C1+C2)
7486+
const GSub *Sub1 = cast<GSub>(&MI);
7487+
GSub *Sub2 = cast<GSub>(MRI.getVRegDef(Sub1->getLHSReg()));
7488+
7489+
if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
7490+
return false;
7491+
7492+
APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
7493+
APInt C1 = getIConstantFromReg(Sub2->getRHSReg(), MRI);
7494+
7495+
Register Dst = Sub1->getReg(0);
7496+
LLT DstTy = MRI.getType(Dst);
7497+
7498+
MatchInfo = [=](MachineIRBuilder &B) {
7499+
auto Const = B.buildConstant(DstTy, C1 + C2);
7500+
B.buildSub(Dst, Sub2->getLHSReg(), Const);
7501+
};
7502+
7503+
return true;
7504+
}
7505+
7506+
bool CombinerHelper::matchFoldC1Minus2MinusC2(const MachineInstr &MI,
7507+
BuildFnTy &MatchInfo) {
7508+
// fold (C1-A)-C2 -> (C1-C2)-A
7509+
const GSub *Sub1 = cast<GSub>(&MI);
7510+
GSub *Sub2 = cast<GSub>(MRI.getVRegDef(Sub1->getLHSReg()));
7511+
7512+
if (!MRI.hasOneNonDBGUse(Sub2->getReg(0)))
7513+
return false;
7514+
7515+
APInt C2 = getIConstantFromReg(Sub1->getRHSReg(), MRI);
7516+
APInt C1 = getIConstantFromReg(Sub2->getLHSReg(), MRI);
7517+
7518+
Register Dst = Sub1->getReg(0);
7519+
LLT DstTy = MRI.getType(Dst);
7520+
7521+
MatchInfo = [=](MachineIRBuilder &B) {
7522+
auto Const = B.buildConstant(DstTy, C1 - C2);
7523+
B.buildSub(Dst, Const, Sub2->getRHSReg());
7524+
};
7525+
7526+
return true;
7527+
}
7528+
7529+
bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
7530+
BuildFnTy &MatchInfo) {
7531+
// fold ((A-C1)+C2) -> (A+(C2-C1))
7532+
const GAdd *Add = cast<GAdd>(&MI);
7533+
GSub *Sub = cast<GSub>(MRI.getVRegDef(Add->getLHSReg()));
7534+
7535+
if (!MRI.hasOneNonDBGUse(Sub->getReg(0)))
7536+
return false;
7537+
7538+
APInt C2 = getIConstantFromReg(Add->getRHSReg(), MRI);
7539+
APInt C1 = getIConstantFromReg(Sub->getRHSReg(), MRI);
7540+
7541+
Register Dst = Add->getReg(0);
7542+
LLT DstTy = MRI.getType(Dst);
7543+
7544+
MatchInfo = [=](MachineIRBuilder &B) {
7545+
auto Const = B.buildConstant(DstTy, C2 - C1);
7546+
B.buildAdd(Dst, Sub->getLHSReg(), Const);
7547+
};
7548+
7549+
return true;
7550+
}

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ std::optional<APInt> llvm::getIConstantVRegVal(Register VReg,
303303
return ValAndVReg->Value;
304304
}
305305

306+
APInt llvm::getIConstantFromReg(Register Reg, const MachineRegisterInfo &MRI) {
307+
MachineInstr *Const = MRI.getVRegDef(Reg);
308+
assert((Const && Const->getOpcode() == TargetOpcode::G_CONSTANT) &&
309+
"expected a G_CONSTANT on Reg");
310+
return Const->getOperand(1).getCImm()->getValue();
311+
}
312+
306313
std::optional<int64_t>
307314
llvm::getIConstantVRegSExtVal(Register VReg, const MachineRegisterInfo &MRI) {
308315
std::optional<APInt> Val = getIConstantVRegVal(VReg, MRI);

0 commit comments

Comments
 (0)