Skip to content

Commit 710a552

Browse files
author
Thorsten Schütt
authored
[GlobalIsel] Revisit ext of ext. (#102769)
Credits: https://reviews.llvm.org/D86516 combine-ext.mir Notable semantic changes: InstCombine does not mix zero and sign extend, see CastInst::isEliminableCastPair. New version has legality checks. Folds sext/zext of anyext -> sext/zext Support for nneg Future work: nneg zext of sext -> sext sext of nneg zext -> sext
1 parent aa427b1 commit 710a552

File tree

5 files changed

+166
-77
lines changed

5 files changed

+166
-77
lines changed

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -390,12 +390,6 @@ class CombinerHelper {
390390
/// Transform zext(trunc(x)) to x.
391391
bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg);
392392

393-
/// Transform [asz]ext([asz]ext(x)) to [asz]ext x.
394-
bool matchCombineExtOfExt(MachineInstr &MI,
395-
std::tuple<Register, unsigned> &MatchInfo);
396-
void applyCombineExtOfExt(MachineInstr &MI,
397-
std::tuple<Register, unsigned> &MatchInfo);
398-
399393
/// Transform trunc (shl x, K) to shl (trunc x), K
400394
/// if K < VT.getScalarSizeInBits().
401395
///
@@ -903,6 +897,9 @@ class CombinerHelper {
903897
// fold ((A-C1)+C2) -> (A+(C2-C1))
904898
bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
905899

900+
bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
901+
BuildFnTy &MatchInfo);
902+
906903
private:
907904
/// Checks for legality of an indexed variant of \p LdSt.
908905
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;

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

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -767,15 +767,6 @@ def zext_trunc_fold: GICombineRule <
767767
(apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
768768
>;
769769

770-
// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
771-
def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">;
772-
def ext_ext_fold: GICombineRule <
773-
(defs root:$root, ext_ext_fold_matchinfo:$matchinfo),
774-
(match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root,
775-
[{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]),
776-
(apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }])
777-
>;
778-
779770
def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">;
780771
def not_cmp_fold : GICombineRule<
781772
(defs root:$d, not_cmp_fold_matchinfo:$info),
@@ -1850,13 +1841,36 @@ def select_of_zext : select_of_opcode<G_ZEXT>;
18501841
def select_of_anyext : select_of_opcode<G_ANYEXT>;
18511842
def select_of_truncate : select_of_opcode<G_TRUNC>;
18521843

1844+
// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
1845+
class ext_of_ext_opcodes<Instruction ext1Opcode, Instruction ext2Opcode> : GICombineRule <
1846+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1847+
(match (ext2Opcode $second, $src):$Second,
1848+
(ext1Opcode $root, $second):$First,
1849+
[{ return Helper.matchExtOfExt(*${First}, *${Second}, ${matchinfo}); }]),
1850+
(apply [{ Helper.applyBuildFn(*${First}, ${matchinfo}); }])>;
1851+
1852+
def zext_of_zext : ext_of_ext_opcodes<G_ZEXT, G_ZEXT>;
1853+
def zext_of_anyext : ext_of_ext_opcodes<G_ZEXT, G_ANYEXT>;
1854+
def sext_of_sext : ext_of_ext_opcodes<G_SEXT, G_SEXT>;
1855+
def sext_of_anyext : ext_of_ext_opcodes<G_SEXT, G_ANYEXT>;
1856+
def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>;
1857+
def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>;
1858+
def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>;
1859+
18531860
def cast_combines: GICombineGroup<[
18541861
truncate_of_zext,
18551862
truncate_of_sext,
18561863
truncate_of_anyext,
18571864
select_of_zext,
18581865
select_of_anyext,
1859-
select_of_truncate
1866+
select_of_truncate,
1867+
zext_of_zext,
1868+
zext_of_anyext,
1869+
sext_of_sext,
1870+
sext_of_anyext,
1871+
anyext_of_anyext,
1872+
anyext_of_zext,
1873+
anyext_of_sext
18601874
]>;
18611875

18621876

@@ -1928,7 +1942,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
19281942
reassocs, ptr_add_immed_chain,
19291943
shl_ashr_to_sext_inreg, sext_inreg_of_load,
19301944
width_reduction_combines, select_combines,
1931-
known_bits_simplifications, ext_ext_fold,
1945+
known_bits_simplifications,
19321946
not_cmp_fold, opt_brcond_by_inverting_cond,
19331947
unmerge_merge, unmerge_cst, unmerge_dead_to_trunc,
19341948
unmerge_zext_to_zext, merge_unmerge, trunc_shift,

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 0 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2538,60 +2538,6 @@ bool CombinerHelper::matchCombineZextTrunc(MachineInstr &MI, Register &Reg) {
25382538
return false;
25392539
}
25402540

2541-
bool CombinerHelper::matchCombineExtOfExt(
2542-
MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) {
2543-
assert((MI.getOpcode() == TargetOpcode::G_ANYEXT ||
2544-
MI.getOpcode() == TargetOpcode::G_SEXT ||
2545-
MI.getOpcode() == TargetOpcode::G_ZEXT) &&
2546-
"Expected a G_[ASZ]EXT");
2547-
Register SrcReg = MI.getOperand(1).getReg();
2548-
Register OriginalSrcReg = getSrcRegIgnoringCopies(SrcReg, MRI);
2549-
if (OriginalSrcReg.isValid())
2550-
SrcReg = OriginalSrcReg;
2551-
MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
2552-
// Match exts with the same opcode, anyext([sz]ext) and sext(zext).
2553-
unsigned Opc = MI.getOpcode();
2554-
unsigned SrcOpc = SrcMI->getOpcode();
2555-
if (Opc == SrcOpc ||
2556-
(Opc == TargetOpcode::G_ANYEXT &&
2557-
(SrcOpc == TargetOpcode::G_SEXT || SrcOpc == TargetOpcode::G_ZEXT)) ||
2558-
(Opc == TargetOpcode::G_SEXT && SrcOpc == TargetOpcode::G_ZEXT)) {
2559-
MatchInfo = std::make_tuple(SrcMI->getOperand(1).getReg(), SrcOpc);
2560-
return true;
2561-
}
2562-
return false;
2563-
}
2564-
2565-
void CombinerHelper::applyCombineExtOfExt(
2566-
MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) {
2567-
assert((MI.getOpcode() == TargetOpcode::G_ANYEXT ||
2568-
MI.getOpcode() == TargetOpcode::G_SEXT ||
2569-
MI.getOpcode() == TargetOpcode::G_ZEXT) &&
2570-
"Expected a G_[ASZ]EXT");
2571-
2572-
Register Reg = std::get<0>(MatchInfo);
2573-
unsigned SrcExtOp = std::get<1>(MatchInfo);
2574-
2575-
// Combine exts with the same opcode.
2576-
if (MI.getOpcode() == SrcExtOp) {
2577-
Observer.changingInstr(MI);
2578-
MI.getOperand(1).setReg(Reg);
2579-
Observer.changedInstr(MI);
2580-
return;
2581-
}
2582-
2583-
// Combine:
2584-
// - anyext([sz]ext x) to [sz]ext x
2585-
// - sext(zext x) to zext x
2586-
if (MI.getOpcode() == TargetOpcode::G_ANYEXT ||
2587-
(MI.getOpcode() == TargetOpcode::G_SEXT &&
2588-
SrcExtOp == TargetOpcode::G_ZEXT)) {
2589-
Register DstReg = MI.getOperand(0).getReg();
2590-
Builder.buildInstr(SrcExtOp, {DstReg}, {Reg});
2591-
MI.eraseFromParent();
2592-
}
2593-
}
2594-
25952541
static LLT getMidVTForTruncRightShiftCombine(LLT ShiftTy, LLT TruncTy) {
25962542
const unsigned ShiftSize = ShiftTy.getScalarSizeInBits();
25972543
const unsigned TruncSize = TruncTy.getScalarSizeInBits();

llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,3 +209,67 @@ bool CombinerHelper::matchCastOfSelect(const MachineInstr &CastMI,
209209

210210
return true;
211211
}
212+
213+
bool CombinerHelper::matchExtOfExt(const MachineInstr &FirstMI,
214+
const MachineInstr &SecondMI,
215+
BuildFnTy &MatchInfo) {
216+
const GExtOp *First = cast<GExtOp>(&FirstMI);
217+
const GExtOp *Second = cast<GExtOp>(&SecondMI);
218+
219+
Register Dst = First->getReg(0);
220+
Register Src = Second->getSrcReg();
221+
LLT DstTy = MRI.getType(Dst);
222+
LLT SrcTy = MRI.getType(Src);
223+
224+
if (!MRI.hasOneNonDBGUse(Second->getReg(0)))
225+
return false;
226+
227+
// ext of ext -> later ext
228+
if (First->getOpcode() == Second->getOpcode() &&
229+
isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
230+
if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
231+
MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
232+
if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
233+
Flag = MachineInstr::MIFlag::NonNeg;
234+
MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
235+
return true;
236+
}
237+
// not zext -> no flags
238+
MatchInfo = [=](MachineIRBuilder &B) {
239+
B.buildInstr(Second->getOpcode(), {Dst}, {Src});
240+
};
241+
return true;
242+
}
243+
244+
// anyext of sext/zext -> sext/zext
245+
// -> pick anyext as second ext, then ext of ext
246+
if (First->getOpcode() == TargetOpcode::G_ANYEXT &&
247+
isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
248+
if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
249+
MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
250+
if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
251+
Flag = MachineInstr::MIFlag::NonNeg;
252+
MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
253+
return true;
254+
}
255+
MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
256+
return true;
257+
}
258+
259+
// sext/zext of anyext -> sext/zext
260+
// -> pick anyext as first ext, then ext of ext
261+
if (Second->getOpcode() == TargetOpcode::G_ANYEXT &&
262+
isLegalOrBeforeLegalizer({First->getOpcode(), {DstTy, SrcTy}})) {
263+
if (First->getOpcode() == TargetOpcode::G_ZEXT) {
264+
MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
265+
if (First->getFlag(MachineInstr::MIFlag::NonNeg))
266+
Flag = MachineInstr::MIFlag::NonNeg;
267+
MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
268+
return true;
269+
}
270+
MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
271+
return true;
272+
}
273+
274+
return false;
275+
}

llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,9 @@ body: |
251251
; CHECK: liveins: $h0
252252
; CHECK-NEXT: {{ $}}
253253
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
254-
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
255-
; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
254+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[COPY]](s16)
255+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[ZEXT]](s32)
256+
; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
256257
%0:_(s16) = COPY $h0
257258
%1:_(s32) = G_ZEXT %0(s16)
258259
%2:_(s64) = G_SEXT %1(s32)
@@ -267,8 +268,10 @@ body: |
267268
; CHECK: liveins: $h0
268269
; CHECK-NEXT: {{ $}}
269270
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
270-
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
271-
; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
271+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[COPY]](s16)
272+
; CHECK-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[ZEXT]], 11
273+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[ASSERT_ZEXT]](s32)
274+
; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
272275
%0:_(s16) = COPY $h0
273276
%1:_(s32) = G_ZEXT %0(s16)
274277
%2:_(s32) = G_ASSERT_ZEXT %1(s32), 11
@@ -284,8 +287,9 @@ body: |
284287
; CHECK: liveins: $s0
285288
; CHECK-NEXT: {{ $}}
286289
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $s0
287-
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[COPY]](<2 x s16>)
288-
; CHECK-NEXT: $q0 = COPY [[ZEXT]](<2 x s64>)
290+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s32>) = G_ZEXT [[COPY]](<2 x s16>)
291+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x s64>) = G_SEXT [[ZEXT]](<2 x s32>)
292+
; CHECK-NEXT: $q0 = COPY [[SEXT]](<2 x s64>)
289293
%0:_(<2 x s16>) = COPY $s0
290294
%1:_(<2 x s32>) = G_ZEXT %0(<2 x s16>)
291295
%2:_(<2 x s64>) = G_SEXT %1(<2 x s32>)
@@ -340,3 +344,67 @@ body: |
340344
%2:_(<2 x s64>) = G_ZEXT %1(<2 x s32>)
341345
$q0 = COPY %2(<2 x s64>)
342346
...
347+
---
348+
name: test_combine_zext_anyext
349+
body: |
350+
bb.1:
351+
liveins: $h0
352+
; CHECK-LABEL: name: test_combine_zext_anyext
353+
; CHECK: liveins: $h0
354+
; CHECK-NEXT: {{ $}}
355+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
356+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
357+
; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
358+
%0:_(s16) = COPY $h0
359+
%1:_(s32) = G_ANYEXT %0(s16)
360+
%2:_(s64) = G_ZEXT %1(s32)
361+
$x0 = COPY %2(s64)
362+
...
363+
---
364+
name: test_combine_sext_anyext
365+
body: |
366+
bb.1:
367+
liveins: $h0
368+
; CHECK-LABEL: name: test_combine_sext_anyext
369+
; CHECK: liveins: $h0
370+
; CHECK-NEXT: {{ $}}
371+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
372+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[COPY]](s16)
373+
; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
374+
%0:_(s16) = COPY $h0
375+
%1:_(s32) = G_ANYEXT %0(s16)
376+
%2:_(s64) = G_SEXT %1(s32)
377+
$x0 = COPY %2(s64)
378+
...
379+
---
380+
name: test_combine_nneg_zext_anyext
381+
body: |
382+
bb.1:
383+
liveins: $h0
384+
; CHECK-LABEL: name: test_combine_nneg_zext_anyext
385+
; CHECK: liveins: $h0
386+
; CHECK-NEXT: {{ $}}
387+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
388+
; CHECK-NEXT: %2:_(s64) = nneg G_ZEXT [[COPY]](s16)
389+
; CHECK-NEXT: $x0 = COPY %2(s64)
390+
%0:_(s16) = COPY $h0
391+
%1:_(s32) = G_ANYEXT %0(s16)
392+
%2:_(s64) = nneg G_ZEXT %1(s32)
393+
$x0 = COPY %2(s64)
394+
...
395+
---
396+
name: test_combine_anyext_nneg_zext
397+
body: |
398+
bb.1:
399+
liveins: $h0
400+
; CHECK-LABEL: name: test_combine_anyext_nneg_zext
401+
; CHECK: liveins: $h0
402+
; CHECK-NEXT: {{ $}}
403+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
404+
; CHECK-NEXT: %2:_(s64) = nneg G_ZEXT [[COPY]](s16)
405+
; CHECK-NEXT: $x0 = COPY %2(s64)
406+
%0:_(s16) = COPY $h0
407+
%1:_(s32) = nneg G_ZEXT %0(s16)
408+
%2:_(s64) = G_ANYEXT %1(s32)
409+
$x0 = COPY %2(s64)
410+
...

0 commit comments

Comments
 (0)