Skip to content

Commit d8b17f2

Browse files
author
Thorsten Schütt
authored
[GlobalISel] Combine G_UNMERGE_VALUES with anyext and build vector (#112370)
G_UNMERGE_VALUES (G_ANYEXT (G_BUILD_VECTOR)) ag G_UNMERGE_VALUES llvm/test/CodeGen/AArch64/GlobalISel | grep ANYEXT [ANYEXT] is build vector or shuffle vector Prior art: https://reviews.llvm.org/D87117 https://reviews.llvm.org/D87166 https://reviews.llvm.org/D87174 https://reviews.llvm.org/D87427 ; CHECK-NEXT: [[BUILD_VECTOR2:%[0-9]+]]:_(<8 x s8>) = G_BUILD_VECTOR [[C2]](s8), [[C2]](s8), [[C2]](s8), [[C2]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8), [[DEF1]](s8) ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(<8 x s16>) = G_ANYEXT [[BUILD_VECTOR2]](<8 x s8>) ; CHECK-NEXT: [[UV10:%[0-9]+]]:_(<4 x s16>), [[UV11:%[0-9]+]]:_(<4 x s16>) = G_UNMERGE_VALUES [[ANYEXT1]](<8 x s16>) Test: llvm/test/CodeGen/AArch64/GlobalISel/combine-unmerge.mir
1 parent 3d84b74 commit d8b17f2

27 files changed

+948
-884
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -918,6 +918,10 @@ class CombinerHelper {
918918
bool matchCanonicalizeICmp(const MachineInstr &MI, BuildFnTy &MatchInfo);
919919
bool matchCanonicalizeFCmp(const MachineInstr &MI, BuildFnTy &MatchInfo);
920920

921+
// unmerge_values(anyext(build vector)) -> build vector(anyext)
922+
bool matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
923+
BuildFnTy &MatchInfo);
924+
921925
private:
922926
/// Checks for legality of an indexed variant of \p LdSt.
923927
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;

llvm/include/llvm/CodeGen/GlobalISel/GenericMachineInstrs.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,6 +868,14 @@ class GZext : public GCastOp {
868868
};
869869
};
870870

871+
/// Represents an any ext.
872+
class GAnyExt : public GCastOp {
873+
public:
874+
static bool classof(const MachineInstr *MI) {
875+
return MI->getOpcode() == TargetOpcode::G_ANYEXT;
876+
};
877+
};
878+
871879
/// Represents a trunc.
872880
class GTrunc : public GCastOp {
873881
public:

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

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -420,15 +420,15 @@ def unary_undef_to_zero: GICombineRule<
420420
// replaced with undef.
421421
def propagate_undef_any_op: GICombineRule<
422422
(defs root:$root),
423-
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC, G_BITCAST):$root,
423+
(match (wip_match_opcode G_ADD, G_FPTOSI, G_FPTOUI, G_SUB, G_XOR, G_TRUNC, G_BITCAST, G_ANYEXT):$root,
424424
[{ return Helper.matchAnyExplicitUseIsUndef(*${root}); }]),
425425
(apply [{ Helper.replaceInstWithUndef(*${root}); }])>;
426426

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

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

835+
// Transform unmerge any build vector -> build vector anyext
836+
def unmerge_anyext_build_vector : GICombineRule<
837+
(defs root:$root, build_fn_matchinfo:$matchinfo),
838+
(match (wip_match_opcode G_UNMERGE_VALUES): $root,
839+
[{ return Helper.matchUnmergeValuesAnyExtBuildVector(*${root}, ${matchinfo}); }]),
840+
(apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])
841+
>;
842+
835843
// Transform x,y = unmerge(zext(z)) -> x = zext z; y = 0.
836844
def unmerge_zext_to_zext : GICombineRule<
837845
(defs root:$d),
@@ -840,6 +848,16 @@ def unmerge_zext_to_zext : GICombineRule<
840848
(apply [{ Helper.applyCombineUnmergeZExtToZExt(*${d}); }])
841849
>;
842850

