[llvm] 710a552 - [GlobalIsel] Revisit ext of ext. (#102769)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 16 06:38:59 PDT 2024
Author: Thorsten Schütt
Date: 2024-08-16T15:38:56+02:00
New Revision: 710a552dedbf1a28cebac78b481cb78138fbc454
URL: https://github.com/llvm/llvm-project/commit/710a552dedbf1a28cebac78b481cb78138fbc454
DIFF: https://github.com/llvm/llvm-project/commit/710a552dedbf1a28cebac78b481cb78138fbc454.diff
LOG: [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
Added:
Modified:
llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
llvm/include/llvm/Target/GlobalISel/Combine.td
llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir
Removed:
################################################################################
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
index c76a54ed26ed56..32effc536eb35d 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/CombinerHelper.h
@@ -390,12 +390,6 @@ class CombinerHelper {
/// Transform zext(trunc(x)) to x.
bool matchCombineZextTrunc(MachineInstr &MI, Register &Reg);
- /// Transform [asz]ext([asz]ext(x)) to [asz]ext x.
- bool matchCombineExtOfExt(MachineInstr &MI,
- std::tuple<Register, unsigned> &MatchInfo);
- void applyCombineExtOfExt(MachineInstr &MI,
- std::tuple<Register, unsigned> &MatchInfo);
-
/// Transform trunc (shl x, K) to shl (trunc x), K
/// if K < VT.getScalarSizeInBits().
///
@@ -903,6 +897,9 @@ class CombinerHelper {
// fold ((A-C1)+C2) -> (A+(C2-C1))
bool matchFoldAMinusC1PlusC2(const MachineInstr &MI, BuildFnTy &MatchInfo);
+ bool matchExtOfExt(const MachineInstr &FirstMI, const MachineInstr &SecondMI,
+ BuildFnTy &MatchInfo);
+
private:
/// Checks for legality of an indexed variant of \p LdSt.
bool isIndexedLoadStoreLegal(GLoadStore &LdSt) const;
diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td
index c76596ce3e4f2d..814c5e789cb374 100644
--- a/llvm/include/llvm/Target/GlobalISel/Combine.td
+++ b/llvm/include/llvm/Target/GlobalISel/Combine.td
@@ -767,15 +767,6 @@ def zext_trunc_fold: GICombineRule <
(apply [{ Helper.replaceSingleDefInstWithReg(*${root}, ${matchinfo}); }])
>;
-// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
-def ext_ext_fold_matchinfo : GIDefMatchData<"std::tuple<Register, unsigned>">;
-def ext_ext_fold: GICombineRule <
- (defs root:$root, ext_ext_fold_matchinfo:$matchinfo),
- (match (wip_match_opcode G_ANYEXT, G_SEXT, G_ZEXT):$root,
- [{ return Helper.matchCombineExtOfExt(*${root}, ${matchinfo}); }]),
- (apply [{ Helper.applyCombineExtOfExt(*${root}, ${matchinfo}); }])
->;
-
def not_cmp_fold_matchinfo : GIDefMatchData<"SmallVector<Register, 4>">;
def not_cmp_fold : GICombineRule<
(defs root:$d, not_cmp_fold_matchinfo:$info),
@@ -1850,13 +1841,36 @@ def select_of_zext : select_of_opcode<G_ZEXT>;
def select_of_anyext : select_of_opcode<G_ANYEXT>;
def select_of_truncate : select_of_opcode<G_TRUNC>;
+// Fold ([asz]ext ([asz]ext x)) -> ([asz]ext x).
+class ext_of_ext_opcodes<Instruction ext1Opcode, Instruction ext2Opcode> : GICombineRule <
+ (defs root:$root, build_fn_matchinfo:$matchinfo),
+ (match (ext2Opcode $second, $src):$Second,
+ (ext1Opcode $root, $second):$First,
+ [{ return Helper.matchExtOfExt(*${First}, *${Second}, ${matchinfo}); }]),
+ (apply [{ Helper.applyBuildFn(*${First}, ${matchinfo}); }])>;
+
+def zext_of_zext : ext_of_ext_opcodes<G_ZEXT, G_ZEXT>;
+def zext_of_anyext : ext_of_ext_opcodes<G_ZEXT, G_ANYEXT>;
+def sext_of_sext : ext_of_ext_opcodes<G_SEXT, G_SEXT>;
+def sext_of_anyext : ext_of_ext_opcodes<G_SEXT, G_ANYEXT>;
+def anyext_of_anyext : ext_of_ext_opcodes<G_ANYEXT, G_ANYEXT>;
+def anyext_of_zext : ext_of_ext_opcodes<G_ANYEXT, G_ZEXT>;
+def anyext_of_sext : ext_of_ext_opcodes<G_ANYEXT, G_SEXT>;
+
def cast_combines: GICombineGroup<[
truncate_of_zext,
truncate_of_sext,
truncate_of_anyext,
select_of_zext,
select_of_anyext,
- select_of_truncate
+ select_of_truncate,
+ zext_of_zext,
+ zext_of_anyext,
+ sext_of_sext,
+ sext_of_anyext,
+ anyext_of_anyext,
+ anyext_of_zext,
+ anyext_of_sext
]>;
@@ -1928,7 +1942,7 @@ def all_combines : GICombineGroup<[integer_reassoc_combines, trivial_combines,
reassocs, ptr_add_immed_chain,
shl_ashr_to_sext_inreg, sext_inreg_of_load,
width_reduction_combines, select_combines,
- known_bits_simplifications, ext_ext_fold,
+ known_bits_simplifications,
not_cmp_fold, opt_brcond_by_inverting_cond,
unmerge_merge, unmerge_cst, unmerge_dead_to_trunc,
unmerge_zext_to_zext, merge_unmerge, trunc_shift,
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index d363e6794cb017..1517ae707c8cff 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -2538,60 +2538,6 @@ bool CombinerHelper::matchCombineZextTrunc(MachineInstr &MI, Register &Reg) {
return false;
}
-bool CombinerHelper::matchCombineExtOfExt(
- MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) {
- assert((MI.getOpcode() == TargetOpcode::G_ANYEXT ||
- MI.getOpcode() == TargetOpcode::G_SEXT ||
- MI.getOpcode() == TargetOpcode::G_ZEXT) &&
- "Expected a G_[ASZ]EXT");
- Register SrcReg = MI.getOperand(1).getReg();
- Register OriginalSrcReg = getSrcRegIgnoringCopies(SrcReg, MRI);
- if (OriginalSrcReg.isValid())
- SrcReg = OriginalSrcReg;
- MachineInstr *SrcMI = MRI.getVRegDef(SrcReg);
- // Match exts with the same opcode, anyext([sz]ext) and sext(zext).
- unsigned Opc = MI.getOpcode();
- unsigned SrcOpc = SrcMI->getOpcode();
- if (Opc == SrcOpc ||
- (Opc == TargetOpcode::G_ANYEXT &&
- (SrcOpc == TargetOpcode::G_SEXT || SrcOpc == TargetOpcode::G_ZEXT)) ||
- (Opc == TargetOpcode::G_SEXT && SrcOpc == TargetOpcode::G_ZEXT)) {
- MatchInfo = std::make_tuple(SrcMI->getOperand(1).getReg(), SrcOpc);
- return true;
- }
- return false;
-}
-
-void CombinerHelper::applyCombineExtOfExt(
- MachineInstr &MI, std::tuple<Register, unsigned> &MatchInfo) {
- assert((MI.getOpcode() == TargetOpcode::G_ANYEXT ||
- MI.getOpcode() == TargetOpcode::G_SEXT ||
- MI.getOpcode() == TargetOpcode::G_ZEXT) &&
- "Expected a G_[ASZ]EXT");
-
- Register Reg = std::get<0>(MatchInfo);
- unsigned SrcExtOp = std::get<1>(MatchInfo);
-
- // Combine exts with the same opcode.
- if (MI.getOpcode() == SrcExtOp) {
- Observer.changingInstr(MI);
- MI.getOperand(1).setReg(Reg);
- Observer.changedInstr(MI);
- return;
- }
-
- // Combine:
- // - anyext([sz]ext x) to [sz]ext x
- // - sext(zext x) to zext x
- if (MI.getOpcode() == TargetOpcode::G_ANYEXT ||
- (MI.getOpcode() == TargetOpcode::G_SEXT &&
- SrcExtOp == TargetOpcode::G_ZEXT)) {
- Register DstReg = MI.getOperand(0).getReg();
- Builder.buildInstr(SrcExtOp, {DstReg}, {Reg});
- MI.eraseFromParent();
- }
-}
-
static LLT getMidVTForTruncRightShiftCombine(LLT ShiftTy, LLT TruncTy) {
const unsigned ShiftSize = ShiftTy.getScalarSizeInBits();
const unsigned TruncSize = TruncTy.getScalarSizeInBits();
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
index 59295f7a65835c..494d8da84445d1 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelperCasts.cpp
@@ -209,3 +209,67 @@ bool CombinerHelper::matchCastOfSelect(const MachineInstr &CastMI,
return true;
}
+
+bool CombinerHelper::matchExtOfExt(const MachineInstr &FirstMI,
+ const MachineInstr &SecondMI,
+ BuildFnTy &MatchInfo) {
+ const GExtOp *First = cast<GExtOp>(&FirstMI);
+ const GExtOp *Second = cast<GExtOp>(&SecondMI);
+
+ Register Dst = First->getReg(0);
+ Register Src = Second->getSrcReg();
+ LLT DstTy = MRI.getType(Dst);
+ LLT SrcTy = MRI.getType(Src);
+
+ if (!MRI.hasOneNonDBGUse(Second->getReg(0)))
+ return false;
+
+ // ext of ext -> later ext
+ if (First->getOpcode() == Second->getOpcode() &&
+ isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
+ if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
+ MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
+ if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
+ Flag = MachineInstr::MIFlag::NonNeg;
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
+ return true;
+ }
+ // not zext -> no flags
+ MatchInfo = [=](MachineIRBuilder &B) {
+ B.buildInstr(Second->getOpcode(), {Dst}, {Src});
+ };
+ return true;
+ }
+
+ // anyext of sext/zext -> sext/zext
+ // -> pick anyext as second ext, then ext of ext
+ if (First->getOpcode() == TargetOpcode::G_ANYEXT &&
+ isLegalOrBeforeLegalizer({Second->getOpcode(), {DstTy, SrcTy}})) {
+ if (Second->getOpcode() == TargetOpcode::G_ZEXT) {
+ MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
+ if (Second->getFlag(MachineInstr::MIFlag::NonNeg))
+ Flag = MachineInstr::MIFlag::NonNeg;
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
+ return true;
+ }
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
+ return true;
+ }
+
+ // sext/zext of anyext -> sext/zext
+ // -> pick anyext as first ext, then ext of ext
+ if (Second->getOpcode() == TargetOpcode::G_ANYEXT &&
+ isLegalOrBeforeLegalizer({First->getOpcode(), {DstTy, SrcTy}})) {
+ if (First->getOpcode() == TargetOpcode::G_ZEXT) {
+ MachineInstr::MIFlag Flag = MachineInstr::MIFlag::NoFlags;
+ if (First->getFlag(MachineInstr::MIFlag::NonNeg))
+ Flag = MachineInstr::MIFlag::NonNeg;
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildZExt(Dst, Src, Flag); };
+ return true;
+ }
+ MatchInfo = [=](MachineIRBuilder &B) { B.buildSExt(Dst, Src); };
+ return true;
+ }
+
+ return false;
+}
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir b/llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir
index a431a6764d06f7..629238126380c7 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/combine-ext.mir
@@ -251,8 +251,9 @@ body: |
; CHECK: liveins: $h0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
- ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
- ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[COPY]](s16)
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[ZEXT]](s32)
+ ; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
%0:_(s16) = COPY $h0
%1:_(s32) = G_ZEXT %0(s16)
%2:_(s64) = G_SEXT %1(s32)
@@ -267,8 +268,10 @@ body: |
; CHECK: liveins: $h0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
- ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
- ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s32) = G_ZEXT [[COPY]](s16)
+ ; CHECK-NEXT: [[ASSERT_ZEXT:%[0-9]+]]:_(s32) = G_ASSERT_ZEXT [[ZEXT]], 11
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[ASSERT_ZEXT]](s32)
+ ; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
%0:_(s16) = COPY $h0
%1:_(s32) = G_ZEXT %0(s16)
%2:_(s32) = G_ASSERT_ZEXT %1(s32), 11
@@ -284,8 +287,9 @@ body: |
; CHECK: liveins: $s0
; CHECK-NEXT: {{ $}}
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(<2 x s16>) = COPY $s0
- ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s64>) = G_ZEXT [[COPY]](<2 x s16>)
- ; CHECK-NEXT: $q0 = COPY [[ZEXT]](<2 x s64>)
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(<2 x s32>) = G_ZEXT [[COPY]](<2 x s16>)
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(<2 x s64>) = G_SEXT [[ZEXT]](<2 x s32>)
+ ; CHECK-NEXT: $q0 = COPY [[SEXT]](<2 x s64>)
%0:_(<2 x s16>) = COPY $s0
%1:_(<2 x s32>) = G_ZEXT %0(<2 x s16>)
%2:_(<2 x s64>) = G_SEXT %1(<2 x s32>)
@@ -340,3 +344,67 @@ body: |
%2:_(<2 x s64>) = G_ZEXT %1(<2 x s32>)
$q0 = COPY %2(<2 x s64>)
...
+---
+name: test_combine_zext_anyext
+body: |
+ bb.1:
+ liveins: $h0
+ ; CHECK-LABEL: name: test_combine_zext_anyext
+ ; CHECK: liveins: $h0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+ ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[COPY]](s16)
+ ; CHECK-NEXT: $x0 = COPY [[ZEXT]](s64)
+ %0:_(s16) = COPY $h0
+ %1:_(s32) = G_ANYEXT %0(s16)
+ %2:_(s64) = G_ZEXT %1(s32)
+ $x0 = COPY %2(s64)
+...
+---
+name: test_combine_sext_anyext
+body: |
+ bb.1:
+ liveins: $h0
+ ; CHECK-LABEL: name: test_combine_sext_anyext
+ ; CHECK: liveins: $h0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+ ; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[COPY]](s16)
+ ; CHECK-NEXT: $x0 = COPY [[SEXT]](s64)
+ %0:_(s16) = COPY $h0
+ %1:_(s32) = G_ANYEXT %0(s16)
+ %2:_(s64) = G_SEXT %1(s32)
+ $x0 = COPY %2(s64)
+...
+---
+name: test_combine_nneg_zext_anyext
+body: |
+ bb.1:
+ liveins: $h0
+ ; CHECK-LABEL: name: test_combine_nneg_zext_anyext
+ ; CHECK: liveins: $h0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+ ; CHECK-NEXT: %2:_(s64) = nneg G_ZEXT [[COPY]](s16)
+ ; CHECK-NEXT: $x0 = COPY %2(s64)
+ %0:_(s16) = COPY $h0
+ %1:_(s32) = G_ANYEXT %0(s16)
+ %2:_(s64) = nneg G_ZEXT %1(s32)
+ $x0 = COPY %2(s64)
+...
+---
+name: test_combine_anyext_nneg_zext
+body: |
+ bb.1:
+ liveins: $h0
+ ; CHECK-LABEL: name: test_combine_anyext_nneg_zext
+ ; CHECK: liveins: $h0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s16) = COPY $h0
+ ; CHECK-NEXT: %2:_(s64) = nneg G_ZEXT [[COPY]](s16)
+ ; CHECK-NEXT: $x0 = COPY %2(s64)
+ %0:_(s16) = COPY $h0
+ %1:_(s32) = nneg G_ZEXT %0(s16)
+ %2:_(s64) = G_ANYEXT %1(s32)
+ $x0 = COPY %2(s64)
+...
More information about the llvm-commits
mailing list