Skip to content

Commit 0cf3c29

Browse files
committed
1 parent 7ef602b commit 0cf3c29

File tree

5 files changed

+297
-1
lines changed

5 files changed

+297
-1
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,12 @@ class CombinerHelper {
809809
/// Match constant LHS ops that should be commuted.
810810
bool matchCommuteConstantToRHS(MachineInstr &MI);
811811

812+
/// Combine sext of trunc.
813+
bool matchSextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo);
814+
815+
/// Combine zext of trunc.
816+
bool matchZextOfTrunc(const MachineOperand &MO, BuildFnTy &MatchInfo);
817+
812818
/// Match constant LHS FP ops that should be commuted.
813819
bool matchCommuteFPConstantToRHS(MachineInstr &MI);
814820

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

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -780,6 +780,58 @@ class GFreeze : public GenericMachineInstr {
780780
}
781781
};
782782

783+
/// Represents a cast operation.
784+
/// It models the llvm::CastInst concept.
785+
/// The exception is bitcast.
786+
class GCastOp : public GenericMachineInstr {
787+
public:
788+
Register getSrcReg() const { return getOperand(1).getReg(); }
789+
790+
static bool classof(const MachineInstr *MI) {
791+
switch (MI->getOpcode()) {
792+
case TargetOpcode::G_ADDRSPACE_CAST:
793+
case TargetOpcode::G_FPEXT:
794+
case TargetOpcode::G_FPTOSI:
795+
case TargetOpcode::G_FPTOUI:
796+
case TargetOpcode::G_FPTRUNC:
797+
case TargetOpcode::G_INTTOPTR:
798+
case TargetOpcode::G_PTRTOINT:
799+
case TargetOpcode::G_SEXT:
800+
case TargetOpcode::G_SITOFP:
801+
case TargetOpcode::G_TRUNC:
802+
case TargetOpcode::G_UITOFP:
803+
case TargetOpcode::G_ZEXT:
804+
return true;
805+
default:
806+
return false;
807+
}
808+
};
809+
};
810+
811+
/// Represents a sext.
812+
class GSext : public GCastOp {
813+
public:
814+
static bool classof(const MachineInstr *MI) {
815+
return MI->getOpcode() == TargetOpcode::G_SEXT;
816+
};
817+
};
818+
819+
/// Represents a zext.
820+
class GZext : public GCastOp {
821+
public:
822+
static bool classof(const MachineInstr *MI) {
823+
return MI->getOpcode() == TargetOpcode::G_ZEXT;
824+
};
825+
};
826+
827+
/// Represents a trunc.
828+
class GTrunc : public GCastOp {
829+
public:
830+
static bool classof(const MachineInstr *MI) {
831+
return MI->getOpcode() == TargetOpcode::G_TRUNC;
832+
};
833+
};
834+
783835
} // namespace llvm
784836

785837
#endif // LLVM_CODEGEN_GLOBALISEL_GENERICMACHINEINSTRS_H

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ def FmContract : MIFlagEnum<"FmContract">;
180180
def FmAfn : MIFlagEnum<"FmAfn">;
181181
def FmReassoc : MIFlagEnum<"FmReassoc">;
182182
def IsExact : MIFlagEnum<"IsExact">;
183+
def NoSWrap : MIFlagEnum<"NoSWrap">;
184+
def NoUWrap : MIFlagEnum<"NoUWrap">;
183185

184186
def MIFlags;
185187
// def not; -> Already defined as a SDNode
@@ -1497,6 +1499,19 @@ def extract_vector_element_freeze : GICombineRule<
14971499
(match (G_FREEZE $src, $input),
14981500
(G_EXTRACT_VECTOR_ELT $root, $src, $idx),
14991501
[{ return Helper.matchExtractVectorElementWithFreeze(${root}, ${matchinfo}); }]),
1502+
1503+
def sext_trunc : GICombineRule<
1504+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1505+
(match (G_TRUNC $src, $x, (MIFlags NoSWrap)),
1506+
(G_SEXT $root, $src),
1507+
[{ return Helper.matchSextOfTrunc(${root}, ${matchinfo}); }]),
1508+
(apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
1509+
1510+
def zext_trunc : GICombineRule<
1511+
(defs root:$root, build_fn_matchinfo:$matchinfo),
1512+
(match (G_TRUNC $src, $x, (MIFlags NoUWrap)),
1513+
(G_ZEXT $root, $src),
1514+
[{ return Helper.matchZextOfTrunc(${root}, ${matchinfo}); }]),
15001515
(apply [{ Helper.applyBuildFnMO(${root}, ${matchinfo}); }])>;
15011516

15021517
// Combines concat operations
@@ -1614,7 +1629,8 @@ def all_combines : GICombineGroup<[trivial_combines, vector_ops_combines,
16141629
and_or_disjoint_mask, fma_combines, fold_binop_into_select,
16151630
sub_add_reg, select_to_minmax, redundant_binop_in_equality,
16161631
fsub_to_fneg, commute_constant_to_rhs, match_ands, match_ors,
1617-
combine_concat_vector, double_icmp_zero_and_or_combine, match_addos]>;
1632+
combine_concat_vector, double_icmp_zero_and_or_combine, match_addos,
1633+
sext_trunc, zext_trunc]>;
16181634

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

llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7146,3 +7146,69 @@ bool CombinerHelper::matchAddOverflow(MachineInstr &MI, BuildFnTy &MatchInfo) {
71467146

71477147
return false;
71487148
}
7149+
7150+
void CombinerHelper::applyBuildFnMO(const MachineOperand &MO,
7151+
BuildFnTy &MatchInfo) {
7152+
MachineInstr *Root = getDefIgnoringCopies(MO.getReg(), MRI);
7153+
Builder.setInstrAndDebugLoc(*Root);
7154+
MatchInfo(Builder);
7155+
Root->eraseFromParent();
7156+
}
7157+
7158+
bool CombinerHelper::matchSextOfTrunc(const MachineOperand &MO,
7159+
BuildFnTy &MatchInfo) {
7160+
GSext *Sext = getOpcodeDef<GSext>(MO.getReg(), MRI);
7161+
if (!Sext)
7162+
return false;
7163+
7164+
GTrunc *Trunc = getOpcodeDef<GTrunc>(Sext->getSrcReg(), MRI);
7165+
if (!Trunc)
7166+
return false;
7167+
7168+
// The trunc must have the nsw flag.
7169+
if (!Trunc->getFlag(MachineInstr::MIFlag::NoSWrap))
7170+
return false;
7171+
7172+
Register Dst = Sext->getReg(0);
7173+
Register Src = Trunc->getSrcReg();
7174+
7175+
LLT DstTy = MRI.getType(Dst);
7176+
LLT SrcTy = MRI.getType(Src);
7177+
7178+
// The types have to match for a no-op.
7179+
if (DstTy != SrcTy)
7180+
return false;
7181+
7182+
MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
7183+
7184+
return true;
7185+
}
7186+
7187+
bool CombinerHelper::matchZextOfTrunc(const MachineOperand &MO,
7188+
BuildFnTy &MatchInfo) {
7189+
GZext *Zext = getOpcodeDef<GZext>(MO.getReg(), MRI);
7190+
if (!Zext)
7191+
return false;
7192+
7193+
GTrunc *Trunc = getOpcodeDef<GTrunc>(Zext->getSrcReg(), MRI);
7194+
if (!Trunc)
7195+
return false;
7196+
7197+
// The trunc must have the nuw flag.
7198+
if (!Trunc->getFlag(MachineInstr::MIFlag::NoUWrap))
7199+
return false;
7200+
7201+
Register Dst = Zext->getReg(0);
7202+
Register Src = Trunc->getSrcReg();
7203+
7204+
LLT DstTy = MRI.getType(Dst);
7205+
LLT SrcTy = MRI.getType(Src);
7206+
7207+
// The types have to match for a no-op.
7208+
if (DstTy != SrcTy)
7209+
return false;
7210+
7211+
MatchInfo = [=](MachineIRBuilder &B) { B.buildCopy(Dst, Src); };
7212+
7213+
return true;
7214+
}
Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py
2+
# RUN: llc -run-pass=aarch64-prelegalizer-combiner -verify-machineinstrs -mtriple aarch64-unknown-unknown %s -o - | FileCheck %s
3+
4+
---
5+
name: zext_trunc_nuw
6+
body: |
7+
bb.0:
8+
liveins: $w0, $w1
9+
; CHECK-LABEL: name: zext_trunc_nuw
10+
; CHECK: liveins: $w0, $w1
11+
; CHECK-NEXT: {{ $}}
12+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
13+
; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
14+
%0:_(s64) = COPY $x0
15+
%2:_(s32) = nuw G_TRUNC %0
16+
%3:_(s64) = G_ZEXT %2
17+
$x1 = COPY %3
18+
...
19+
---
20+
name: zext_trunc_nsw
21+
body: |
22+
bb.0:
23+
liveins: $w0, $w1
24+
; CHECK-LABEL: name: zext_trunc_nsw
25+
; CHECK: liveins: $w0, $w1
26+
; CHECK-NEXT: {{ $}}
27+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
28+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nsw G_TRUNC [[COPY]](s64)
29+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s32)
30+
; CHECK-NEXT: $x1 = COPY [[ZEXT]](s64)
31+
%0:_(s64) = COPY $x0
32+
%2:_(s32) = nsw G_TRUNC %0
33+
%3:_(s64) = G_ZEXT %2
34+
$x1 = COPY %3
35+
...
36+
---
37+
name: zext_trunc
38+
body: |
39+
bb.0:
40+
liveins: $w0, $w1
41+
; CHECK-LABEL: name: zext_trunc
42+
; CHECK: liveins: $w0, $w1
43+
; CHECK-NEXT: {{ $}}
44+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
45+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
46+
; CHECK-NEXT: [[ZEXT:%[0-9]+]]:_(s64) = G_ZEXT [[TRUNC]](s32)
47+
; CHECK-NEXT: $x1 = COPY [[ZEXT]](s64)
48+
%0:_(s64) = COPY $x0
49+
%2:_(s32) = G_TRUNC %0
50+
%3:_(s64) = G_ZEXT %2
51+
$x1 = COPY %3
52+
...
53+
---
54+
name: zext_trunc_nuw_vector
55+
body: |
56+
bb.0:
57+
liveins: $w0, $w1
58+
; CHECK-LABEL: name: zext_trunc_nuw_vector
59+
; CHECK: liveins: $w0, $w1
60+
; CHECK-NEXT: {{ $}}
61+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s32) = COPY $w0
62+
; CHECK-NEXT: [[COPY1:%[0-9]+]]:_(s32) = COPY $w1
63+
; CHECK-NEXT: %bv0:_(<4 x s32>) = G_BUILD_VECTOR [[COPY]](s32), [[COPY1]](s32), [[COPY]](s32), [[COPY1]](s32)
64+
; CHECK-NEXT: $q0 = COPY %bv0(<4 x s32>)
65+
; CHECK-NEXT: RET_ReallyLR implicit $w0
66+
%0:_(s32) = COPY $w0
67+
%1:_(s32) = COPY $w1
68+
%2:_(s32) = COPY $w2
69+
%3:_(s32) = COPY $w3
70+
%bv0:_(<4 x s32>) = G_BUILD_VECTOR %0:_(s32), %1:_(s32), %0:_(s32), %1:_(s32)
71+
%trunc:_(<4 x s16>) = nuw G_TRUNC %bv0
72+
%zext:_(<4 x s32>) = G_ZEXT %trunc
73+
$q0 = COPY %zext(<4 x s32>)
74+
RET_ReallyLR implicit $w0
75+
...
76+
---
77+
name: sext_trunc_nsw
78+
body: |
79+
bb.0:
80+
liveins: $w0, $w1
81+
; CHECK-LABEL: name: sext_trunc_nsw
82+
; CHECK: liveins: $w0, $w1
83+
; CHECK-NEXT: {{ $}}
84+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
85+
; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
86+
%0:_(s64) = COPY $x0
87+
%2:_(s32) = nsw G_TRUNC %0
88+
%3:_(s64) = G_SEXT %2
89+
$x1 = COPY %3
90+
...
91+
---
92+
name: sext_trunc_nuw
93+
body: |
94+
bb.0:
95+
liveins: $w0, $w1
96+
; CHECK-LABEL: name: sext_trunc_nuw
97+
; CHECK: liveins: $w0, $w1
98+
; CHECK-NEXT: {{ $}}
99+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
100+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = nuw G_TRUNC [[COPY]](s64)
101+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
102+
; CHECK-NEXT: $x1 = COPY [[SEXT]](s64)
103+
%0:_(s64) = COPY $x0
104+
%2:_(s32) = nuw G_TRUNC %0
105+
%3:_(s64) = G_SEXT %2
106+
$x1 = COPY %3
107+
...
108+
---
109+
name: sext_trunc
110+
body: |
111+
bb.0:
112+
liveins: $w0, $w1
113+
; CHECK-LABEL: name: sext_trunc
114+
; CHECK: liveins: $w0, $w1
115+
; CHECK-NEXT: {{ $}}
116+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
117+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[COPY]](s64)
118+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s64) = G_SEXT [[TRUNC]](s32)
119+
; CHECK-NEXT: $x1 = COPY [[SEXT]](s64)
120+
%0:_(s64) = COPY $x0
121+
%2:_(s32) = G_TRUNC %0
122+
%3:_(s64) = G_SEXT %2
123+
$x1 = COPY %3
124+
...
125+
---
126+
name: sext_trunc_nsw_types_wrong
127+
body: |
128+
bb.0:
129+
liveins: $w0, $w1
130+
; CHECK-LABEL: name: sext_trunc_nsw_types_wrong
131+
; CHECK: liveins: $w0, $w1
132+
; CHECK-NEXT: {{ $}}
133+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
134+
; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s16) = nsw G_TRUNC [[COPY]](s64)
135+
; CHECK-NEXT: [[SEXT:%[0-9]+]]:_(s32) = G_SEXT [[TRUNC]](s16)
136+
; CHECK-NEXT: $w1 = COPY [[SEXT]](s32)
137+
%0:_(s64) = COPY $x0
138+
%2:_(s16) = nsw G_TRUNC %0
139+
%3:_(s32) = G_SEXT %2
140+
$w1 = COPY %3
141+
...
142+
---
143+
name: sext_trunc_nsw_nuw
144+
body: |
145+
bb.0:
146+
liveins: $w0, $w1
147+
; CHECK-LABEL: name: sext_trunc_nsw_nuw
148+
; CHECK: liveins: $w0, $w1
149+
; CHECK-NEXT: {{ $}}
150+
; CHECK-NEXT: [[COPY:%[0-9]+]]:_(s64) = COPY $x0
151+
; CHECK-NEXT: $x1 = COPY [[COPY]](s64)
152+
%0:_(s64) = COPY $x0
153+
%2:_(s32) = nsw nuw G_TRUNC %0
154+
%3:_(s64) = G_SEXT %2
155+
$x1 = COPY %3
156+
...

0 commit comments

Comments
 (0)