851+
def merge_combines: GICombineGroup<[
852+
unmerge_anyext_build_vector,
853+
unmerge_merge,
854+
merge_unmerge,
855+
unmerge_cst,
856+
unmerge_undef,
857+
unmerge_dead_to_trunc,
858+
unmerge_zext_to_zext
859+
]>;
860+
843861
// Under certain conditions, transform:
844862
// trunc (shl x, K) -> shl (trunc x), K//
845863
// trunc ([al]shr x, K) -> (trunc ([al]shr (trunc x), K))
@@ -1851,7 +1869,6 @@ def undef_combines : GICombineGroup<[undef_to_fp_zero, undef_to_int_zero,
18511869
propagate_undef_all_ops,
18521870
propagate_undef_shuffle_mask,
18531871
erase_undef_store,
1854-
unmerge_undef,
18551872
insert_extract_vec_elt_out_of_bounds]>;
18561873

18571874
def identity_combines : GICombineGroup<[select_same_val, right_identity_zero,
@@ -1909,22 +1926,20 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
19091926
reassocs, ptr_add_immed_chain, cmp_combines,
19101927
shl_ashr_to_sext_inreg, sext_inreg_of_load,
19111928
width_reduction_combines, select_combines,
1912-
known_bits_simplifications,
1929+
known_bits_simplifications, trunc_shift,
19131930
not_cmp_fold, opt_brcond_by_inverting_cond,
1914-
unmerge_merge, unmerge_cst, unmerge_dead_to_trunc,
1915-
unmerge_zext_to_zext, merge_unmerge, trunc_shift,
19161931
const_combines, xor_of_and_with_same_reg, ptr_add_with_zero,
19171932
shift_immed_chain, shift_of_shifted_logic_chain, load_or_combine,
19181933
div_rem_to_divrem, funnel_shift_combines, bitreverse_shift, commute_shift,
19191934
form_bitfield_extract, constant_fold_binops, constant_fold_fma,
19201935
constant_fold_cast_op, fabs_fneg_fold,
19211936
intdiv_combines, mulh_combines, redundant_neg_operands,
19221937
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
1923-
sub_add_reg, select_to_minmax,
1938+
sub_add_reg, select_to_minmax,
19241939
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
19251940
combine_concat_vector, match_addos,
19261941
sext_trunc, zext_trunc, prefer_sign_combines, combine_shuffle_concat,
1927-
combine_use_vector_truncate]>;
1942+
combine_use_vector_truncate, merge_combines]>;
19281943

