blob: ccc331d1bf03203f5cbde16a1a9042dc52123a9b [file] [log] [blame]
JF Bastien5ca0bac2015-07-10 18:23:10 +00001// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// WebAssembly Memory operand code-gen constructs.
JF Bastien5ca0bac2015-07-10 18:23:10 +000012///
13//===----------------------------------------------------------------------===//
14
Dan Gohman9c54d3b2015-11-25 18:13:18 +000015// TODO:
JF Bastien73ff6af2015-08-31 22:24:11 +000016// - HasAddr64
JF Bastien73ff6af2015-08-31 22:24:11 +000017// - WebAssemblyTargetLowering having to do with atomics
Dan Gohman4b9d7912015-12-15 22:01:29 +000018// - Each has optional alignment.
JF Bastien73ff6af2015-08-31 22:24:11 +000019
20// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
21// local types. These memory-only types instead zero- or sign-extend into local
22// types when loading, and truncate when storing.
23
Dan Gohman4b9d7912015-12-15 22:01:29 +000024// WebAssembly constant offsets are performed as unsigned with infinite
25// precision, so we need to check for NoUnsignedWrap so that we don't fold an
26// offset for an add that needs wrapping.
Dan Gohmanf225a632016-01-11 22:05:44 +000027def regPlusImm : PatFrag<(ops node:$addr, node:$off),
Dan Gohman4b9d7912015-12-15 22:01:29 +000028 (add node:$addr, node:$off),
Derek Schuff2fa36042017-05-01 16:49:39 +000029 [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
Dan Gohman4b9d7912015-12-15 22:01:29 +000030
Dan Gohman3b09d272016-02-22 20:04:02 +000031// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
32def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
33 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
34 return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
35
Craig Topper053cf4d2017-04-28 08:15:33 +000036 KnownBits Known0;
37 CurDAG->computeKnownBits(N->getOperand(0), Known0, 0);
38 KnownBits Known1;
39 CurDAG->computeKnownBits(N->getOperand(1), Known1, 0);
40 return (~Known0.Zero & ~Known1.Zero) == 0;
Dan Gohman3b09d272016-02-22 20:04:02 +000041}]>;
42
Dan Gohmanf225a632016-01-11 22:05:44 +000043// GlobalAddresses are conceptually unsigned values, so we can also fold them
Derek Schuff1b258d32016-08-31 20:27:20 +000044// into immediate values as long as the add is 'nuw'.
45// TODO: We'd like to also match GA offsets but there are cases where the
46// register can have a negative value. Find out what more we can do.
Dan Gohmanf225a632016-01-11 22:05:44 +000047def regPlusGA : PatFrag<(ops node:$addr, node:$off),
48 (add node:$addr, node:$off),
49 [{
Derek Schuff2fa36042017-05-01 16:49:39 +000050 return N->getFlags().hasNoUnsignedWrap();
Dan Gohmanf225a632016-01-11 22:05:44 +000051}]>;
52
53// We don't need a regPlusES because external symbols never have constant
54// offsets folded into them, so we can just use add.
55
Derek Schuff885dc592017-10-05 21:18:42 +000056// Defines atomic and non-atomic loads, regular and extending.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000057multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> {
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000058 let mayLoad = 1 in
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000059 defm "": I<(outs rc:$dst),
60 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
61 (outs), (ins P2Align:$p2align, offset32_op:$off),
62 [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000063 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000064}
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000065
JF Bastien73ff6af2015-08-31 22:24:11 +000066// Basic load.
Dan Gohman48abaa92016-10-25 00:17:11 +000067// FIXME: When we can break syntax compatibility, reorder the fields in the
68// asmstrings to match the binary encoding.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000069defm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>;
70defm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>;
71defm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>;
72defm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>;
JF Bastien73ff6af2015-08-31 22:24:11 +000073
Dan Gohman4b9d7912015-12-15 22:01:29 +000074// Select loads with no constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +000075class LoadPatNoOffset<ValueType ty, PatFrag kind, NI inst> :
76 Pat<(ty (kind I32:$addr)), (inst 0, 0, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000077
78def : LoadPatNoOffset<i32, load, LOAD_I32>;
79def : LoadPatNoOffset<i64, load, LOAD_I64>;
80def : LoadPatNoOffset<f32, load, LOAD_F32>;
81def : LoadPatNoOffset<f64, load, LOAD_F64>;
82
Dan Gohman4b9d7912015-12-15 22:01:29 +000083
84// Select loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000085
86// Pattern with address + immediate offset
Heejin Ahnd31bc982018-07-09 20:18:21 +000087class LoadPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
88 Pat<(ty (kind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000089
90def : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>;
91def : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>;
92def : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>;
93def : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>;
94def : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>;
95def : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>;
96def : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>;
97def : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>;
98
Heejin Ahnd31bc982018-07-09 20:18:21 +000099class LoadPatGlobalAddr<ValueType ty, PatFrag kind, NI inst> :
100 Pat<(ty (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))),
101 (inst 0, tglobaladdr:$off, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000102
103def : LoadPatGlobalAddr<i32, load, LOAD_I32>;
104def : LoadPatGlobalAddr<i64, load, LOAD_I64>;
105def : LoadPatGlobalAddr<f32, load, LOAD_F32>;
106def : LoadPatGlobalAddr<f64, load, LOAD_F64>;
107
Heejin Ahnd31bc982018-07-09 20:18:21 +0000108class LoadPatExternalSym<ValueType ty, PatFrag kind, NI inst> :
109 Pat<(ty (kind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
110 (inst 0, texternalsym:$off, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000111def : LoadPatExternalSym<i32, load, LOAD_I32>;
112def : LoadPatExternalSym<i64, load, LOAD_I64>;
113def : LoadPatExternalSym<f32, load, LOAD_F32>;
114def : LoadPatExternalSym<f64, load, LOAD_F64>;
115
Dan Gohman4b9d7912015-12-15 22:01:29 +0000116
117// Select loads with just a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000118class LoadPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
119 Pat<(ty (kind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000120
121def : LoadPatOffsetOnly<i32, load, LOAD_I32>;
122def : LoadPatOffsetOnly<i64, load, LOAD_I64>;
123def : LoadPatOffsetOnly<f32, load, LOAD_F32>;
124def : LoadPatOffsetOnly<f64, load, LOAD_F64>;
125
Heejin Ahnd31bc982018-07-09 20:18:21 +0000126class LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
127 Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))),
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000128 (inst 0, tglobaladdr:$off, (CONST_I32 0))>;
129
130def : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>;
131def : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>;
132def : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>;
133def : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>;
134
Heejin Ahnd31bc982018-07-09 20:18:21 +0000135class LoadPatExternSymOffOnly<ValueType ty, PatFrag kind, NI inst> :
136 Pat<(ty (kind (WebAssemblywrapper texternalsym:$off))),
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000137 (inst 0, texternalsym:$off, (CONST_I32 0))>;
138def : LoadPatExternSymOffOnly<i32, load, LOAD_I32>;
139def : LoadPatExternSymOffOnly<i64, load, LOAD_I64>;
140def : LoadPatExternSymOffOnly<f32, load, LOAD_F32>;
141def : LoadPatExternSymOffOnly<f64, load, LOAD_F64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000142
JF Bastien73ff6af2015-08-31 22:24:11 +0000143// Extending load.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000144defm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>;
145defm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>;
146defm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>;
147defm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>;
148defm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>;
149defm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>;
150defm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>;
151defm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>;
152defm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>;
153defm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000154
Derek Schuff9d779522015-12-05 00:26:39 +0000155// Select extending loads with no constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000156def : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>;
157def : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>;
158def : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>;
159def : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>;
160def : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>;
161def : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>;
162def : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>;
163def : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>;
164def : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>;
165def : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>;
Derek Schuff9d779522015-12-05 00:26:39 +0000166
Dan Gohman4b9d7912015-12-15 22:01:29 +0000167// Select extending loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000168def : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>;
169def : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>;
170def : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>;
171def : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>;
172def : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>;
173def : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>;
174def : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>;
175def : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>;
176def : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>;
177def : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>;
178
179def : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>;
180def : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>;
181def : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>;
182def : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>;
183def : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>;
184def : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>;
185def : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>;
186def : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>;
187def : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>;
188def : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>;
189
190def : LoadPatGlobalAddr<i32, sextloadi8, LOAD8_S_I32>;
191def : LoadPatGlobalAddr<i32, zextloadi8, LOAD8_U_I32>;
192def : LoadPatGlobalAddr<i32, sextloadi16, LOAD16_S_I32>;
193def : LoadPatGlobalAddr<i32, zextloadi8, LOAD16_U_I32>;
194
195def : LoadPatGlobalAddr<i64, sextloadi8, LOAD8_S_I64>;
196def : LoadPatGlobalAddr<i64, zextloadi8, LOAD8_U_I64>;
197def : LoadPatGlobalAddr<i64, sextloadi16, LOAD16_S_I64>;
198def : LoadPatGlobalAddr<i64, zextloadi16, LOAD16_U_I64>;
199def : LoadPatGlobalAddr<i64, sextloadi32, LOAD32_S_I64>;
200def : LoadPatGlobalAddr<i64, zextloadi32, LOAD32_U_I64>;
201
202def : LoadPatExternalSym<i32, sextloadi8, LOAD8_S_I32>;
203def : LoadPatExternalSym<i32, zextloadi8, LOAD8_U_I32>;
204def : LoadPatExternalSym<i32, sextloadi16, LOAD16_S_I32>;
205def : LoadPatExternalSym<i32, zextloadi16, LOAD16_U_I32>;
206def : LoadPatExternalSym<i64, sextloadi8, LOAD8_S_I64>;
207def : LoadPatExternalSym<i64, zextloadi8, LOAD8_U_I64>;
208def : LoadPatExternalSym<i64, sextloadi16, LOAD16_S_I64>;
209def : LoadPatExternalSym<i64, zextloadi16, LOAD16_U_I64>;
210def : LoadPatExternalSym<i64, sextloadi32, LOAD32_S_I64>;
211def : LoadPatExternalSym<i64, zextloadi32, LOAD32_U_I64>;
212
Dan Gohman4b9d7912015-12-15 22:01:29 +0000213
214// Select extending loads with just a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000215def : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>;
216def : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>;
217def : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>;
218def : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>;
219
220def : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>;
221def : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>;
222def : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>;
223def : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>;
224def : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>;
225def : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>;
226
227def : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>;
228def : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>;
229def : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>;
230def : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>;
231def : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>;
232def : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>;
233def : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>;
234def : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>;
235def : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>;
236def : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>;
237
238def : LoadPatExternSymOffOnly<i32, sextloadi8, LOAD8_S_I32>;
239def : LoadPatExternSymOffOnly<i32, zextloadi8, LOAD8_U_I32>;
240def : LoadPatExternSymOffOnly<i32, sextloadi16, LOAD16_S_I32>;
241def : LoadPatExternSymOffOnly<i32, zextloadi16, LOAD16_U_I32>;
242def : LoadPatExternSymOffOnly<i64, sextloadi8, LOAD8_S_I64>;
243def : LoadPatExternSymOffOnly<i64, zextloadi8, LOAD8_U_I64>;
244def : LoadPatExternSymOffOnly<i64, sextloadi16, LOAD16_S_I64>;
245def : LoadPatExternSymOffOnly<i64, zextloadi16, LOAD16_U_I64>;
246def : LoadPatExternSymOffOnly<i64, sextloadi32, LOAD32_S_I64>;
247def : LoadPatExternSymOffOnly<i64, zextloadi32, LOAD32_U_I64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000248
249// Resolve "don't care" extending loads to zero-extending loads. This is
250// somewhat arbitrary, but zero-extending is conceptually simpler.
251
252// Select "don't care" extending loads with no constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000253def : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>;
254def : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>;
255def : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>;
256def : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>;
257def : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>;
258
Dan Gohman4b9d7912015-12-15 22:01:29 +0000259// Select "don't care" extending loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000260def : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>;
261def : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>;
262def : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>;
263def : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>;
264def : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>;
265def : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>;
266def : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>;
267def : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>;
268def : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>;
269def : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>;
270def : LoadPatGlobalAddr<i32, extloadi8, LOAD8_U_I32>;
271def : LoadPatGlobalAddr<i32, extloadi16, LOAD16_U_I32>;
272def : LoadPatGlobalAddr<i64, extloadi8, LOAD8_U_I64>;
273def : LoadPatGlobalAddr<i64, extloadi16, LOAD16_U_I64>;
274def : LoadPatGlobalAddr<i64, extloadi32, LOAD32_U_I64>;
275def : LoadPatExternalSym<i32, extloadi8, LOAD8_U_I32>;
276def : LoadPatExternalSym<i32, extloadi16, LOAD16_U_I32>;
277def : LoadPatExternalSym<i64, extloadi8, LOAD8_U_I64>;
278def : LoadPatExternalSym<i64, extloadi16, LOAD16_U_I64>;
279def : LoadPatExternalSym<i64, extloadi32, LOAD32_U_I64>;
280
Dan Gohman4b9d7912015-12-15 22:01:29 +0000281// Select "don't care" extending loads with just a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000282def : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>;
283def : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>;
284def : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>;
285def : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>;
286def : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>;
287def : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>;
288def : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>;
289def : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>;
290def : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>;
291def : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>;
292def : LoadPatExternSymOffOnly<i32, extloadi8, LOAD8_U_I32>;
293def : LoadPatExternSymOffOnly<i32, extloadi16, LOAD16_U_I32>;
294def : LoadPatExternSymOffOnly<i64, extloadi8, LOAD8_U_I64>;
295def : LoadPatExternSymOffOnly<i64, extloadi16, LOAD16_U_I64>;
296def : LoadPatExternSymOffOnly<i64, extloadi32, LOAD32_U_I64>;
297
Derek Schuffa2726e92018-03-30 17:02:50 +0000298// Defines atomic and non-atomic stores, regular and truncating
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000299multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> {
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000300 let mayStore = 1 in
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000301 defm "" : I<(outs),
302 (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
303 (outs),
304 (ins P2Align:$p2align, offset32_op:$off), [],
305 !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000306 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000307}
JF Bastien73ff6af2015-08-31 22:24:11 +0000308// Basic store.
309// Note: WebAssembly inverts SelectionDAG's usual operand order.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000310defm STORE_I32 : WebAssemblyStore<I32, "i32.store", 0x36>;
311defm STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>;
312defm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>;
313defm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000314
Dan Gohman4b9d7912015-12-15 22:01:29 +0000315// Select stores with no constant offset.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000316class StorePatNoOffset<ValueType ty, PatFrag node, NI inst> :
Heejin Ahnd31bc982018-07-09 20:18:21 +0000317 Pat<(node ty:$val, I32:$addr), (inst 0, 0, I32:$addr, ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000318
319def : StorePatNoOffset<i32, store, STORE_I32>;
320def : StorePatNoOffset<i64, store, STORE_I64>;
321def : StorePatNoOffset<f32, store, STORE_F32>;
322def : StorePatNoOffset<f64, store, STORE_F64>;
Derek Schuff9d779522015-12-05 00:26:39 +0000323
Dan Gohman4b9d7912015-12-15 22:01:29 +0000324// Select stores with a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000325class StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
326 Pat<(kind ty:$val, (operand I32:$addr, imm:$off)),
327 (inst 0, imm:$off, I32:$addr, ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000328
329def : StorePatImmOff<i32, store, regPlusImm, STORE_I32>;
330def : StorePatImmOff<i64, store, regPlusImm, STORE_I64>;
331def : StorePatImmOff<f32, store, regPlusImm, STORE_F32>;
332def : StorePatImmOff<f64, store, regPlusImm, STORE_F64>;
333def : StorePatImmOff<i32, store, or_is_add, STORE_I32>;
334def : StorePatImmOff<i64, store, or_is_add, STORE_I64>;
335def : StorePatImmOff<f32, store, or_is_add, STORE_F32>;
336def : StorePatImmOff<f64, store, or_is_add, STORE_F64>;
337
Heejin Ahnd31bc982018-07-09 20:18:21 +0000338class StorePatGlobalAddr<ValueType ty, PatFrag kind, NI inst> :
339 Pat<(kind ty:$val,
340 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))),
Derek Schuffa2726e92018-03-30 17:02:50 +0000341 (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>;
342def : StorePatGlobalAddr<i32, store, STORE_I32>;
343def : StorePatGlobalAddr<i64, store, STORE_I64>;
344def : StorePatGlobalAddr<f32, store, STORE_F32>;
345def : StorePatGlobalAddr<f64, store, STORE_F64>;
346
Heejin Ahnd31bc982018-07-09 20:18:21 +0000347class StorePatExternalSym<ValueType ty, PatFrag kind, NI inst> :
348 Pat<(kind ty:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))),
Derek Schuffa2726e92018-03-30 17:02:50 +0000349 (inst 0, texternalsym:$off, I32:$addr, ty:$val)>;
350def : StorePatExternalSym<i32, store, STORE_I32>;
351def : StorePatExternalSym<i64, store, STORE_I64>;
352def : StorePatExternalSym<f32, store, STORE_F32>;
353def : StorePatExternalSym<f64, store, STORE_F64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000354
355// Select stores with just a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000356class StorePatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
357 Pat<(kind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000358def : StorePatOffsetOnly<i32, store, STORE_I32>;
359def : StorePatOffsetOnly<i64, store, STORE_I64>;
360def : StorePatOffsetOnly<f32, store, STORE_F32>;
361def : StorePatOffsetOnly<f64, store, STORE_F64>;
362
Heejin Ahnd31bc982018-07-09 20:18:21 +0000363class StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
364 Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)),
Derek Schuffa2726e92018-03-30 17:02:50 +0000365 (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>;
366def : StorePatGlobalAddrOffOnly<i32, store, STORE_I32>;
367def : StorePatGlobalAddrOffOnly<i64, store, STORE_I64>;
368def : StorePatGlobalAddrOffOnly<f32, store, STORE_F32>;
369def : StorePatGlobalAddrOffOnly<f64, store, STORE_F64>;
370
Heejin Ahnd31bc982018-07-09 20:18:21 +0000371class StorePatExternSymOffOnly<ValueType ty, PatFrag kind, NI inst> :
372 Pat<(kind ty:$val, (WebAssemblywrapper texternalsym:$off)),
Derek Schuffa2726e92018-03-30 17:02:50 +0000373 (inst 0, texternalsym:$off, (CONST_I32 0), ty:$val)>;
374def : StorePatExternSymOffOnly<i32, store, STORE_I32>;
375def : StorePatExternSymOffOnly<i64, store, STORE_I64>;
376def : StorePatExternSymOffOnly<f32, store, STORE_F32>;
377def : StorePatExternSymOffOnly<f64, store, STORE_F64>;
378
JF Bastien73ff6af2015-08-31 22:24:11 +0000379// Truncating store.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000380defm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
381defm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>;
382defm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>;
383defm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
384defm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000385
Dan Gohman4b9d7912015-12-15 22:01:29 +0000386// Select truncating stores with no constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000387def : StorePatNoOffset<i32, truncstorei8, STORE8_I32>;
388def : StorePatNoOffset<i32, truncstorei16, STORE16_I32>;
389def : StorePatNoOffset<i64, truncstorei8, STORE8_I64>;
390def : StorePatNoOffset<i64, truncstorei16, STORE16_I64>;
391def : StorePatNoOffset<i64, truncstorei32, STORE32_I64>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000392
Dan Gohman4b9d7912015-12-15 22:01:29 +0000393// Select truncating stores with a constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000394def : StorePatImmOff<i32, truncstorei8, regPlusImm, STORE8_I32>;
395def : StorePatImmOff<i32, truncstorei16, regPlusImm, STORE16_I32>;
396def : StorePatImmOff<i64, truncstorei8, regPlusImm, STORE8_I64>;
397def : StorePatImmOff<i64, truncstorei16, regPlusImm, STORE16_I64>;
398def : StorePatImmOff<i64, truncstorei32, regPlusImm, STORE32_I64>;
399def : StorePatImmOff<i32, truncstorei8, or_is_add, STORE8_I32>;
400def : StorePatImmOff<i32, truncstorei16, or_is_add, STORE16_I32>;
401def : StorePatImmOff<i64, truncstorei8, or_is_add, STORE8_I64>;
402def : StorePatImmOff<i64, truncstorei16, or_is_add, STORE16_I64>;
403def : StorePatImmOff<i64, truncstorei32, or_is_add, STORE32_I64>;
404
405def : StorePatGlobalAddr<i32, truncstorei8, STORE8_I32>;
406def : StorePatGlobalAddr<i32, truncstorei16, STORE16_I32>;
407def : StorePatGlobalAddr<i64, truncstorei8, STORE8_I64>;
408def : StorePatGlobalAddr<i64, truncstorei16, STORE16_I64>;
409def : StorePatGlobalAddr<i64, truncstorei32, STORE32_I64>;
410def : StorePatExternalSym<i32, truncstorei8, STORE8_I32>;
411def : StorePatExternalSym<i32, truncstorei16, STORE16_I32>;
412def : StorePatExternalSym<i64, truncstorei8, STORE8_I64>;
413def : StorePatExternalSym<i64, truncstorei16, STORE16_I64>;
414def : StorePatExternalSym<i64, truncstorei32, STORE32_I64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000415
416// Select truncating stores with just a constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000417def : StorePatOffsetOnly<i32, truncstorei8, STORE8_I32>;
418def : StorePatOffsetOnly<i32, truncstorei16, STORE16_I32>;
419def : StorePatOffsetOnly<i64, truncstorei8, STORE8_I64>;
420def : StorePatOffsetOnly<i64, truncstorei16, STORE16_I64>;
421def : StorePatOffsetOnly<i64, truncstorei32, STORE32_I64>;
422def : StorePatGlobalAddrOffOnly<i32, truncstorei8, STORE8_I32>;
423def : StorePatGlobalAddrOffOnly<i32, truncstorei16, STORE16_I32>;
424def : StorePatGlobalAddrOffOnly<i64, truncstorei8, STORE8_I64>;
425def : StorePatGlobalAddrOffOnly<i64, truncstorei16, STORE16_I64>;
426def : StorePatGlobalAddrOffOnly<i64, truncstorei32, STORE32_I64>;
427def : StorePatExternSymOffOnly<i32, truncstorei8, STORE8_I32>;
428def : StorePatExternSymOffOnly<i32, truncstorei16, STORE16_I32>;
429def : StorePatExternSymOffOnly<i64, truncstorei8, STORE8_I64>;
430def : StorePatExternSymOffOnly<i64, truncstorei16, STORE16_I64>;
431def : StorePatExternSymOffOnly<i64, truncstorei32, STORE32_I64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000432
Derek Schuff31680dd2016-05-02 17:25:22 +0000433// Current memory size.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000434defm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
435 (outs), (ins i32imm:$flags),
436 [(set I32:$dst,
437 (int_wasm_memory_size (i32 imm:$flags)))],
438 "memory.size\t$dst, $flags", "memory.size\t$flags",
439 0x3f>,
440 Requires<[HasAddr32]>;
441defm MEM_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
442 (outs), (ins i32imm:$flags),
443 [(set I32:$dst, (int_wasm_mem_size (i32 imm:$flags)))],
444 "mem.size\t$dst, $flags", "mem.size\t$flags", 0x3f>,
445 Requires<[HasAddr32]>;
446defm CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
447 (outs), (ins i32imm:$flags),
448 [],
449 "current_memory\t$dst",
450 "current_memory\t$flags", 0x3f>,
451 Requires<[HasAddr32]>;
Dan Gohmanbaba8c62015-10-02 20:10:26 +0000452
Dan Gohmand7ffb912015-11-05 20:16:59 +0000453// Grow memory.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000454defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000455 (outs), (ins i32imm:$flags),
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000456 [(set I32:$dst,
457 (int_wasm_memory_grow (i32 imm:$flags),
458 I32:$delta))],
459 "memory.grow\t$dst, $flags, $delta",
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000460 "memory.grow\t$flags", 0x40>,
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000461 Requires<[HasAddr32]>;
462defm MEM_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
463 (outs), (ins i32imm:$flags),
464 [(set I32:$dst,
465 (int_wasm_mem_grow (i32 imm:$flags), I32:$delta))],
466 "mem.grow\t$dst, $flags, $delta", "mem.grow\t$flags",
Heejin Ahn68432592018-08-22 00:33:34 +0000467 0x40>,
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000468 Requires<[HasAddr32]>;
469defm GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
470 (outs), (ins i32imm:$flags),
471 [],
472 "grow_memory\t$dst, $delta", "grow_memory\t$flags",
473 0x40>,
474 Requires<[HasAddr32]>;
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000475
Dan Gohmanf50d9642016-10-25 16:55:52 +0000476def : Pat<(int_wasm_current_memory),
477 (CURRENT_MEMORY_I32 0)>;
478def : Pat<(int_wasm_grow_memory I32:$delta),
479 (GROW_MEMORY_I32 0, $delta)>;