Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,9 @@ class CombinerHelper {
/// Combine select to integer min/max.
bool matchSelectIMinMax(const MachineOperand &MO, BuildFnTy &MatchInfo) const;

/// Tranform (neg (min/max x, (neg x))) into (max/min x, (neg x)).
bool matchSimplifyNegMinMax(MachineInstr &MI, BuildFnTy &MatchInfo) const;

/// Combine selects.
bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const;

Expand Down
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,10 @@ void reportGISelWarning(MachineFunction &MF, const TargetPassConfig &TPC,
MachineOptimizationRemarkEmitter &MORE,
MachineOptimizationRemarkMissed &R);

/// Returns the inverse opcode of \p MinMaxOpc, which is a generic min/max
/// opcode like G_SMIN.
unsigned getInverseGMinMaxOpcode(unsigned MinMaxOpc);

/// If \p VReg is defined by a G_CONSTANT, return the corresponding value.
std::optional<APInt> getIConstantVRegVal(Register VReg,
const MachineRegisterInfo &MRI);
Expand Down
8 changes: 7 additions & 1 deletion llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,12 @@ def select_to_iminmax: GICombineRule<
[{ return Helper.matchSelectIMinMax(${root}, ${info}); }]),
(apply [{ Helper.applyBuildFnMO(${root}, ${info}); }])>;

def simplify_neg_minmax : GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (wip_match_opcode G_SUB):$root,
[{ return Helper.matchSimplifyNegMinMax(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;

def match_selects : GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (wip_match_opcode G_SELECT):$root,
Expand Down Expand Up @@ -2008,7 +2014,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
sub_add_reg, select_to_minmax,
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
combine_concat_vector,
simplify_neg_minmax, combine_concat_vector,
sext_trunc, zext_trunc, prefer_sign_combines, shuffle_combines,
combine_use_vector_truncate, merge_combines, overflow_combines]>;

Expand Down
30 changes: 30 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7062,6 +7062,36 @@ bool CombinerHelper::matchSelectIMinMax(const MachineOperand &MO,
}
}

// (neg (min/max x, (neg x))) --> (max/min x, (neg x))
bool CombinerHelper::matchSimplifyNegMinMax(MachineInstr &MI,
BuildFnTy &MatchInfo) const {
assert(MI.getOpcode() == TargetOpcode::G_SUB);
Register DestReg = MI.getOperand(0).getReg();
LLT DestTy = MRI.getType(DestReg);
if (!isLegal({TargetOpcode::G_SUB, {DestTy}}))
return false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this legality check here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops must be left there by accident. It's removed now.


Register X;
Register Sub0;
auto NegPattern = m_all_of(m_Neg(m_DeferredReg(X)), m_Reg(Sub0));
if (mi_match(DestReg, MRI,
m_Neg(m_OneUse(m_any_of(m_GSMin(m_Reg(X), NegPattern),
m_GSMax(m_Reg(X), NegPattern),
m_GUMin(m_Reg(X), NegPattern),
m_GUMax(m_Reg(X), NegPattern)))))) {
MachineInstr *MinMaxMI = MRI.getVRegDef(MI.getOperand(2).getReg());
unsigned NewOpc = getInverseGMinMaxOpcode(MinMaxMI->getOpcode());
if (isLegal({NewOpc, {DestTy}})) {
MatchInfo = [=](MachineIRBuilder &B) {
B.buildInstr(NewOpc, {DestReg}, {X, Sub0});
};
return true;
}
}

return false;
}

bool CombinerHelper::matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo) const {
GSelect *Select = cast<GSelect>(&MI);

Expand Down
15 changes: 15 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,21 @@ void llvm::reportGISelFailure(MachineFunction &MF, const TargetPassConfig &TPC,
reportGISelFailure(MF, TPC, MORE, R);
}

unsigned llvm::getInverseGMinMaxOpcode(unsigned MinMaxOpc) {
switch (MinMaxOpc) {
case TargetOpcode::G_SMIN:
return TargetOpcode::G_SMAX;
case TargetOpcode::G_SMAX:
return TargetOpcode::G_SMIN;
case TargetOpcode::G_UMIN:
return TargetOpcode::G_UMAX;
case TargetOpcode::G_UMAX:
return TargetOpcode::G_UMIN;
default:
llvm_unreachable("unrecognized opcode");
}
}

std::optional<APInt> llvm::getIConstantVRegVal(Register VReg,
const MachineRegisterInfo &MRI) {
std::optional<ValueAndVReg> ValAndVReg = getIConstantVRegValWithLookThrough(
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Target/RISCV/RISCVCombine.td
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ def RISCVPostLegalizerCombiner
: GICombiner<"RISCVPostLegalizerCombinerImpl",
[sub_to_add, combines_for_extload, redundant_and,
identity_combines, shift_immed_chain,
commute_constant_to_rhs]> {
commute_constant_to_rhs, simplify_neg_minmax]> {
}
Loading
Loading