19291944
// A combine group used to for prelegalizer combiners at -O0. The combines in
19301945
// this group have been selected based on experiments to balance code size and

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7611,3 +7611,85 @@ bool CombinerHelper::matchFoldAMinusC1PlusC2(const MachineInstr &MI,
76117611

76127612
return true;
76137613
}
7614+
7615+
bool CombinerHelper::matchUnmergeValuesAnyExtBuildVector(const MachineInstr &MI,
7616+
BuildFnTy &MatchInfo) {
7617+
const GUnmerge *Unmerge = cast<GUnmerge>(&MI);
7618+
7619+
if (!MRI.hasOneNonDBGUse(Unmerge->getSourceReg()))
7620+
return false;
7621+
7622+
const MachineInstr *Source = MRI.getVRegDef(Unmerge->getSourceReg());
7623+
7624+
LLT DstTy = MRI.getType(Unmerge->getReg(0));
7625+
7626+
// $bv:_(<8 x s8>) = G_BUILD_VECTOR ....
7627+
// $any:_(<8 x s16>) = G_ANYEXT $bv
7628+
// $uv:_(<4 x s16>), $uv1:_(<4 x s16>) = G_UNMERGE_VALUES $any
7629+
//
7630+
// ->
7631+
//
7632+
// $any:_(s16) = G_ANYEXT $bv[0]
7633+
// $any1:_(s16) = G_ANYEXT $bv[1]
7634+
// $any2:_(s16) = G_ANYEXT $bv[2]
7635+
// $any3:_(s16) = G_ANYEXT $bv[3]
7636+
// $any4:_(s16) = G_ANYEXT $bv[4]
7637+
// $any5:_(s16) = G_ANYEXT $bv[5]
7638+
// $any6:_(s16) = G_ANYEXT $bv[6]
7639+
// $any7:_(s16) = G_ANYEXT $bv[7]
7640+
// $uv:_(<4 x s16>) = G_BUILD_VECTOR $any, $any1, $any2, $any3
7641+
// $uv1:_(<4 x s16>) = G_BUILD_VECTOR $any4, $any5, $any6, $any7
7642+
7643+
// We want to unmerge into vectors.
7644+
if (!DstTy.isFixedVector())
7645+
return false;
7646+
7647+
const GAnyExt *Any = dyn_cast<GAnyExt>(Source);
7648+
if (!Any)
7649+
return false;
7650+
7651+
const MachineInstr *NextSource = MRI.getVRegDef(Any->getSrcReg());
7652+
7653+
if (const GBuildVector *BV = dyn_cast<GBuildVector>(NextSource)) {
7654+
// G_UNMERGE_VALUES G_ANYEXT G_BUILD_VECTOR
7655+
7656+
if (!MRI.hasOneNonDBGUse(BV->getReg(0)))
7657+
return false;
7658+
7659+
// FIXME: check element types?
7660+
if (BV->getNumSources() % Unmerge->getNumDefs() != 0)
7661+
return false;
7662+
7663+
LLT BigBvTy = MRI.getType(BV->getReg(0));
7664+
LLT SmallBvTy = DstTy;
7665+
LLT SmallBvElemenTy = SmallBvTy.getElementType();
7666+
7667+
if (!isLegalOrBeforeLegalizer(
7668+
{TargetOpcode::G_BUILD_VECTOR, {SmallBvTy, SmallBvElemenTy}}))
7669+
return false;
7670+
7671+
// We check the legality of scalar anyext.
7672+
if (!isLegalOrBeforeLegalizer(
7673+
{TargetOpcode::G_ANYEXT,
7674+
{SmallBvElemenTy, BigBvTy.getElementType()}}))
7675+
return false;
7676+
7677+
MatchInfo = [=](MachineIRBuilder &B) {
7678+
// Build into each G_UNMERGE_VALUES def
7679+
// a small build vector with anyext from the source build vector.
7680+
for (unsigned I = 0; I < Unmerge->getNumDefs(); ++I) {
7681+
SmallVector<Register> Ops;
7682+
for (unsigned J = 0; J < SmallBvTy.getNumElements(); ++J) {
7683+
Register SourceArray =
7684+
BV->getSourceReg(I * SmallBvTy.getNumElements() + J);
7685+
auto AnyExt = B.buildAnyExt(SmallBvElemenTy, SourceArray);
7686+
Ops.push_back(AnyExt.getReg(0));
7687+
}
7688+
B.buildBuildVector(Unmerge->getOperand(I).getReg(), Ops);
7689+
};
7690+
};
7691+
return true;
7692+
};
7693+
7694+
return false;
7695+
}

llvm/lib/Target/AArch64/AArch64Combine.td

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,13 @@ def AArch64PostLegalizerCombiner
322322
extractvecelt_pairwise_add, redundant_or,
323323
mul_const, redundant_sext_inreg,
324324
form_bitfield_extract, rotate_out_of_range,
325-
icmp_to_true_false_known_bits, merge_unmerge,
325+
icmp_to_true_false_known_bits,
326326
select_combines, fold_merge_to_zext,
327327
constant_fold_binops, identity_combines,
328328
ptr_add_immed_chain, overlapping_and,
329329
split_store_zero_128, undef_combines,
330330
select_to_minmax, or_to_bsp, combine_concat_vector,
331-
commute_constant_to_rhs,
331+
commute_constant_to_rhs, merge_combines,
332332
push_freeze_to_prevent_poison_from_propagating,
333333
combine_mul_cmlt, combine_use_vector_truncate]> {
334334
}

