Skip to content

Commit 69ba5ab

Browse files
Make this a non-backend specific optimisation & check all unmerged values are used
1 parent 3f8d7da commit 69ba5ab

File tree

5 files changed

+103
-88
lines changed

5 files changed

+103
-88
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,12 @@ class CombinerHelper {
647647
bool matchRotateOutOfRange(MachineInstr &MI) const;
648648
void applyRotateOutOfRange(MachineInstr &MI) const;
649649

650+
bool matchCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
651+
Register &UnmergeSrc) const;
652+
void applyCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
653+
MachineIRBuilder &B,
654+
Register &UnmergeSrc) const;
655+
650656
bool matchUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
651657
void applyUseVectorTruncate(MachineInstr &MI, Register &MatchInfo) const;
652658

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,15 @@ def merge_of_x_and_zero : GICombineRule <
921921
[{ return Helper.matchMergeXAndZero(*${MI}, ${matchinfo}); }]),
922922
(apply [{ Helper.applyBuildFn(*${MI}, ${matchinfo}); }])>;
923923

924+
// Transform build_vector(unmerge(src, 0), ... unmerge(src, n), undef, ..., undef)
925+
// => concat_vectors(src, undef)
926+
def combine_build_unmerge : GICombineRule<
927+
(defs root:$root, register_matchinfo:$unmergeSrc),
928+
(match (G_BUILD_VECTOR $dst, GIVariadic<>:$unused):$root,
929+
[{ return Helper.matchCombineBuildUnmerge(*${root}, MRI, ${unmergeSrc}); }]),
930+
(apply [{ Helper.applyCombineBuildUnmerge(*${root}, MRI, B, ${unmergeSrc}); }])
931+
>;
932+
924933
def merge_combines: GICombineGroup<[
925934
unmerge_anyext_build_vector,
926935
unmerge_merge,
@@ -930,7 +939,8 @@ def merge_combines: GICombineGroup<[
930939
unmerge_dead_to_trunc,
931940
unmerge_zext_to_zext,
932941
merge_of_x_and_undef,
933-
merge_of_x_and_zero
942+
merge_of_x_and_zero,
943+
combine_build_unmerge
934944
]>;
935945

936946
// Under certain conditions, transform:

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3463,6 +3463,91 @@ static bool isConstValidTrue(const TargetLowering &TLI, unsigned ScalarSizeBits,
34633463
isConstTrueVal(TLI, Cst, IsVector, IsFP);
34643464
}
34653465

3466+
// This pattern aims to match the following shape to avoid extra mov
3467+
// instructions
3468+
// G_BUILD_VECTOR(
3469+
// G_UNMERGE_VALUES(src, 0)
3470+
// G_UNMERGE_VALUES(src, 1)
3471+
// G_IMPLICIT_DEF
3472+
// G_IMPLICIT_DEF
3473+
// )
3474+
// ->
3475+
// G_CONCAT_VECTORS(
3476+
// src,
3477+
// undef
3478+
// )
3479+
bool CombinerHelper::matchCombineBuildUnmerge(MachineInstr &MI,
3480+
MachineRegisterInfo &MRI,
3481+
Register &UnmergeSrc) const {
3482+
assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
3483+
3484+
unsigned BuildUseCount = MI.getNumOperands() - 1;
3485+
3486+
if (BuildUseCount % 2 != 0)
3487+
return false;
3488+
3489+
unsigned NumUnmerge = BuildUseCount / 2;
3490+
3491+
// Check the first operand is an unmerge
3492+
auto *MaybeUnmerge = getDefIgnoringCopies(MI.getOperand(1).getReg(), MRI);
3493+
if (MaybeUnmerge->getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
3494+
return false;
3495+
3496+
// Check that the resultant concat will be legal
3497+
auto UnmergeEltSize =
3498+
MRI.getType(MaybeUnmerge->getOperand(1).getReg()).getScalarSizeInBits();
3499+
auto UnmergeEltCount = MaybeUnmerge->getNumDefs();
3500+
3501+
if (UnmergeEltCount < 2 || (UnmergeEltSize * UnmergeEltCount != 64 &&
3502+
UnmergeEltSize * UnmergeEltCount != 128))
3503+
return false;
3504+
3505+
// Check that all of the operands before the midpoint come from the same
3506+
// unmerge and are in the same order as they are used in the build_vector
3507+
for (unsigned I = 0; I < NumUnmerge; ++I) {
3508+
auto MaybeUnmergeReg = MI.getOperand(I + 1).getReg();
3509+
auto *Unmerge = getDefIgnoringCopies(MaybeUnmergeReg, MRI);
3510+
3511+
if (Unmerge != MaybeUnmerge)
3512+
return false;
3513+
3514+
if (Unmerge->getOperand(I).getReg() != MaybeUnmergeReg)
3515+
return false;
3516+
}
3517+
3518+
// Check that all of the unmerged values are used
3519+
if (UnmergeEltCount != NumUnmerge)
3520+
return false;
3521+
3522+
// Check that all of the operands after the mid point are undefs.
3523+
for (unsigned I = NumUnmerge; I < BuildUseCount; ++I) {
3524+
auto *Undef = getDefIgnoringCopies(MI.getOperand(I + 1).getReg(), MRI);
3525+
3526+
if (Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
3527+
return false;
3528+
}
3529+
3530+
// Unmerge should only use one register so we can use the last one
3531+
for (auto &UnmergeUse :
3532+
getDefIgnoringCopies(MI.getOperand(1).getReg(), MRI)->all_uses())
3533+
UnmergeSrc = UnmergeUse.getReg();
3534+
3535+
return true;
3536+
}
3537+
3538+
void CombinerHelper::applyCombineBuildUnmerge(MachineInstr &MI,
3539+
MachineRegisterInfo &MRI,
3540+
MachineIRBuilder &B,
3541+
Register &UnmergeSrc) const {
3542+
assert(UnmergeSrc && "Expected there to be one matching G_UNMERGE_VALUES");
3543+
B.setInstrAndDebugLoc(MI);
3544+
3545+
Register UndefVec = B.buildUndef(MRI.getType(UnmergeSrc)).getReg(0);
3546+
B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc, UndefVec});
3547+
3548+
MI.eraseFromParent();
3549+
}
3550+
34663551
// This combine tries to reduce the number of scalarised G_TRUNC instructions by
34673552
// using vector truncates instead
34683553
//

llvm/lib/Target/AArch64/AArch64Combine.td

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,13 +332,6 @@ def combine_mul_cmlt : GICombineRule<
332332
(apply [{ applyCombineMulCMLT(*${root}, MRI, B, ${matchinfo}); }])
333333
>;
334334

335-
def combine_build_unmerge : GICombineRule<
336-
(defs root:$root, register_matchinfo:$unmergeSrc),
337-
(match (G_BUILD_VECTOR $dst, GIVariadic<>:$unused):$root,
338-
[{ return matchCombineBuildUnmerge(*${root}, MRI, ${unmergeSrc}); }]),
339-
(apply [{ applyCombineBuildUnmerge(*${root}, MRI, B, ${unmergeSrc}); }])
340-
>;
341-
342335
// Post-legalization combines which should happen at all optimization levels.
343336
// (E.g. ones that facilitate matching for the selector) For example, matching
344337
// pseudos.
@@ -373,7 +366,7 @@ def AArch64PostLegalizerCombiner
373366
select_to_minmax, or_to_bsp, combine_concat_vector,
374367
commute_constant_to_rhs, extract_vec_elt_combines,
375368
push_freeze_to_prevent_poison_from_propagating,
376-
combine_mul_cmlt, combine_use_vector_truncate, combine_build_unmerge,
369+
combine_mul_cmlt, combine_use_vector_truncate,
377370
extmultomull, truncsat_combines, lshr_of_trunc_of_lshr,
378371
funnel_shift_from_or_shift_constants_are_legal]> {
379372
}

