Skip to content

Commit

Permalink
[GlobalISel] Combine (X op Y) == X --> Y == 0
Browse files Browse the repository at this point in the history
This matches patterns of the form

```
(X op Y) == X
```

And transforms them to

```
Y == 0
```

where appropriate.

Example: https://godbolt.org/z/hfW811c7W

Differential Revision: https://reviews.llvm.org/D135380
  • Loading branch information
Jessica Paquette committed Oct 11, 2022
1 parent 487695e commit 036a130
Show file tree
Hide file tree
Showing 4 changed files with 912 additions and 1 deletion.
9 changes: 9 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,15 @@ class CombinerHelper {
/// to a min/max instruction of some sort.
bool matchSimplifySelectToMinMax(MachineInstr &MI, BuildFnTy &MatchInfo);

/// Transform:
/// (X + Y) == X -> Y == 0
/// (X - Y) == X -> Y == 0
/// (X ^ Y) == X -> Y == 0
/// (X + Y) != X -> Y != 0
/// (X - Y) != X -> Y != 0
/// (X ^ Y) != X -> Y != 0
bool matchRedundantBinOpInEquality(MachineInstr &MI, BuildFnTy &MatchInfo);

private:
/// Given a non-indexed load or store instruction \p MI, find an offset that
/// can be usefully and legally folded into it as a post-indexing operation.
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 @@ -736,6 +736,12 @@ def icmp_to_lhs_known_bits : GICombineRule<
[{ return Helper.matchICmpToLHSKnownBits(*${root}, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;

def redundant_binop_in_equality : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_ICMP):$root,
[{ return Helper.matchRedundantBinOpInEquality(*${root}, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;

def and_or_disjoint_mask : GICombineRule<
(defs root:$root, build_fn_matchinfo:$info),
(match (wip_match_opcode G_AND):$root,
Expand Down Expand Up @@ -1045,7 +1051,7 @@ def all_combines : GICombineGroup<[trivial_combines, insert_vec_elt_combines,
form_bitfield_extract, constant_fold, fabs_fneg_fold,
intdiv_combines, mulh_combines, redundant_neg_operands,
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
sub_add_reg, select_to_minmax]>;
sub_add_reg, select_to_minmax, redundant_binop_in_equality]>;

// 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
Expand Down
33 changes: 33 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetOpcodes.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/DivisionByConstantInfo.h"
#include "llvm/Support/MathExtras.h"
Expand Down Expand Up @@ -6060,6 +6061,38 @@ bool CombinerHelper::matchSimplifySelectToMinMax(MachineInstr &MI,
return matchFPSelectToMinMax(Dst, Cond, TrueVal, FalseVal, MatchInfo);
}

bool CombinerHelper::matchRedundantBinOpInEquality(MachineInstr &MI,
BuildFnTy &MatchInfo) {
assert(MI.getOpcode() == TargetOpcode::G_ICMP);
// (X + Y) == X --> Y == 0
// (X + Y) != X --> Y != 0
// (X - Y) == X --> Y == 0
// (X - Y) != X --> Y != 0
// (X ^ Y) == X --> Y == 0
// (X ^ Y) != X --> Y != 0
Register Dst = MI.getOperand(0).getReg();
CmpInst::Predicate Pred;
Register X, Y, OpLHS, OpRHS;
bool MatchedSub = mi_match(
Dst, MRI,
m_c_GICmp(m_Pred(Pred), m_Reg(X), m_GSub(m_Reg(OpLHS), m_Reg(Y))));
if (MatchedSub && X != OpLHS)
return false;
if (!MatchedSub) {
if (!mi_match(Dst, MRI,
m_c_GICmp(m_Pred(Pred), m_Reg(X),
m_any_of(m_GAdd(m_Reg(OpLHS), m_Reg(OpRHS)),
m_GXor(m_Reg(OpLHS), m_Reg(OpRHS))))))
return false;
Y = X == OpLHS ? OpRHS : X == OpRHS ? OpLHS : Register();
}
MatchInfo = [=](MachineIRBuilder &B) {
auto Zero = B.buildConstant(MRI.getType(Y), 0);
B.buildICmp(Pred, Dst, Y, Zero);
};
return CmpInst::isEquality(Pred) && Y.isValid();
}

bool CombinerHelper::tryCombine(MachineInstr &MI) {
if (tryCombineCopy(MI))
return true;
Expand Down

0 comments on commit 036a130

Please sign in to comment.