llvm/test/CodeGen/AArch64/GlobalISel/combine-shift-immed-mismatch-crash.mir

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,27 @@ liveins:
99
body: |
1010
; CHECK-LABEL: name: shift_immed_chain_mismatch_size_crash
1111
; CHECK: bb.0:
12-
; CHECK: successors: %bb.1(0x40000000), %bb.2(0x40000000)
13-
; CHECK: liveins: $x0
14-
; CHECK: [[DEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
15-
; CHECK: [[DEF1:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
16-
; CHECK: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 9
17-
; CHECK: G_BRCOND [[DEF]](s1), %bb.2
18-
; CHECK: G_BR %bb.1
19-
; CHECK: bb.1:
20-
; CHECK: successors:
21-
; CHECK: bb.2:
22-
; CHECK: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF1]](p0) :: (load (s32) from `ptr undef`, align 8)
23-
; CHECK: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
24-
; CHECK: [[SHL:%[0-9]+]]:_(s32) = nsw G_SHL [[LOAD]], [[C1]](s32)
25-
; CHECK: [[MUL:%[0-9]+]]:_(s32) = nsw G_MUL [[SHL]], [[C]]
26-
; CHECK: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
27-
; CHECK: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s64)
28-
; CHECK: $w0 = COPY [[SHL1]](s32)
29-
; CHECK: RET_ReallyLR implicit $w0
12+
; CHECK-NEXT: successors: %bb.1(0x40000000), %bb.2(0x40000000)
13+
; CHECK-NEXT: liveins: $x0
14+
; CHECK-NEXT: {{ $}}
15+
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s1) = G_IMPLICIT_DEF
16+
; CHECK-NEXT: [[DEF1:%[0-9]+]]:_(p0) = G_IMPLICIT_DEF
17+
; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 9
18+
; CHECK-NEXT: G_BRCOND [[DEF]](s1), %bb.2
19+
; CHECK-NEXT: G_BR %bb.1
20+
; CHECK-NEXT: {{ $}}
21+
; CHECK-NEXT: bb.1:
22+
; CHECK-NEXT: successors:
23+
; CHECK-NEXT: {{ $}}
24+
; CHECK-NEXT: bb.2:
25+
; CHECK-NEXT: [[LOAD:%[0-9]+]]:_(s32) = G_LOAD [[DEF1]](p0) :: (load (s32) from `ptr undef`, align 8)
26+
; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 4
27+
; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = nsw G_SHL [[LOAD]], [[C1]](s32)
28+
; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = nsw G_MUL [[SHL]], [[C]]
29+
; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 2
30+
; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[MUL]], [[C2]](s64)
31+
; CHECK-NEXT: $w0 = COPY [[SHL1]](s32)
32+
; CHECK-NEXT: RET_ReallyLR implicit $w0
3033
bb.1:
3134
liveins: $x0
3235

llvm/test/CodeGen/AArch64/GlobalISel/combine-shifts-undef.mir

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ body: |
1313
; CHECK-LABEL: name: shl_by_ge_bw
1414
; CHECK: liveins: $w0
1515
; CHECK-NEXT: {{ $}}
16-
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
17-
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
18-
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
16+
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
17+
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
1918
; CHECK-NEXT: RET_ReallyLR implicit $w0
2019
%1:_(s32) = COPY $w0
2120
%0:_(s16) = G_TRUNC %1(s32)
@@ -39,9 +38,8 @@ body: |
3938
; CHECK-LABEL: name: lshr_by_ge_bw
4039
; CHECK: liveins: $w0
4140
; CHECK-NEXT: {{ $}}
42-
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
43-
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
44-
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
41+
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
42+
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
4543
; CHECK-NEXT: RET_ReallyLR implicit $w0
4644
%1:_(s32) = COPY $w0
4745
%0:_(s16) = G_TRUNC %1(s32)
@@ -65,9 +63,8 @@ body: |
6563
; CHECK-LABEL: name: ashr_by_ge_bw
6664
; CHECK: liveins: $w0
6765
; CHECK-NEXT: {{ $}}
68-
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s16) = G_IMPLICIT_DEF
69-
; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s32) = G_ANYEXT [[DEF]](s16)
70-
; CHECK-NEXT: $w0 = COPY [[ANYEXT]](s32)
66+
; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
67+
; CHECK-NEXT: $w0 = COPY [[DEF]](s32)
7168
; CHECK-NEXT: RET_ReallyLR implicit $w0
7269
%1:_(s32) = COPY $w0
7370
%0:_(s16) = G_TRUNC %1(s32)

0 commit comments

Comments
 (0)