Skip to content

Commit 3cac26f

Browse files
authored
[GISel] Combine (neg (min/max x, (neg x))) into (max/min x, (neg x)) (#120998)
This is the GISel version of #120666. Also supports both unsigned and signed version of min & max.
1 parent 2291d0a commit 3cac26f

File tree

7 files changed

+515
-2
lines changed

7 files changed

+515
-2
lines changed

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,9 @@ class CombinerHelper {
864864
/// Combine select to integer min/max.
865865
bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const;
866866

867+
/// Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
868+
bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const;
869+
867870
/// Combine selects.
868871
bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const;
869872

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,10 @@ void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
171171
MachineOptimizationRemarkEmitter &MORE,
172172
MachineOptimizationRemarkMissed &R);
173173

174+
/// Returns the inverse opcode of \p MinMaxOpc, which is a generic min/max
175+
/// opcode like G_SMIN.
176+
unsigned getInverseGMinMaxOpcode(unsigned MinMaxOpc);
177+
174178
/// If \p VReg is defined by a G_CONSTANT, return the corresponding value.
175179
std::optional<APInt> getIConstantVRegVal(Register VReg,
176180
const MachineRegisterInfo &MRI);

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,6 +1372,12 @@ def select_to_iminmax: GICombineRule<
13721372
[{ return Helper.matchSelectIMinMax(${root}, ${info}); }]),
13731373
(apply [{ Helper.applyBuildFnMO(${root}, ${info}); }])>;
13741374

1375+
def simplify_neg_minmax : GICombineRule<
1376+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1377+
(match (wip_match_opcode G_SUB):$root,
1378+
[{ return Helper.matchSimplifyNegMinMax(*${root}, ${matchinfo}); }]),
1379+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1380+
13751381
def match_selects : GICombineRule<
13761382
(defs root:$root, build_fn_matchinfo:$matchinfo),
13771383
(match (wip_match_opcode G_SELECT):$root,
@@ -2008,7 +2014,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
20082014
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
20092015
sub_add_reg, select_to_minmax,
20102016
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
2011-
combine_concat_vector,
2017+
simplify_neg_minmax, combine_concat_vector,
20122018
sext_trunc, zext_trunc, prefer_sign_combines, shuffle_combines,
20132019
combine_use_vector_truncate, merge_combines, overflow_combines]>;
20142020

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7062,6 +7062,34 @@ bool CombinerHelper::matchSelectIMinMax(const MachineOperand &MO,
70627062
}
70637063
}
70647064

7065+
// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
7066+
bool CombinerHelper::matchSimplifyNegMinMax(MachineInstr &MI,
7067+
BuildFnTy &MatchInfo) const {
7068+
assert(MI.getOpcode() == TargetOpcode::G_SUB);
7069+
Register DestReg = MI.getOperand(0).getReg();
7070+
LLT DestTy = MRI.getType(DestReg);
7071+
7072+
Register X;
7073+
Register Sub0;
7074+
auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
7075+
if (mi_match(DestReg, MRI,
7076+
m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
7077+
m_GSMax(m_Reg(X), NegPattern),
7078+
m_GUMin(m_Reg(X), NegPattern),
7079+
m_GUMax(m_Reg(X), NegPattern)))))) {
7080+
MachineInstr *MinMaxMI = MRI.getVRegDef(MI.getOperand(2).getReg());
7081+
unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
7082+
if (isLegal({NewOpc, {DestTy}})) {
7083+
MatchInfo = [=](MachineIRBuilder &B) {
7084+
B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
7085+
};
7086+
return true;
7087+
}
7088+
}
7089+
7090+
return false;
7091+
}
7092+
70657093
bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const {
70667094
GSelect *Select = cast<GSelect>(&MI);
70677095

llvm/lib/CodeGen/GlobalISel/Utils.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,21 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
276276
reportGISelFailure(MF, TPC, MORE, R);
277277
}
278278

279+
unsigned llvm::getInverseGMinMaxOpcode(unsigned MinMaxOpc) {
280+
switch (MinMaxOpc) {
281+
case TargetOpcode::G_SMIN:
282+
return TargetOpcode::G_SMAX;
283+
case TargetOpcode::G_SMAX:
284+
return TargetOpcode::G_SMIN;
285+
case TargetOpcode::G_UMIN:
286+
return TargetOpcode::G_UMAX;
287+
case TargetOpcode::G_UMAX:
288+
return TargetOpcode::G_UMIN;
289+
default:
290+
llvm_unreachable("unrecognized opcode");
291+
}
292+
}
293+
279294
std::optional<APInt> llvm::getIConstantVRegVal(Register VReg,
280295
const MachineRegisterInfo &MRI) {
281296
std::optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough(

llvm/lib/Target/RISCV/RISCVCombine.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ def RISCVPostLegalizerCombiner
2525
: GICombiner<"RISCVPostLegalizerCombinerImpl",
2626
[sub_to_add, combines_for_extload, redundant_and,
2727
identity_combines, shift_immed_chain,
28-
commute_constant_to_rhs]> {
28+
commute_constant_to_rhs, simplify_neg_minmax]> {
2929
}

0 commit comments

Comments
 (0)