Skip to content

Commit 9131454

Browse files
committed
[GlobalIsel] Combine G_SELECT
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) ```
1 parent a3d2d34 commit 9131454

31 files changed

+5247
-4251
lines changed

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

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -421,16 +421,9 @@ class CombinerHelper {
421421
/// Return true if a G_STORE instruction \p MI is storing an undef value.
422422
bool matchUndefStore(MachineInstr &MI);
423423

424-
/// Return true if a G_SELECT instruction \p MI has an undef comparison.
425-
bool matchUndefSelectCmp(MachineInstr &MI);
426-
427424
/// Return true if a G_{EXTRACT,INSERT}_VECTOR_ELT has an out of range index.
428425
bool matchInsertExtractVecEltOutOfBounds(MachineInstr &MI);
429426

430-
/// Return true if a G_SELECT instruction \p MI has a constant comparison. If
431-
/// true, \p OpIdx will store the operand index of the known selected value.
432-
bool matchConstantSelectCmp(MachineInstr &MI, unsigned &OpIdx);
433-
434427
/// Replace an instruction with a G_FCONSTANT with value \p C.
435428
void replaceInstWithFConstant(MachineInstr &MI, double C);
436429

@@ -769,9 +762,6 @@ class CombinerHelper {
769762
bool matchCombineFSubFpExtFNegFMulToFMadOrFMA(MachineInstr &MI,
770763
BuildFnTy &MatchInfo);
771764

772-
/// Fold boolean selects to logical operations.
773-
bool matchSelectToLogical(MachineInstr &MI, BuildFnTy &MatchInfo);
774-
775765
bool matchCombineFMinMaxNaN(MachineInstr &MI, unsigned &Info);
776766

777767
/// Transform G_ADD(x, G_SUB(y, x)) to y.
@@ -814,6 +804,9 @@ class CombinerHelper {
814804
// Given a binop \p MI, commute operands 1 and 2.
815805
void applyCommuteBinOpOperands(MachineInstr &MI);
816806

807+
// Combine selects.
808+
bool matchSelect(MachineInstr &MI, BuildFnTy &MatchInfo);
809+
817810
private:
818811
/// Checks for legality of an indexed variant of \p LdSt.
819812
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
@@ -904,6 +897,21 @@ class CombinerHelper {
904897
/// select (fcmp uge x, 1.0) 1.0, x -> fminnm x, 1.0
905898
bool matchFPSelectToMinMax(Register Dst, Register Cond, Register TrueVal,
906899
Register FalseVal, BuildFnTy &MatchInfo);
900+
901+
bool isOneOrOneSplat(Register Src, bool AllowUndefs);
902+
bool isZeroOrZeroSplat(Register Src, bool AllowUndefs);
903+
bool isConstantSplatVector(Register Src, int64_t SplatValue,
904+
bool AllowUndefs);
905+
std::optional<APInt> getConstantOrConstantSplatVector(Register Src);
906+
907+
/// Try to combine selects with constant conditions.
908+
bool tryCombineSelectConstantCondition(GSelect *Select, BuildFnTy &MatchInfo);
909+
910+
/// Try to combine selects with boolean conditions to logical operators.
911+
bool tryFoldBoolSelectToLogic(GSelect *Select, BuildFnTy &MatchInfo);
912+
913+
/// Try to combine selects where the true and false values are constant.
914+
bool tryFoldSelectOfConstants(GSelect *Select, BuildFnTy &MatchInfo);
907915
};
908916
} // namespace llvm
909917

llvm/include/llvm/CodeGen/GlobalISel/MachineIRBuilder.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,11 +1706,11 @@ class MachineIRBuilder {
17061706

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

17151715
/// Build and insert integer negation
17161716
/// \p Zero = G_CONSTANT 0

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

Lines changed: 7 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -419,31 +419,6 @@ def select_same_val: GICombineRule<
419419
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, 2); }])
420420
>;
421421

422-
// Fold (undef ? x : y) -> y
423-
def select_undef_cmp: GICombineRule<
424-
(defs root:$dst),
425-
(match (G_IMPLICIT_DEF $undef),
426-
(G_SELECT $dst, $undef, $x, $y)),
427-
(apply (GIReplaceReg $dst, $y))
428-
>;
429-
430-
// Fold (true ? x : y) -> x
431-
// Fold (false ? x : y) -> y
432-
def select_constant_cmp_matchdata : GIDefMatchData<"unsigned">;
433-
def select_constant_cmp: GICombineRule<
434-
(defs root:$root, select_constant_cmp_matchdata:$matchinfo),
435-
(match (wip_match_opcode G_SELECT):$root,
436-
[{ return Helper.matchConstantSelectCmp(*${root}, ${matchinfo}); }]),
437-
(apply [{ Helper.replaceSingleDefInstWithOperand(*${root}, ${matchinfo}); }])
438-
>;
439-
440-
def select_to_logical : GICombineRule<
441-
(defs root:$root, build_fn_matchinfo:$matchinfo),
442-
(match (wip_match_opcode G_SELECT):$root,
443-
[{ return Helper.matchSelectToLogical(*${root}, ${matchinfo}); }]),
444-
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
445-
>;
446-
447422
// Fold (C op x) -> (x op C)
448423
// TODO: handle more isCommutable opcodes
449424
// TODO: handle compares (currently not marked as isCommutable)
@@ -1242,6 +1217,12 @@ def select_to_minmax: GICombineRule<
12421217
[{ return Helper.matchSimplifySelectToMinMax(*${root}, ${info}); }]),
12431218
(apply [{ Helper.applyBuildFn(*${root}, ${info}); }])>;
12441219

1220+
def match_selects : GICombineRule<
1221+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1222+
(match (wip_match_opcode G_SELECT):$root,
1223+
[{ return Helper.matchSelect(*${root}, ${matchinfo}); }]),
1224+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>;
1225+
12451226
// FIXME: These should use the custom predicate feature once it lands.
12461227
def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
12471228
undef_to_negative_one,
@@ -1281,8 +1262,7 @@ def width_reduction_combines : GICombineGroup<[reduce_shl_of_extend,
12811262

12821263
def phi_combines : GICombineGroup<[extend_through_phis]>;
12831264

1284-
def select_combines : GICombineGroup<[select_undef_cmp, select_constant_cmp,
1285-
select_to_logical]>;
1265+
def select_combines : GICombineGroup<[match_selects]>;
12861266

12871267
def trivial_combines : GICombineGroup<[copy_prop, mul_to_shl, add_p2i_to_ptradd,
12881268
mul_by_neg_one, idempotent_prop]>;

0 commit comments

Comments
 (0)