Skip to content

Commit 1814899

Browse files
Set up basic legalization (scalar only, limited support for FP, p0 only)
1 parent 63fc530 commit 1814899

File tree

2 files changed

+258
-0
lines changed

2 files changed

+258
-0
lines changed

llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "WebAssemblyLegalizerInfo.h"
14+
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
15+
#include "WebAssemblySubtarget.h"
16+
#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
17+
#include "llvm/CodeGen/MachineInstr.h"
18+
#include "llvm/CodeGen/TargetOpcodes.h"
19+
#include "llvm/IR/DerivedTypes.h"
1420

1521
#define DEBUG_TYPE "wasm-legalinfo"
1622

@@ -19,5 +25,255 @@ using namespace LegalizeActions;
1925

2026
WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
2127
const WebAssemblySubtarget &ST) {
28+
using namespace TargetOpcode;
29+
const LLT s8 = LLT::scalar(8);
30+
const LLT s16 = LLT::scalar(16);
31+
const LLT s32 = LLT::scalar(32);
32+
const LLT s64 = LLT::scalar(64);
33+
34+
const LLT p0 = LLT::pointer(0, ST.hasAddr64() ? 64 : 32);
35+
const LLT p0s = LLT::scalar(ST.hasAddr64() ? 64 : 32);
36+
37+
getActionDefinitionsBuilder(G_GLOBAL_VALUE).legalFor({p0});
38+
39+
getActionDefinitionsBuilder(G_PHI)
40+
.legalFor({p0, s32, s64})
41+
.widenScalarToNextPow2(0)
42+
.clampScalar(0, s32, s64);
43+
getActionDefinitionsBuilder(G_BR).alwaysLegal();
44+
getActionDefinitionsBuilder(G_BRCOND).legalFor({s32}).clampScalar(0, s32,
45+
s32);
46+
getActionDefinitionsBuilder(G_BRJT)
47+
.legalFor({{p0, s32}})
48+
.clampScalar(1, s32, s32);
49+
50+
getActionDefinitionsBuilder(G_SELECT)
51+
.legalFor({{s32, s32}, {s64, s32}, {p0, s32}})
52+
.widenScalarToNextPow2(0)
53+
.clampScalar(0, s32, s64)
54+
.clampScalar(1, s32, s32);
55+
56+
getActionDefinitionsBuilder(G_JUMP_TABLE).legalFor({p0});
57+
58+
getActionDefinitionsBuilder(G_ICMP)
59+
.legalFor({{s32, s32}, {s32, s64}, {s32, p0}})
60+
.widenScalarToNextPow2(1)
61+
.clampScalar(1, s32, s64)
62+
.clampScalar(0, s32, s32);
63+
64+
getActionDefinitionsBuilder(G_FCMP)
65+
.legalFor({{s32, s32}, {s32, s64}})
66+
.clampScalar(0, s32, s32)
67+
.libcall();
68+
69+
getActionDefinitionsBuilder(G_FRAME_INDEX).legalFor({p0});
70+
71+
getActionDefinitionsBuilder(G_CONSTANT)
72+
.legalFor({s32, s64, p0})
73+
.widenScalarToNextPow2(0)
74+
.clampScalar(0, s32, s64);
75+
76+
getActionDefinitionsBuilder(G_FCONSTANT)
77+
.legalFor({s32, s64})
78+
.clampScalar(0, s32, s64);
79+
80+
getActionDefinitionsBuilder(G_IMPLICIT_DEF)
81+
.legalFor({s32, s64, p0})
82+
.widenScalarToNextPow2(0)
83+
.clampScalar(0, s32, s64);
84+
85+
getActionDefinitionsBuilder(
86+
{G_ADD, G_SUB, G_MUL, G_UDIV, G_SDIV, G_UREM, G_SREM})
87+
.legalFor({s32, s64})
88+
.widenScalarToNextPow2(0)
89+
.clampScalar(0, s32, s64);
90+
91+
getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL, G_CTLZ, G_CTLZ_ZERO_UNDEF,
92+
G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTPOP, G_FSHL,
93+
G_FSHR})
94+
.legalFor({{s32, s32}, {s64, s64}})
95+
.widenScalarToNextPow2(0)
96+
.clampScalar(0, s32, s64)
97+
.minScalarSameAs(1, 0)
98+
.maxScalarSameAs(1, 0);
99+
100+
getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
101+
102+
getActionDefinitionsBuilder({G_AND, G_OR, G_XOR})
103+
.legalFor({s32, s64})
104+
.widenScalarToNextPow2(0)
105+
.clampScalar(0, s32, s64);
106+
107+
getActionDefinitionsBuilder({G_UMIN, G_UMAX, G_SMIN, G_SMAX}).lower();
108+
109+
getActionDefinitionsBuilder({G_FADD, G_FSUB, G_FDIV, G_FMUL, G_FNEG, G_FABS,
110+
G_FCEIL, G_FFLOOR, G_FSQRT, G_INTRINSIC_TRUNC,
111+
G_FNEARBYINT, G_FRINT, G_INTRINSIC_ROUNDEVEN,
112+
G_FMINIMUM, G_FMAXIMUM})
113+
.legalFor({s32, s64})
114+
.minScalar(0, s32);
115+
116+
// TODO: _IEEE not lowering correctly?
117+
getActionDefinitionsBuilder(
118+
{G_FMINNUM, G_FMAXNUM, G_FMINNUM_IEEE, G_FMAXNUM_IEEE})
119+
.lowerFor({s32, s64})
120+
.minScalar(0, s32);
121+
122+
getActionDefinitionsBuilder({G_FMA, G_FREM})
123+
.libcallFor({s32, s64})
124+
.minScalar(0, s32);
125+
126+
getActionDefinitionsBuilder(G_FCOPYSIGN)
127+
.legalFor({s32, s64})
128+
.minScalar(0, s32)
129+
.minScalarSameAs(1, 0)
130+
.maxScalarSameAs(1, 0);
131+
132+
getActionDefinitionsBuilder({G_FPTOUI, G_FPTOUI_SAT, G_FPTOSI, G_FPTOSI_SAT})
133+
.legalForCartesianProduct({s32, s64}, {s32, s64})
134+
.minScalar(1, s32)
135+
.widenScalarToNextPow2(0)
136+
.clampScalar(0, s32, s64);
137+
138+
getActionDefinitionsBuilder({G_UITOFP, G_SITOFP})
139+
.legalForCartesianProduct({s32, s64}, {s32, s64})
140+
.minScalar(1, s32)
141+
.widenScalarToNextPow2(1)
142+
.clampScalar(1, s32, s64);
143+
144+
getActionDefinitionsBuilder(G_PTRTOINT).legalFor({{p0s, p0}});
145+
getActionDefinitionsBuilder(G_INTTOPTR).legalFor({{p0, p0s}});
146+
getActionDefinitionsBuilder(G_PTR_ADD).legalFor({{p0, p0s}});
147+
148+
getActionDefinitionsBuilder(G_LOAD)
149+
.legalForTypesWithMemDesc(
150+
{{s32, p0, s32, 1}, {s64, p0, s64, 1}, {p0, p0, p0, 1}})
151+
.legalForTypesWithMemDesc({{s32, p0, s8, 1},
152+
{s32, p0, s16, 1},
153+
154+
{s64, p0, s8, 1},
155+
{s64, p0, s16, 1},
156+
{s64, p0, s32, 1}})
157+
.widenScalarToNextPow2(0)
158+
.lowerIfMemSizeNotByteSizePow2()
159+
.clampScalar(0, s32, s64);
160+
161+
getActionDefinitionsBuilder(G_STORE)
162+
.legalForTypesWithMemDesc(
163+
{{s32, p0, s32, 1}, {s64, p0, s64, 1}, {p0, p0, p0, 1}})
164+
.legalForTypesWithMemDesc({{s32, p0, s8, 1},
165+
{s32, p0, s16, 1},
166+
167+
{s64, p0, s8, 1},
168+
{s64, p0, s16, 1},
169+
{s64, p0, s32, 1}})
170+
.widenScalarToNextPow2(0)
171+
.lowerIfMemSizeNotByteSizePow2()
172+
.clampScalar(0, s32, s64);
173+
174+
getActionDefinitionsBuilder({G_ZEXTLOAD, G_SEXTLOAD})
175+
.legalForTypesWithMemDesc({{s32, p0, s8, 1},
176+
{s32, p0, s16, 1},
177+
178+
{s64, p0, s8, 1},
179+
{s64, p0, s16, 1},
180+
{s64, p0, s32, 1}})
181+
.widenScalarToNextPow2(0)
182+
.lowerIfMemSizeNotByteSizePow2()
183+
.clampScalar(0, s32, s64)
184+
.lower();
185+
186+
if (ST.hasBulkMemoryOpt()) {
187+
getActionDefinitionsBuilder(G_BZERO).unsupported();
188+
189+
getActionDefinitionsBuilder(G_MEMSET)
190+
.legalForCartesianProduct({p0}, {s32}, {p0s})
191+
.customForCartesianProduct({p0}, {s8}, {p0s})
192+
.immIdx(0);
193+
194+
getActionDefinitionsBuilder({G_MEMCPY, G_MEMMOVE})
195+
.legalForCartesianProduct({p0}, {p0}, {p0s})
196+
.immIdx(0);
197+
198+
getActionDefinitionsBuilder(G_MEMCPY_INLINE)
199+
.legalForCartesianProduct({p0}, {p0}, {p0s});
200+
} else {
201+
getActionDefinitionsBuilder({G_BZERO, G_MEMCPY, G_MEMMOVE, G_MEMSET})
202+
.libcall();
203+
}
204+
205+
// TODO: figure out how to combine G_ANYEXT of G_ASSERT_{S|Z}EXT (or
206+
// appropriate G_AND and G_SEXT_IN_REG?) to a G_{S|Z}EXT + G_ASSERT_{S|Z}EXT
207+
// for better optimization (since G_ANYEXT lowers to a ZEXT or SEXT
208+
// instruction anyway).
209+
210+
getActionDefinitionsBuilder(G_ANYEXT)
211+
.legalFor({{s64, s32}})
212+
.clampScalar(0, s32, s64)
213+
.clampScalar(1, s32, s64);
214+
215+
getActionDefinitionsBuilder({G_SEXT, G_ZEXT})
216+
.legalFor({{s64, s32}})
217+
.clampScalar(0, s32, s64)
218+
.clampScalar(1, s32, s64)
219+
.lower();
220+
221+
if (ST.hasSignExt()) {
222+
getActionDefinitionsBuilder(G_SEXT_INREG)
223+
.clampScalar(0, s32, s64)
224+
.customFor({s32, s64})
225+
.lower();
226+
} else {
227+
getActionDefinitionsBuilder(G_SEXT_INREG).lower();
228+
}
229+
230+
getActionDefinitionsBuilder(G_TRUNC)
231+
.legalFor({{s32, s64}})
232+
.clampScalar(0, s32, s64)
233+
.clampScalar(1, s32, s64)
234+
.lower();
235+
236+
getActionDefinitionsBuilder(G_FPEXT).legalFor({{s64, s32}});
237+
238+
getActionDefinitionsBuilder(G_FPTRUNC).legalFor({{s32, s64}});
239+
240+
getActionDefinitionsBuilder(G_VASTART).legalFor({p0});
241+
getActionDefinitionsBuilder(G_VAARG)
242+
.legalForCartesianProduct({s32, s64}, {p0})
243+
.clampScalar(0, s32, s64);
244+
22245
getLegacyLegalizerInfo().computeTables();
23246
}
247+
248+
bool WebAssemblyLegalizerInfo::legalizeCustom(
249+
LegalizerHelper &Helper, MachineInstr &MI,
250+
LostDebugLocObserver &LocObserver) const {
251+
switch (MI.getOpcode()) {
252+
case TargetOpcode::G_SEXT_INREG: {
253+
// Mark only 8/16/32-bit SEXT_INREG as legal
254+
auto [DstType, SrcType] = MI.getFirst2LLTs();
255+
auto ExtFromWidth = MI.getOperand(2).getImm();
256+
257+
if (ExtFromWidth == 8 || ExtFromWidth == 16 ||
258+
(DstType.getScalarSizeInBits() == 64 && ExtFromWidth == 32)) {
259+
return true;
260+
}
261+
return false;
262+
}
263+
case TargetOpcode::G_MEMSET: {
264+
// Anyext the value being set to 32 bit (only the bottom 8 bits are read by
265+
// the instruction).
266+
Helper.Observer.changingInstr(MI);
267+
auto &Value = MI.getOperand(1);
268+
269+
Register ExtValueReg =
270+
Helper.MIRBuilder.buildAnyExt(LLT::scalar(32), Value).getReg(0);
271+
Value.setReg(ExtValueReg);
272+
Helper.Observer.changedInstr(MI);
273+
return true;
274+
}
275+
default:
276+
break;
277+
}
278+
return false;
279+
}

llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ class WebAssemblySubtarget;
2424
class WebAssemblyLegalizerInfo : public LegalizerInfo {
2525
public:
2626
WebAssemblyLegalizerInfo(const WebAssemblySubtarget &ST);
27+
28+
bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI, LostDebugLocObserver &LocObserver) const override;
2729
};
2830
} // namespace llvm
2931
#endif

0 commit comments

Comments
 (0)