Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GlobalISel] Combine G_UNMERGE_VALUES with anyext and build vector #112370

Merged
merged 9 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 4 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
Original file line number Diff line number Diff line change
Expand Up @@ -918,6 +918,10 @@ class CombinerHelper {
bool matchCanonicalizeICmp(const MachineInstr &MI, BuildFnTy &MatchInfo);
bool matchCanonicalizeFCmp(const MachineInstr &MI, BuildFnTy &MatchInfo);

// unmerge_values(anyext(build vector)) -> build vector(anyext)
bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
BuildFnTy &MatchInfo);

private:
/// Checks for legality of an indexed variant of \p LdSt.
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
Expand Down
8 changes: 8 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -868,6 +868,14 @@ class GZext : public GCastOp {
};
};

/// Represents an any ext.
class GAnyExt : public GCastOp {
public:
static bool classof(const MachineInstr *MI) {
return MI->getOpcode() == TargetOpcode::G_ANYEXT;
};
};

/// Represents a trunc.
class GTrunc : public GCastOp {
public:
Expand Down
31 changes: 23 additions & 8 deletions llvm/include/llvm/Target/GlobalISel/Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -420,15 +420,15 @@ def unary_undef_to_zero: GICombineRule<
// replaced with undef.
def propagate_undef_any_op: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC, G_BITCAST):$root,
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC, G_BITCAST, G_ANYEXT):$root,
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;

// Instructions where if all source operands are undef, the instruction can be
// replaced with undef.
def propagate_undef_all_ops: GICombineRule<
(defs root:$root),
(match (wip_match_opcode G_SHUFFLE_VECTOR):$root,
(match (wip_match_opcode G_SHUFFLE_VECTOR, G_BUILD_VECTOR):$root,
[{ return Helper.matchAllExplicitUsesAreUndef(*${root}); }]),
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;

Expand Down Expand Up @@ -832,6 +832,14 @@ def unmerge_dead_to_trunc : GICombineRule<
(apply [{ Helper.applyCombineUnmergeWithDeadLanesToTrunc(*${d}); }])
>;

// Transform unmerge any build vector -> build vector anyext
def unmerge_anyext_build_vector : GICombineRule<
(defs root:$root, build_fn_matchinfo:$matchinfo),
(match (wip_match_opcode G_UNMERGE_VALUES): $root,
[{ return Helper.matchUnmergeValuesAnyExtBuildVector(*${root}, ${matchinfo}); }]),
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
>;

// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0.
def unmerge_zext_to_zext : GICombineRule<
(defs root:$d),
Expand All @@ -840,6 +848,16 @@ def unmerge_zext_to_zext : GICombineRule<
(apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }])
>;

def merge_combines: GICombineGroup<[
unmerge_anyext_build_vector,
unmerge_merge,
merge_unmerge,
unmerge_cst,
unmerge_undef,
unmerge_dead_to_trunc,
unmerge_zext_to_zext
]>;

// Under certain conditions, transform:
// trunc (shl x, K) -> shl (trunc x), K//
// trunc ([al]shr x, K) -> (trunc ([al]shr (trunc x), K))
Expand Down Expand Up @@ -1851,7 +1869,6 @@ def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
propagate_undef_all_ops,
propagate_undef_shuffle_mask,
erase_undef_store,
unmerge_undef,
insert_extract_vec_elt_out_of_bounds]>;

def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
Expand Down Expand Up @@ -1909,22 +1926,20 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
reassocs, ptr_add_immed_chain, cmp_combines,
shl_ashr_to_sext_inreg, sext_inreg_of_load,
width_reduction_combines, select_combines,
known_bits_simplifications,
known_bits_simplifications, trunc_shift,
not_cmp_fold, opt_brcond_by_inverting_cond,
unmerge_merge, unmerge_cst, unmerge_dead_to_trunc,
unmerge_zext_to_zext, merge_unmerge, trunc_shift,
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift,
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
constant_fold_cast_op, 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,
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
combine_concat_vector, match_addos,
sext_trunc, zext_trunc, prefer_sign_combines, combine_shuffle_concat,
combine_use_vector_truncate]>;
combine_use_vector_truncate, merge_combines]>;

// 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
82 changes: 82 additions & 0 deletions llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7611,3 +7611,85 @@ bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,

return true;
}

bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
BuildFnTy &MatchInfo) {
const GUnmerge *Unmerge = cast<GUnmerge>(&MI);

if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
return false;

const MachineInstr *Source = MRI.getVRegDef(Unmerge->getSourceReg());

LLT DstTy = MRI.getType(Unmerge->getReg(0));

// $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
// $any:_(<8 x s16>) = G_ANYEXT $bv
// $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
//
// ->
//
// $any:_(s16) = G_ANYEXT $bv[0]
// $any1:_(s16) = G_ANYEXT $bv[1]
// $any2:_(s16) = G_ANYEXT $bv[2]
// $any3:_(s16) = G_ANYEXT $bv[3]
// $any4:_(s16) = G_ANYEXT $bv[4]
// $any5:_(s16) = G_ANYEXT $bv[5]
// $any6:_(s16) = G_ANYEXT $bv[6]
// $any7:_(s16) = G_ANYEXT $bv[7]
// $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
// $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7

// We want to unmerge into vectors.
if (!DstTy.isFixedVector())
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.

DAG style comment for the pattern?

Copy link
Author

Choose a reason for hiding this comment

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

Is the doc sufficient?

const GAnyExt *Any = dyn_cast<GAnyExt>(Source);
if (!Any)
return false;

const MachineInstr *NextSource = MRI.getVRegDef(Any->getSrcReg());

if (const GBuildVector *BV = dyn_cast<GBuildVector>(NextSource)) {
// G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR

if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
return false;

// FIXME: check element types?
if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
return false;

LLT BigBvTy = MRI.getType(BV->getReg(0));
LLT SmallBvTy = DstTy;
LLT SmallBvElemenTy = SmallBvTy.getElementType();

if (!isLegalOrBeforeLegalizer(
{TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
return false;

// We check the legality of scalar anyext.
if (!isLegalOrBeforeLegalizer(
{TargetOpcode::G_ANYEXT,
{SmallBvElemenTy, BigBvTy.getElementType()}}))
return false;

MatchInfo = [=](MachineIRBuilder &B) {
// Build into each G_UNMERGE_VALUES def
// a small build vector with anyext from the source build vector.
for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
SmallVector<Register> Ops;
for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
Register SourceArray =
BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
Ops.push_back(AnyExt.getReg(0));
}
B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
};
};
return true;
};

return false;
}
4 changes: 2 additions & 2 deletions llvm/lib/Target/AArch64/AArch64Combine.td
Original file line number Diff line number Diff line change
Expand Up @@ -322,13 +322,13 @@ def AArch64PostLegalizerCombiner
extractvecelt_pairwise_add, redundant_or,
mul_const, redundant_sext_inreg,
form_bitfield_extract, rotate_out_of_range,
icmp_to_true_false_known_bits, merge_unmerge,
icmp_to_true_false_known_bits,
select_combines, fold_merge_to_zext,
constant_fold_binops, identity_combines,
ptr_add_immed_chain, overlapping_and,
split_store_zero_128, undef_combines,
select_to_minmax, or_to_bsp, combine_concat_vector,
commute_constant_to_rhs,
commute_constant_to_rhs, merge_combines,
push_freeze_to_prevent_poison_from_propagating,
combine_mul_cmlt, combine_use_vector_truncate]> {
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,27 @@ liveins:
body: |
; CHECK-LABEL: name: shift_immed_chain_mismatch_size_crash
; CHECK: bb.0:
; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000)
; CHECK: liveins: $x0
; CHECK: [[DEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
; CHECK: [[DEF1:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 9
; CHECK: G_BRCOND [[DEF]](s1), %bb.2
; CHECK: G_BR %bb.1
; CHECK: bb.1:
; CHECK: successors:
; CHECK: bb.2:
; CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF1]](p0) :: (load (s32) from `ptr undef`, align 8)
; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
; CHECK: [[SHL:%[0-9]+]]:_(s32) = nsw G_SHL [[LOAD]], [[C1]](s32)
; CHECK: [[MUL:%[0-9]+]]:_(s32) = nsw G_MUL [[SHL]], [[C]]
; CHECK: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s64)
; CHECK: $w0 = COPY [[SHL1]](s32)
; CHECK: RET_ReallyLR implicit $w0
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
; CHECK-NEXT: liveins: $x0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 9
; CHECK-NEXT: G_BRCOND [[DEF]](s1), %bb.2
; CHECK-NEXT: G_BR %bb.1
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.1:
; CHECK-NEXT: successors:
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: bb.2:
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF1]](p0) :: (load (s32) from `ptr undef`, align 8)
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = nsw G_SHL [[LOAD]], [[C1]](s32)
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = nsw G_MUL [[SHL]], [[C]]
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s64)
; CHECK-NEXT: $w0 = COPY [[SHL1]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
bb.1:
liveins: $x0

Expand Down
15 changes: 6 additions & 9 deletions llvm/test/CodeGen/AArch64/GlobalISel/combine-shifts-undef.mir
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ body: |
; CHECK-LABEL: name: shl_by_ge_bw
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%1:_(s32) = COPY $w0
%0:_(s16) = G_TRUNC %1(s32)
Expand All @@ -39,9 +38,8 @@ body: |
; CHECK-LABEL: name: lshr_by_ge_bw
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%1:_(s32) = COPY $w0
%0:_(s16) = G_TRUNC %1(s32)
Expand All @@ -65,9 +63,8 @@ body: |
; CHECK-LABEL: name: ashr_by_ge_bw
; CHECK: liveins: $w0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
; CHECK-NEXT: RET_ReallyLR implicit $w0
%1:_(s32) = COPY $w0
%0:_(s16) = G_TRUNC %1(s32)
Expand Down
Loading
Loading