blob: 6916b165f9709f096d1d8eb94727cfcc65d7af9f [file] [log] [blame]
JF Bastien5ca0bac2015-07-10 18:23:10 +00001// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
JF Bastien5ca0bac2015-07-10 18:23:10 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// WebAssembly Memory operand code-gen constructs.
JF Bastien5ca0bac2015-07-10 18:23:10 +000011///
12//===----------------------------------------------------------------------===//
13
Dan Gohman9c54d3b2015-11-25 18:13:18 +000014// TODO:
JF Bastien73ff6af2015-08-31 22:24:11 +000015// - HasAddr64
JF Bastien73ff6af2015-08-31 22:24:11 +000016// - WebAssemblyTargetLowering having to do with atomics
Dan Gohman4b9d7912015-12-15 22:01:29 +000017// - Each has optional alignment.
JF Bastien73ff6af2015-08-31 22:24:11 +000018
19// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
20// local types. These memory-only types instead zero- or sign-extend into local
21// types when loading, and truncate when storing.
22
Dan Gohman4b9d7912015-12-15 22:01:29 +000023// WebAssembly constant offsets are performed as unsigned with infinite
24// precision, so we need to check for NoUnsignedWrap so that we don't fold an
25// offset for an add that needs wrapping.
Dan Gohmanf225a632016-01-11 22:05:44 +000026def regPlusImm : PatFrag<(ops node:$addr, node:$off),
Dan Gohman4b9d7912015-12-15 22:01:29 +000027 (add node:$addr, node:$off),
Derek Schuff2fa36042017-05-01 16:49:39 +000028 [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
Dan Gohman4b9d7912015-12-15 22:01:29 +000029
Dan Gohman3b09d272016-02-22 20:04:02 +000030// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
31def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
32 if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
33 return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
34
Simon Pilgrimca8bca22018-12-21 15:25:37 +000035 KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
36 KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
Craig Topper053cf4d2017-04-28 08:15:33 +000037 return (~Known0.Zero & ~Known1.Zero) == 0;
Dan Gohman3b09d272016-02-22 20:04:02 +000038}]>;
39
Dan Gohmanf225a632016-01-11 22:05:44 +000040// GlobalAddresses are conceptually unsigned values, so we can also fold them
Derek Schuff1b258d32016-08-31 20:27:20 +000041// into immediate values as long as the add is 'nuw'.
42// TODO: We'd like to also match GA offsets but there are cases where the
43// register can have a negative value. Find out what more we can do.
Dan Gohmanf225a632016-01-11 22:05:44 +000044def regPlusGA : PatFrag<(ops node:$addr, node:$off),
45 (add node:$addr, node:$off),
46 [{
Derek Schuff2fa36042017-05-01 16:49:39 +000047 return N->getFlags().hasNoUnsignedWrap();
Dan Gohmanf225a632016-01-11 22:05:44 +000048}]>;
49
50// We don't need a regPlusES because external symbols never have constant
51// offsets folded into them, so we can just use add.
52
Derek Schuff885dc592017-10-05 21:18:42 +000053// Defines atomic and non-atomic loads, regular and extending.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000054multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> {
Thomas Lively972d7d52019-03-09 04:31:37 +000055 let mayLoad = 1, UseNamedOperandTable = 1 in
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000056 defm "": I<(outs rc:$dst),
57 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
58 (outs), (ins P2Align:$p2align, offset32_op:$off),
59 [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +000060 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000061}
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000062
JF Bastien73ff6af2015-08-31 22:24:11 +000063// Basic load.
Dan Gohman48abaa92016-10-25 00:17:11 +000064// FIXME: When we can break syntax compatibility, reorder the fields in the
65// asmstrings to match the binary encoding.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +000066defm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>;
67defm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>;
68defm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>;
69defm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>;
JF Bastien73ff6af2015-08-31 22:24:11 +000070
Dan Gohman4b9d7912015-12-15 22:01:29 +000071// Select loads with no constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +000072class LoadPatNoOffset<ValueType ty, PatFrag kind, NI inst> :
73 Pat<(ty (kind I32:$addr)), (inst 0, 0, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000074
75def : LoadPatNoOffset<i32, load, LOAD_I32>;
76def : LoadPatNoOffset<i64, load, LOAD_I64>;
77def : LoadPatNoOffset<f32, load, LOAD_F32>;
78def : LoadPatNoOffset<f64, load, LOAD_F64>;
79
Dan Gohman4b9d7912015-12-15 22:01:29 +000080
81// Select loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000082
83// Pattern with address + immediate offset
Heejin Ahnd31bc982018-07-09 20:18:21 +000084class LoadPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
85 Pat<(ty (kind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, I32:$addr)>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000086
87def : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>;
88def : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>;
89def : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>;
90def : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>;
91def : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>;
92def : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>;
93def : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>;
94def : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>;
95
Heejin Ahnd31bc982018-07-09 20:18:21 +000096class LoadPatGlobalAddr<ValueType ty, PatFrag kind, NI inst> :
97 Pat<(ty (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))),
Sam Clegg492f7522019-03-26 19:46:15 +000098 (inst 0, tglobaladdr:$off, I32:$addr)>, Requires<[IsNotPIC]>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +000099
100def : LoadPatGlobalAddr<i32, load, LOAD_I32>;
101def : LoadPatGlobalAddr<i64, load, LOAD_I64>;
102def : LoadPatGlobalAddr<f32, load, LOAD_F32>;
103def : LoadPatGlobalAddr<f64, load, LOAD_F64>;
104
Dan Gohman4b9d7912015-12-15 22:01:29 +0000105// Select loads with just a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000106class LoadPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
107 Pat<(ty (kind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000108
109def : LoadPatOffsetOnly<i32, load, LOAD_I32>;
110def : LoadPatOffsetOnly<i64, load, LOAD_I64>;
111def : LoadPatOffsetOnly<f32, load, LOAD_F32>;
112def : LoadPatOffsetOnly<f64, load, LOAD_F64>;
113
Heejin Ahnd31bc982018-07-09 20:18:21 +0000114class LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
115 Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))),
Sam Clegg492f7522019-03-26 19:46:15 +0000116 (inst 0, tglobaladdr:$off, (CONST_I32 0))>, Requires<[IsNotPIC]>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000117
118def : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>;
119def : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>;
120def : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>;
121def : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>;
122
JF Bastien73ff6af2015-08-31 22:24:11 +0000123// Extending load.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000124defm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>;
125defm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>;
126defm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>;
127defm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>;
128defm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>;
129defm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>;
130defm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>;
131defm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>;
132defm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>;
133defm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000134
Derek Schuff9d779522015-12-05 00:26:39 +0000135// Select extending loads with no constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000136def : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>;
137def : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>;
138def : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>;
139def : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>;
140def : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>;
141def : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>;
142def : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>;
143def : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>;
144def : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>;
145def : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>;
Derek Schuff9d779522015-12-05 00:26:39 +0000146
Dan Gohman4b9d7912015-12-15 22:01:29 +0000147// Select extending loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000148def : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>;
149def : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>;
150def : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>;
151def : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>;
152def : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>;
153def : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>;
154def : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>;
155def : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>;
156def : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>;
157def : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>;
158
159def : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>;
160def : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>;
161def : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>;
162def : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>;
163def : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>;
164def : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>;
165def : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>;
166def : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>;
167def : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>;
168def : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>;
169
170def : LoadPatGlobalAddr<i32, sextloadi8, LOAD8_S_I32>;
171def : LoadPatGlobalAddr<i32, zextloadi8, LOAD8_U_I32>;
172def : LoadPatGlobalAddr<i32, sextloadi16, LOAD16_S_I32>;
173def : LoadPatGlobalAddr<i32, zextloadi8, LOAD16_U_I32>;
174
175def : LoadPatGlobalAddr<i64, sextloadi8, LOAD8_S_I64>;
176def : LoadPatGlobalAddr<i64, zextloadi8, LOAD8_U_I64>;
177def : LoadPatGlobalAddr<i64, sextloadi16, LOAD16_S_I64>;
178def : LoadPatGlobalAddr<i64, zextloadi16, LOAD16_U_I64>;
179def : LoadPatGlobalAddr<i64, sextloadi32, LOAD32_S_I64>;
180def : LoadPatGlobalAddr<i64, zextloadi32, LOAD32_U_I64>;
181
Dan Gohman4b9d7912015-12-15 22:01:29 +0000182// Select extending loads with just a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000183def : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>;
184def : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>;
185def : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>;
186def : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>;
187
188def : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>;
189def : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>;
190def : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>;
191def : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>;
192def : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>;
193def : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>;
194
195def : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>;
196def : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>;
197def : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>;
198def : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>;
199def : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>;
200def : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>;
201def : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>;
202def : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>;
203def : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>;
204def : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>;
205
Dan Gohman4b9d7912015-12-15 22:01:29 +0000206// Resolve "don't care" extending loads to zero-extending loads. This is
207// somewhat arbitrary, but zero-extending is conceptually simpler.
208
209// Select "don't care" extending loads with no constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000210def : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>;
211def : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>;
212def : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>;
213def : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>;
214def : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>;
215
Dan Gohman4b9d7912015-12-15 22:01:29 +0000216// Select "don't care" extending loads with a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000217def : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>;
218def : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>;
219def : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>;
220def : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>;
221def : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>;
222def : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>;
223def : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>;
224def : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>;
225def : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>;
226def : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>;
227def : LoadPatGlobalAddr<i32, extloadi8, LOAD8_U_I32>;
228def : LoadPatGlobalAddr<i32, extloadi16, LOAD16_U_I32>;
229def : LoadPatGlobalAddr<i64, extloadi8, LOAD8_U_I64>;
230def : LoadPatGlobalAddr<i64, extloadi16, LOAD16_U_I64>;
231def : LoadPatGlobalAddr<i64, extloadi32, LOAD32_U_I64>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000232
Dan Gohman4b9d7912015-12-15 22:01:29 +0000233// Select "don't care" extending loads with just a constant offset.
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000234def : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>;
235def : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>;
236def : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>;
237def : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>;
238def : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>;
239def : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>;
240def : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>;
241def : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>;
242def : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>;
243def : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>;
Derek Schuff0f3bc0f2017-08-31 21:51:48 +0000244
Derek Schuffa2726e92018-03-30 17:02:50 +0000245// Defines atomic and non-atomic stores, regular and truncating
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000246multiclass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> {
Thomas Lively972d7d52019-03-09 04:31:37 +0000247 let mayStore = 1, UseNamedOperandTable = 1 in
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000248 defm "" : I<(outs),
249 (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
250 (outs),
251 (ins P2Align:$p2align, offset32_op:$off), [],
252 !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000253 !strconcat(Name, "\t${off}${p2align}"), Opcode>;
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000254}
JF Bastien73ff6af2015-08-31 22:24:11 +0000255// Basic store.
256// Note: WebAssembly inverts SelectionDAG's usual operand order.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000257defm STORE_I32 : WebAssemblyStore<I32, "i32.store", 0x36>;
258defm STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>;
259defm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>;
260defm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000261
Dan Gohman4b9d7912015-12-15 22:01:29 +0000262// Select stores with no constant offset.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000263class StorePatNoOffset<ValueType ty, PatFrag node, NI inst> :
Heejin Ahnd31bc982018-07-09 20:18:21 +0000264 Pat<(node ty:$val, I32:$addr), (inst 0, 0, I32:$addr, ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000265
266def : StorePatNoOffset<i32, store, STORE_I32>;
267def : StorePatNoOffset<i64, store, STORE_I64>;
268def : StorePatNoOffset<f32, store, STORE_F32>;
269def : StorePatNoOffset<f64, store, STORE_F64>;
Derek Schuff9d779522015-12-05 00:26:39 +0000270
Dan Gohman4b9d7912015-12-15 22:01:29 +0000271// Select stores with a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000272class StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
273 Pat<(kind ty:$val, (operand I32:$addr, imm:$off)),
274 (inst 0, imm:$off, I32:$addr, ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000275
276def : StorePatImmOff<i32, store, regPlusImm, STORE_I32>;
277def : StorePatImmOff<i64, store, regPlusImm, STORE_I64>;
278def : StorePatImmOff<f32, store, regPlusImm, STORE_F32>;
279def : StorePatImmOff<f64, store, regPlusImm, STORE_F64>;
280def : StorePatImmOff<i32, store, or_is_add, STORE_I32>;
281def : StorePatImmOff<i64, store, or_is_add, STORE_I64>;
282def : StorePatImmOff<f32, store, or_is_add, STORE_F32>;
283def : StorePatImmOff<f64, store, or_is_add, STORE_F64>;
284
Heejin Ahnd31bc982018-07-09 20:18:21 +0000285class StorePatGlobalAddr<ValueType ty, PatFrag kind, NI inst> :
286 Pat<(kind ty:$val,
287 (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))),
Sam Clegg492f7522019-03-26 19:46:15 +0000288 (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>, Requires<[IsNotPIC]>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000289def : StorePatGlobalAddr<i32, store, STORE_I32>;
290def : StorePatGlobalAddr<i64, store, STORE_I64>;
291def : StorePatGlobalAddr<f32, store, STORE_F32>;
292def : StorePatGlobalAddr<f64, store, STORE_F64>;
293
Dan Gohman4b9d7912015-12-15 22:01:29 +0000294// Select stores with just a constant offset.
Heejin Ahnd31bc982018-07-09 20:18:21 +0000295class StorePatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
296 Pat<(kind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000297def : StorePatOffsetOnly<i32, store, STORE_I32>;
298def : StorePatOffsetOnly<i64, store, STORE_I64>;
299def : StorePatOffsetOnly<f32, store, STORE_F32>;
300def : StorePatOffsetOnly<f64, store, STORE_F64>;
301
Heejin Ahnd31bc982018-07-09 20:18:21 +0000302class StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
303 Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)),
Sam Clegg492f7522019-03-26 19:46:15 +0000304 (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>, Requires<[IsNotPIC]>;
Derek Schuffa2726e92018-03-30 17:02:50 +0000305def : StorePatGlobalAddrOffOnly<i32, store, STORE_I32>;
306def : StorePatGlobalAddrOffOnly<i64, store, STORE_I64>;
307def : StorePatGlobalAddrOffOnly<f32, store, STORE_F32>;
308def : StorePatGlobalAddrOffOnly<f64, store, STORE_F64>;
309
JF Bastien73ff6af2015-08-31 22:24:11 +0000310// Truncating store.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000311defm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
312defm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>;
313defm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>;
314defm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
315defm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000316
Dan Gohman4b9d7912015-12-15 22:01:29 +0000317// Select truncating stores with no constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000318def : StorePatNoOffset<i32, truncstorei8, STORE8_I32>;
319def : StorePatNoOffset<i32, truncstorei16, STORE16_I32>;
320def : StorePatNoOffset<i64, truncstorei8, STORE8_I64>;
321def : StorePatNoOffset<i64, truncstorei16, STORE16_I64>;
322def : StorePatNoOffset<i64, truncstorei32, STORE32_I64>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000323
Dan Gohman4b9d7912015-12-15 22:01:29 +0000324// Select truncating stores with a constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000325def : StorePatImmOff<i32, truncstorei8, regPlusImm, STORE8_I32>;
326def : StorePatImmOff<i32, truncstorei16, regPlusImm, STORE16_I32>;
327def : StorePatImmOff<i64, truncstorei8, regPlusImm, STORE8_I64>;
328def : StorePatImmOff<i64, truncstorei16, regPlusImm, STORE16_I64>;
329def : StorePatImmOff<i64, truncstorei32, regPlusImm, STORE32_I64>;
330def : StorePatImmOff<i32, truncstorei8, or_is_add, STORE8_I32>;
331def : StorePatImmOff<i32, truncstorei16, or_is_add, STORE16_I32>;
332def : StorePatImmOff<i64, truncstorei8, or_is_add, STORE8_I64>;
333def : StorePatImmOff<i64, truncstorei16, or_is_add, STORE16_I64>;
334def : StorePatImmOff<i64, truncstorei32, or_is_add, STORE32_I64>;
335
336def : StorePatGlobalAddr<i32, truncstorei8, STORE8_I32>;
337def : StorePatGlobalAddr<i32, truncstorei16, STORE16_I32>;
338def : StorePatGlobalAddr<i64, truncstorei8, STORE8_I64>;
339def : StorePatGlobalAddr<i64, truncstorei16, STORE16_I64>;
340def : StorePatGlobalAddr<i64, truncstorei32, STORE32_I64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000341
342// Select truncating stores with just a constant offset.
Derek Schuffa2726e92018-03-30 17:02:50 +0000343def : StorePatOffsetOnly<i32, truncstorei8, STORE8_I32>;
344def : StorePatOffsetOnly<i32, truncstorei16, STORE16_I32>;
345def : StorePatOffsetOnly<i64, truncstorei8, STORE8_I64>;
346def : StorePatOffsetOnly<i64, truncstorei16, STORE16_I64>;
347def : StorePatOffsetOnly<i64, truncstorei32, STORE32_I64>;
348def : StorePatGlobalAddrOffOnly<i32, truncstorei8, STORE8_I32>;
349def : StorePatGlobalAddrOffOnly<i32, truncstorei16, STORE16_I32>;
350def : StorePatGlobalAddrOffOnly<i64, truncstorei8, STORE8_I64>;
351def : StorePatGlobalAddrOffOnly<i64, truncstorei16, STORE16_I64>;
352def : StorePatGlobalAddrOffOnly<i64, truncstorei32, STORE32_I64>;
Dan Gohman4b9d7912015-12-15 22:01:29 +0000353
Derek Schuff31680dd2016-05-02 17:25:22 +0000354// Current memory size.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000355defm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
356 (outs), (ins i32imm:$flags),
357 [(set I32:$dst,
358 (int_wasm_memory_size (i32 imm:$flags)))],
359 "memory.size\t$dst, $flags", "memory.size\t$flags",
360 0x3f>,
361 Requires<[HasAddr32]>;
Dan Gohmanbaba8c62015-10-02 20:10:26 +0000362
Dan Gohmand7ffb912015-11-05 20:16:59 +0000363// Grow memory.
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000364defm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000365 (outs), (ins i32imm:$flags),
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000366 [(set I32:$dst,
367 (int_wasm_memory_grow (i32 imm:$flags),
368 I32:$delta))],
369 "memory.grow\t$dst, $flags, $delta",
Wouter van Oortmerssen8a9cb242018-08-27 15:45:51 +0000370 "memory.grow\t$flags", 0x40>,
Wouter van Oortmerssen48dac312018-06-18 21:22:44 +0000371 Requires<[HasAddr32]>;