llvm/lib/Target/AArch64/GISel/AArch64PostLegalizerCombiner.cpp

Lines changed: 0 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -134,85 +134,6 @@ bool isZeroExtended(Register R, MachineRegisterInfo &MRI) {
134134
return MRI.getVRegDef(R)->getOpcode() == TargetOpcode::G_ZEXT;
135135
}
136136

137-
// This pattern aims to match the following shape to avoid extra mov
138-
// instructions
139-
// G_BUILD_VECTOR(
140-
// G_UNMERGE_VALUES(src, 0)
141-
// G_UNMERGE_VALUES(src, 1)
142-
// G_IMPLICIT_DEF
143-
// G_IMPLICIT_DEF
144-
// )
145-
// ->
146-
// G_CONCAT_VECTORS(
147-
// src,
148-
// undef
149-
// )
150-
bool matchCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
151-
Register &UnmergeSrc) {
152-
assert(MI.getOpcode() == TargetOpcode::G_BUILD_VECTOR);
153-
154-
unsigned BuildUseCount = MI.getNumOperands() - 1;
155-
156-
if (BuildUseCount % 2 != 0)
157-
return false;
158-
159-
unsigned HalfWayIndex = BuildUseCount / 2;
160-
161-
// Check the first operand is an unmerge
162-
auto *MaybeUnmerge = getDefIgnoringCopies(MI.getOperand(1).getReg(), MRI);
163-
if (MaybeUnmerge->getOpcode() != TargetOpcode::G_UNMERGE_VALUES)
164-
return false;
165-
166-
// Check that the resultant concat will be legal
167-
auto UnmergeEltSize =
168-
MRI.getType(MaybeUnmerge->getOperand(1).getReg()).getScalarSizeInBits();
169-
auto UnmergeEltCount = MaybeUnmerge->getNumDefs();
170-
171-
if (UnmergeEltCount < 2 || (UnmergeEltSize * UnmergeEltCount != 64 &&
172-
UnmergeEltSize * UnmergeEltCount != 128))
173-
return false;
174-
175-
// Check that all of the operands before the midpoint come from the same
176-
// unmerge and are in the same order as they are used in the build_vector
177-
for (unsigned I = 0; I < HalfWayIndex; ++I) {
178-
auto MaybeUnmergeReg = MI.getOperand(I + 1).getReg();
179-
auto *Unmerge = getDefIgnoringCopies(MaybeUnmergeReg, MRI);
180-
181-
if (Unmerge != MaybeUnmerge)
182-
return false;
183-
184-
if (Unmerge->getOperand(I).getReg() != MaybeUnmergeReg)
185-
return false;
186-
}
187-
188-
// Check that all of the operands after the mid point are undefs.
189-
for (unsigned I = HalfWayIndex; I < BuildUseCount; ++I) {
190-
auto *Undef = getDefIgnoringCopies(MI.getOperand(I + 1).getReg(), MRI);
191-
192-
if (Undef->getOpcode() != TargetOpcode::G_IMPLICIT_DEF)
193-
return false;
194-
}
195-
196-
// Unmerge should only use one register so we can use the last one
197-
for (auto &UnmergeUse :
198-
getDefIgnoringCopies(MI.getOperand(1).getReg(), MRI)->all_uses())
199-
UnmergeSrc = UnmergeUse.getReg();
200-
201-
return true;
202-
}
203-
204-
void applyCombineBuildUnmerge(MachineInstr &MI, MachineRegisterInfo &MRI,
205-
MachineIRBuilder &B, Register &UnmergeSrc) {
206-
assert(UnmergeSrc && "Expected there to be one matching G_UNMERGE_VALUES");
207-
B.setInstrAndDebugLoc(MI);
208-
209-
Register UndefVec = MRI.createGenericVirtualRegister(MRI.getType(UnmergeSrc));
210-
B.buildUndef(UndefVec);
211-
B.buildConcatVectors(MI.getOperand(0), {UnmergeSrc, UndefVec});
212-
213-
MI.eraseFromParent();
214-
}
215-
216137
bool matchAArch64MulConstCombine(
217138
MachineInstr &MI, MachineRegisterInfo &MRI,
218139
std::function<void(MachineIRBuilder &B, Register DstReg)> &ApplyFn) {

0 commit comments

Comments
 (0)