]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
MFV: r333077
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / WebAssembly / WebAssemblyInstrMemory.td
1 // 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
11 /// \brief WebAssembly Memory operand code-gen constructs.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 // TODO:
16 //  - HasAddr64
17 //  - WebAssemblyTargetLowering having to do with atomics
18 //  - Each has optional alignment.
19
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
24 // 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.
27 def regPlusImm : PatFrag<(ops node:$addr, node:$off),
28                          (add node:$addr, node:$off),
29                          [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
30
31 // Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
32 def 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
36   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;
41 }]>;
42
43 // GlobalAddresses are conceptually unsigned values, so we can also fold them
44 // 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.
47 def regPlusGA : PatFrag<(ops node:$addr, node:$off),
48                         (add node:$addr, node:$off),
49                         [{
50   return N->getFlags().hasNoUnsignedWrap();
51 }]>;
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
56 let Defs = [ARGUMENTS] in {
57
58 // Defines atomic and non-atomic loads, regular and extending.
59 class WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> :
60   I<(outs rc:$dst),
61     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
62     [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), Opcode>;
63
64 // Basic load.
65 // FIXME: When we can break syntax compatibility, reorder the fields in the
66 // asmstrings to match the binary encoding.
67 def LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>;
68 def LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>;
69 def LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>;
70 def LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>;
71
72 } // Defs = [ARGUMENTS]
73
74 // Select loads with no constant offset.
75 class LoadPatNoOffset<ValueType ty, PatFrag node, I inst> :
76   Pat<(ty (node I32:$addr)), (inst 0, 0, $addr)>;
77
78 def : LoadPatNoOffset<i32, load, LOAD_I32>;
79 def : LoadPatNoOffset<i64, load, LOAD_I64>;
80 def : LoadPatNoOffset<f32, load, LOAD_F32>;
81 def : LoadPatNoOffset<f64, load, LOAD_F64>;
82
83
84 // Select loads with a constant offset.
85
86 // Pattern with address + immediate offset
87 class LoadPatImmOff<ValueType ty, PatFrag loadkind, PatFrag operand, I inst> :
88   Pat<(ty (loadkind (operand I32:$addr, imm:$off))),
89       (inst 0, imm:$off, $addr)>;
90
91 def : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>;
92 def : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>;
93 def : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>;
94 def : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>;
95 def : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>;
96 def : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>;
97 def : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>;
98 def : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>;
99
100 class LoadPatGlobalAddr<ValueType ty, PatFrag loadkind, I inst> :
101   Pat<(ty (loadkind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))),
102       (inst 0, tglobaladdr:$off, $addr)>;
103
104 def : LoadPatGlobalAddr<i32, load, LOAD_I32>;
105 def : LoadPatGlobalAddr<i64, load, LOAD_I64>;
106 def : LoadPatGlobalAddr<f32, load, LOAD_F32>;
107 def : LoadPatGlobalAddr<f64, load, LOAD_F64>;
108
109 class LoadPatExternalSym<ValueType ty, PatFrag loadkind, I inst> :
110   Pat<(ty (loadkind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
111       (inst 0, texternalsym:$off, $addr)>;
112 def : LoadPatExternalSym<i32, load, LOAD_I32>;
113 def : LoadPatExternalSym<i64, load, LOAD_I64>;
114 def : LoadPatExternalSym<f32, load, LOAD_F32>;
115 def : LoadPatExternalSym<f64, load, LOAD_F64>;
116
117
118 // Select loads with just a constant offset.
119 class LoadPatOffsetOnly<ValueType ty, PatFrag loadkind, I inst> :
120   Pat<(ty (loadkind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>;
121
122 def : LoadPatOffsetOnly<i32, load, LOAD_I32>;
123 def : LoadPatOffsetOnly<i64, load, LOAD_I64>;
124 def : LoadPatOffsetOnly<f32, load, LOAD_F32>;
125 def : LoadPatOffsetOnly<f64, load, LOAD_F64>;
126
127 class LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag loadkind, I inst> :
128   Pat<(ty (loadkind (WebAssemblywrapper tglobaladdr:$off))),
129       (inst 0, tglobaladdr:$off, (CONST_I32 0))>;
130
131 def : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>;
132 def : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>;
133 def : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>;
134 def : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>;
135
136 class LoadPatExternSymOffOnly<ValueType ty, PatFrag loadkind, I inst> :
137   Pat<(ty (loadkind (WebAssemblywrapper texternalsym:$off))),
138       (inst 0, texternalsym:$off, (CONST_I32 0))>;
139 def : LoadPatExternSymOffOnly<i32, load, LOAD_I32>;
140 def : LoadPatExternSymOffOnly<i64, load, LOAD_I64>;
141 def : LoadPatExternSymOffOnly<f32, load, LOAD_F32>;
142 def : LoadPatExternSymOffOnly<f64, load, LOAD_F64>;
143
144 let Defs = [ARGUMENTS] in {
145
146 // Extending load.
147 def LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>;
148 def LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>;
149 def LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>;
150 def LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>;
151 def LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>;
152 def LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>;
153 def LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>;
154 def LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x32>;
155 def LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>;
156 def LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>;
157
158 } // Defs = [ARGUMENTS]
159
160 // Select extending loads with no constant offset.
161 def : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>;
162 def : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>;
163 def : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>;
164 def : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>;
165 def : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>;
166 def : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>;
167 def : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>;
168 def : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>;
169 def : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>;
170 def : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>;
171
172 // Select extending loads with a constant offset.
173 def : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>;
174 def : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>;
175 def : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>;
176 def : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>;
177 def : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>;
178 def : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>;
179 def : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>;
180 def : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>;
181 def : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>;
182 def : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>;
183
184 def : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>;
185 def : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>;
186 def : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>;
187 def : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>;
188 def : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>;
189 def : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>;
190 def : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>;
191 def : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>;
192 def : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>;
193 def : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>;
194
195 def : LoadPatGlobalAddr<i32, sextloadi8, LOAD8_S_I32>;
196 def : LoadPatGlobalAddr<i32, zextloadi8, LOAD8_U_I32>;
197 def : LoadPatGlobalAddr<i32, sextloadi16, LOAD16_S_I32>;
198 def : LoadPatGlobalAddr<i32, zextloadi8, LOAD16_U_I32>;
199
200 def : LoadPatGlobalAddr<i64, sextloadi8, LOAD8_S_I64>;
201 def : LoadPatGlobalAddr<i64, zextloadi8, LOAD8_U_I64>;
202 def : LoadPatGlobalAddr<i64, sextloadi16, LOAD16_S_I64>;
203 def : LoadPatGlobalAddr<i64, zextloadi16, LOAD16_U_I64>;
204 def : LoadPatGlobalAddr<i64, sextloadi32, LOAD32_S_I64>;
205 def : LoadPatGlobalAddr<i64, zextloadi32, LOAD32_U_I64>;
206
207 def : LoadPatExternalSym<i32, sextloadi8, LOAD8_S_I32>;
208 def : LoadPatExternalSym<i32, zextloadi8, LOAD8_U_I32>;
209 def : LoadPatExternalSym<i32, sextloadi16, LOAD16_S_I32>;
210 def : LoadPatExternalSym<i32, zextloadi16, LOAD16_U_I32>;
211 def : LoadPatExternalSym<i64, sextloadi8, LOAD8_S_I64>;
212 def : LoadPatExternalSym<i64, zextloadi8, LOAD8_U_I64>;
213 def : LoadPatExternalSym<i64, sextloadi16, LOAD16_S_I64>;
214 def : LoadPatExternalSym<i64, zextloadi16, LOAD16_U_I64>;
215 def : LoadPatExternalSym<i64, sextloadi32, LOAD32_S_I64>;
216 def : LoadPatExternalSym<i64, zextloadi32, LOAD32_U_I64>;
217
218
219 // Select extending loads with just a constant offset.
220 def : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>;
221 def : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>;
222 def : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>;
223 def : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>;
224
225 def : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>;
226 def : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>;
227 def : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>;
228 def : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>;
229 def : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>;
230 def : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>;
231
232 def : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>;
233 def : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>;
234 def : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>;
235 def : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>;
236 def : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>;
237 def : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>;
238 def : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>;
239 def : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>;
240 def : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>;
241 def : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>;
242
243 def : LoadPatExternSymOffOnly<i32, sextloadi8, LOAD8_S_I32>;
244 def : LoadPatExternSymOffOnly<i32, zextloadi8, LOAD8_U_I32>;
245 def : LoadPatExternSymOffOnly<i32, sextloadi16, LOAD16_S_I32>;
246 def : LoadPatExternSymOffOnly<i32, zextloadi16, LOAD16_U_I32>;
247 def : LoadPatExternSymOffOnly<i64, sextloadi8, LOAD8_S_I64>;
248 def : LoadPatExternSymOffOnly<i64, zextloadi8, LOAD8_U_I64>;
249 def : LoadPatExternSymOffOnly<i64, sextloadi16, LOAD16_S_I64>;
250 def : LoadPatExternSymOffOnly<i64, zextloadi16, LOAD16_U_I64>;
251 def : LoadPatExternSymOffOnly<i64, sextloadi32, LOAD32_S_I64>;
252 def : LoadPatExternSymOffOnly<i64, zextloadi32, LOAD32_U_I64>;
253
254 // Resolve "don't care" extending loads to zero-extending loads. This is
255 // somewhat arbitrary, but zero-extending is conceptually simpler.
256
257 // Select "don't care" extending loads with no constant offset.
258 def : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>;
259 def : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>;
260 def : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>;
261 def : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>;
262 def : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>;
263
264 // Select "don't care" extending loads with a constant offset.
265 def : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>;
266 def : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>;
267 def : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>;
268 def : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>;
269 def : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>;
270 def : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>;
271 def : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>;
272 def : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>;
273 def : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>;
274 def : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>;
275 def : LoadPatGlobalAddr<i32, extloadi8, LOAD8_U_I32>;
276 def : LoadPatGlobalAddr<i32, extloadi16, LOAD16_U_I32>;
277 def : LoadPatGlobalAddr<i64, extloadi8, LOAD8_U_I64>;
278 def : LoadPatGlobalAddr<i64, extloadi16, LOAD16_U_I64>;
279 def : LoadPatGlobalAddr<i64, extloadi32, LOAD32_U_I64>;
280 def : LoadPatExternalSym<i32, extloadi8, LOAD8_U_I32>;
281 def : LoadPatExternalSym<i32, extloadi16, LOAD16_U_I32>;
282 def : LoadPatExternalSym<i64, extloadi8, LOAD8_U_I64>;
283 def : LoadPatExternalSym<i64, extloadi16, LOAD16_U_I64>;
284 def : LoadPatExternalSym<i64, extloadi32, LOAD32_U_I64>;
285
286 // Select "don't care" extending loads with just a constant offset.
287 def : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>;
288 def : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>;
289 def : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>;
290 def : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>;
291 def : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>;
292 def : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>;
293 def : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>;
294 def : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>;
295 def : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>;
296 def : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>;
297 def : LoadPatExternSymOffOnly<i32, extloadi8, LOAD8_U_I32>;
298 def : LoadPatExternSymOffOnly<i32, extloadi16, LOAD16_U_I32>;
299 def : LoadPatExternSymOffOnly<i64, extloadi8, LOAD8_U_I64>;
300 def : LoadPatExternSymOffOnly<i64, extloadi16, LOAD16_U_I64>;
301 def : LoadPatExternSymOffOnly<i64, extloadi32, LOAD32_U_I64>;
302
303
304 let Defs = [ARGUMENTS] in {
305
306 // Basic store.
307 // Note: WebAssembly inverts SelectionDAG's usual operand order.
308 def STORE_I32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
309                             I32:$val), [],
310                    "i32.store\t${off}(${addr})${p2align}, $val", 0x36>;
311 def STORE_I64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
312                             I64:$val), [],
313                    "i64.store\t${off}(${addr})${p2align}, $val", 0x37>;
314 def STORE_F32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
315                             F32:$val), [],
316                    "f32.store\t${off}(${addr})${p2align}, $val", 0x38>;
317 def STORE_F64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
318                             F64:$val), [],
319                    "f64.store\t${off}(${addr})${p2align}, $val", 0x39>;
320
321 } // Defs = [ARGUMENTS]
322
323 // Select stores with no constant offset.
324 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, 0, I32:$addr, I32:$val)>;
325 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, 0, I32:$addr, I64:$val)>;
326 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, 0, I32:$addr, F32:$val)>;
327 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, 0, I32:$addr, F64:$val)>;
328
329 // Select stores with a constant offset.
330 def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)),
331           (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
332 def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)),
333           (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
334 def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)),
335           (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
336 def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)),
337           (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
338 def : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)),
339           (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
340 def : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)),
341           (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
342 def : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)),
343           (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
344 def : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)),
345           (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
346 def : Pat<(store I32:$val, (regPlusGA I32:$addr,
347                                       (WebAssemblywrapper tglobaladdr:$off))),
348           (STORE_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
349 def : Pat<(store I64:$val, (regPlusGA I32:$addr,
350                                       (WebAssemblywrapper tglobaladdr:$off))),
351           (STORE_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
352 def : Pat<(store F32:$val, (regPlusGA I32:$addr,
353                                       (WebAssemblywrapper tglobaladdr:$off))),
354           (STORE_F32 0, tglobaladdr:$off, I32:$addr, F32:$val)>;
355 def : Pat<(store F64:$val, (regPlusGA I32:$addr,
356                                       (WebAssemblywrapper tglobaladdr:$off))),
357           (STORE_F64 0, tglobaladdr:$off, I32:$addr, F64:$val)>;
358 def : Pat<(store I32:$val, (add I32:$addr,
359                                 (WebAssemblywrapper texternalsym:$off))),
360           (STORE_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
361 def : Pat<(store I64:$val, (add I32:$addr,
362                                 (WebAssemblywrapper texternalsym:$off))),
363           (STORE_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
364 def : Pat<(store F32:$val, (add I32:$addr,
365                                 (WebAssemblywrapper texternalsym:$off))),
366           (STORE_F32 0, texternalsym:$off, I32:$addr, F32:$val)>;
367 def : Pat<(store F64:$val, (add I32:$addr,
368                                 (WebAssemblywrapper texternalsym:$off))),
369           (STORE_F64 0, texternalsym:$off, I32:$addr, F64:$val)>;
370
371 // Select stores with just a constant offset.
372 def : Pat<(store I32:$val, imm:$off),
373           (STORE_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
374 def : Pat<(store I64:$val, imm:$off),
375           (STORE_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
376 def : Pat<(store F32:$val, imm:$off),
377           (STORE_F32 0, imm:$off, (CONST_I32 0), F32:$val)>;
378 def : Pat<(store F64:$val, imm:$off),
379           (STORE_F64 0, imm:$off, (CONST_I32 0), F64:$val)>;
380 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
381           (STORE_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
382 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
383           (STORE_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
384 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
385           (STORE_F32 0, tglobaladdr:$off, (CONST_I32 0), F32:$val)>;
386 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
387           (STORE_F64 0, tglobaladdr:$off, (CONST_I32 0), F64:$val)>;
388 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
389           (STORE_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
390 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
391           (STORE_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
392 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
393           (STORE_F32 0, texternalsym:$off, (CONST_I32 0), F32:$val)>;
394 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
395           (STORE_F64 0, texternalsym:$off, (CONST_I32 0), F64:$val)>;
396
397 let Defs = [ARGUMENTS] in {
398
399 // Truncating store.
400 def STORE8_I32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
401                              I32:$val), [],
402                     "i32.store8\t${off}(${addr})${p2align}, $val", 0x3a>;
403 def STORE16_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
404                              I32:$val), [],
405                     "i32.store16\t${off}(${addr})${p2align}, $val", 0x3b>;
406 def STORE8_I64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
407                              I64:$val), [],
408                     "i64.store8\t${off}(${addr})${p2align}, $val", 0x3c>;
409 def STORE16_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
410                              I64:$val), [],
411                     "i64.store16\t${off}(${addr})${p2align}, $val", 0x3d>;
412 def STORE32_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
413                              I64:$val), [],
414                     "i64.store32\t${off}(${addr})${p2align}, $val", 0x3e>;
415
416 } // Defs = [ARGUMENTS]
417
418 // Select truncating stores with no constant offset.
419 def : Pat<(truncstorei8 I32:$val, I32:$addr),
420           (STORE8_I32 0, 0, I32:$addr, I32:$val)>;
421 def : Pat<(truncstorei16 I32:$val, I32:$addr),
422           (STORE16_I32 0, 0, I32:$addr, I32:$val)>;
423 def : Pat<(truncstorei8 I64:$val, I32:$addr),
424           (STORE8_I64 0, 0, I32:$addr, I64:$val)>;
425 def : Pat<(truncstorei16 I64:$val, I32:$addr),
426           (STORE16_I64 0, 0, I32:$addr, I64:$val)>;
427 def : Pat<(truncstorei32 I64:$val, I32:$addr),
428           (STORE32_I64 0, 0, I32:$addr, I64:$val)>;
429
430 // Select truncating stores with a constant offset.
431 def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)),
432           (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
433 def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)),
434           (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
435 def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)),
436           (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
437 def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)),
438           (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
439 def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)),
440           (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
441 def : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)),
442           (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
443 def : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)),
444           (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
445 def : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)),
446           (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
447 def : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)),
448           (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
449 def : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)),
450           (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
451 def : Pat<(truncstorei8 I32:$val,
452                         (regPlusGA I32:$addr,
453                                    (WebAssemblywrapper tglobaladdr:$off))),
454           (STORE8_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
455 def : Pat<(truncstorei16 I32:$val,
456                          (regPlusGA I32:$addr,
457                                     (WebAssemblywrapper tglobaladdr:$off))),
458           (STORE16_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
459 def : Pat<(truncstorei8 I64:$val,
460                         (regPlusGA I32:$addr,
461                                    (WebAssemblywrapper tglobaladdr:$off))),
462           (STORE8_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
463 def : Pat<(truncstorei16 I64:$val,
464                          (regPlusGA I32:$addr,
465                                     (WebAssemblywrapper tglobaladdr:$off))),
466           (STORE16_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
467 def : Pat<(truncstorei32 I64:$val,
468                          (regPlusGA I32:$addr,
469                                     (WebAssemblywrapper tglobaladdr:$off))),
470           (STORE32_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
471 def : Pat<(truncstorei8 I32:$val, (add I32:$addr,
472                                        (WebAssemblywrapper texternalsym:$off))),
473           (STORE8_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
474 def : Pat<(truncstorei16 I32:$val,
475                          (add I32:$addr,
476                               (WebAssemblywrapper texternalsym:$off))),
477           (STORE16_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
478 def : Pat<(truncstorei8 I64:$val,
479                         (add I32:$addr,
480                              (WebAssemblywrapper texternalsym:$off))),
481           (STORE8_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
482 def : Pat<(truncstorei16 I64:$val,
483                          (add I32:$addr,
484                               (WebAssemblywrapper texternalsym:$off))),
485           (STORE16_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
486 def : Pat<(truncstorei32 I64:$val,
487                          (add I32:$addr,
488                               (WebAssemblywrapper texternalsym:$off))),
489           (STORE32_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
490
491 // Select truncating stores with just a constant offset.
492 def : Pat<(truncstorei8 I32:$val, imm:$off),
493           (STORE8_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
494 def : Pat<(truncstorei16 I32:$val, imm:$off),
495           (STORE16_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
496 def : Pat<(truncstorei8 I64:$val, imm:$off),
497           (STORE8_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
498 def : Pat<(truncstorei16 I64:$val, imm:$off),
499           (STORE16_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
500 def : Pat<(truncstorei32 I64:$val, imm:$off),
501           (STORE32_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
502 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
503           (STORE8_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
504 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
505           (STORE16_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
506 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
507           (STORE8_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
508 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
509           (STORE16_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
510 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
511           (STORE32_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
512 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
513           (STORE8_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
514 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
515           (STORE16_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
516 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
517           (STORE8_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
518 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
519           (STORE16_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
520 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
521           (STORE32_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
522
523 let Defs = [ARGUMENTS] in {
524
525 // Current memory size.
526 def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
527                            [],
528                            "current_memory\t$dst", 0x3f>,
529                          Requires<[HasAddr32]>;
530
531 // Grow memory.
532 def GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
533                         [],
534                         "grow_memory\t$dst, $delta", 0x40>,
535                       Requires<[HasAddr32]>;
536
537 } // Defs = [ARGUMENTS]
538
539 def : Pat<(int_wasm_current_memory),
540           (CURRENT_MEMORY_I32 0)>;
541 def : Pat<(int_wasm_grow_memory I32:$delta),
542           (GROW_MEMORY_I32 0, $delta)>;