Skip to content

Commit

Permalink
[GlobalIsel] Combine G_SELECT
Browse files Browse the repository at this point in the history
Cleanups, preparation for more combines, add known bits for constant
conditions, combine selects where the false and true register are
constants, and improve support for vector conditions.

AMDGPU supports vector conditions. X86 has a todo for vector
conditions. AArch64 SVE supports SEL for vector conditions. How to
implement vector conditions with NEON (with bsl), see arm64-vselect.ll
? Vector select asserts in the instruction selector.

buildNot does not support scalable vectors. We cannot create scalable
constant vectors of -1 and there is no G_Not. AArch64 SVE has a NOT
and a DUP for broadcasting. Something akin to G_CONSTANT_SPLAT,
G_CONSTANT_VECTOR, G_SPLAT_VECTOR, G_BRODCAST, or G_HOMOGENOUS_VECTOR
that takes an immediate and creates a (fixed or scalable) vector where
all elements are the immediate might solve the buildNot challenge,
facilitates new combines, pattern matching, and new selecting
optimizations.

P.S. We need to support integer and float.

llvm#74502

```c
<vscale x 4 x i32> splat (i32 -1)
```
  • Loading branch information
tschuett committed Dec 8, 2023
1 parent 04c4566 commit 3fbe241
Show file tree
Hide file tree
Showing 31 changed files with 5,247 additions and 4,251 deletions.
28 changes: 18 additions & 10 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -423,16 +423,9 @@ class CombinerHelper {
/// Return true if a G_STORE instruction \p MI is storing an undef value.
bool matchUndefStore(MachineInstr &MI);

/// Return true if a G_SELECT instruction \p MI has an undef comparison.
bool matchUndefSelectCmp(MachineInstr &MI);

/// Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
bool matchInsertExtractVecEltOutOfBounds(MachineInstr &MI);

/// Return true if a G_SELECT instruction \p MI has a constant comparison. If
/// true, \p OpIdx will store the operand index of the known selected value.
bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx);

/// Replace an instruction with a G_FCONSTANT with value \p C.
void replaceInstWithFConstant(MachineInstr &MI, double C);

Expand Down Expand Up @@ -771,9 +764,6 @@ class CombinerHelper {
bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI,
BuildFnTy &MatchInfo);

/// Fold boolean selects to logical operations.
bool matchSelectToLogical(MachineInstr &MI, BuildFnTy &MatchInfo);

bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info);

/// Transform G_ADD(x, G_SUB(y, x)) to y.
Expand Down Expand Up @@ -816,6 +806,9 @@ class CombinerHelper {
// Given a binop \p MI, commute operands 1 and 2.
void applyCommuteBinOpOperands(MachineInstr &MI);

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

private:
/// Checks for legality of an indexed variant of \p LdSt.
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
Expand Down Expand Up @@ -906,6 +899,21 @@ class CombinerHelper {
/// select (fcmp uge x, 1.0) 1.0, x -> fminnm x, 1.0
bool matchFPSelectToMinMax(Register Dst, Register Cond, Register TrueVal,
Register FalseVal, BuildFnTy &MatchInfo);

bool isOneOrOneSplat(Register Src, bool AllowUndefs);
bool isZeroOrZeroSplat(Register Src, bool AllowUndefs);
bool isConstantSplatVector(Register Src, int64_t SplatValue,
bool AllowUndefs);
std::optional<APInt> getConstantOrConstantSplatVector(Register Src);

/// Try to combine selects with constant conditions.
bool tryCombineSelectConstantCondition(GSelect *Select, BuildFnTy &MatchInfo);

/// Try to combine selects with boolean conditions to logical operators.
bool tryFoldBoolSelectToLogic(GSelect *Select, BuildFnTy &MatchInfo);

/// Try to combine selects where the true and false values are constant.
bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo);
};
} // namespace llvm

Expand Down
10 changes: 5 additions & 5 deletions llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -1701,11 +1701,11 @@ class MachineIRBuilder {

/// Build and insert a bitwise not,
/// \p NegOne = G_CONSTANT -1
/// \p Res = G_OR \p Op0, NegOne
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0) {
auto NegOne = buildConstant(Dst.getLLTTy(*getMRI()), -1);
return buildInstr(TargetOpcode::G_XOR, {Dst}, {Src0, NegOne});
}
/// \p Res = G_XOR \p Op0, NegOne
/// Or
/// \p NegOne = G_BUILD_VECTOR -1, -1, -1, ...
/// \p Res = G_XOR \p Op0, NegOne
MachineInstrBuilder buildNot(const DstOp &Dst, const SrcOp &Src0);

/// Build and insert integer negation
/// \p Zero = G_CONSTANT 0
Expand Down
34 changes: 7 additions & 27 deletions llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -419,31 +419,6 @@ def select_same_val: GICombineRule<
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
>;

// Fold (undef ? x : y) -> y
def select_undef_cmp: GICombineRule<
(defs root:$dst),
(match (G_IMPLICIT_DEF $undef),
(G_SELECT $dst, $undef, $x, $y)),
(apply (GIReplaceReg $dst, $y))
>;

// Fold (true ? x : y) -> x
// Fold (false ? x : y) -> y
def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">;
def select_constant_cmp: GICombineRule<
(defs root:$root, select_constant_cmp_matchdata:$matchinfo),
(match (wip_match_opcode G_SELECT):$root,
[{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]),
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
>;

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

// Fold (C op x) -> (x op C)
// TODO: handle more isCommutable opcodes
// TODO: handle compares (currently not marked as isCommutable)
Expand Down Expand Up @@ -1242,6 +1217,12 @@ def select_to_minmax: GICombineRule<
[{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;

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

// FIXME: These should use the custom predicate feature once it lands.
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
undef_to_negative_one,
Expand Down Expand Up @@ -1281,8 +1262,7 @@ def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend,

def phi_combines : GICombineGroup<[extend_through_phis]>;

def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp,
select_to_logical]>;
def select_combines : GICombineGroup<[match_selects]>;

def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
mul_by_neg_one, idempotent_prop]>;
Expand Down

0 comments on commit 3fbe241

Please sign in to comment.