1 // WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief WebAssembly Memory operand code-gen constructs.
13 //===----------------------------------------------------------------------===//
17 // - WebAssemblyTargetLowering having to do with atomics
18 // - Each has optional alignment.
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.
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(); }]>;
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());
36 APInt KnownZero0, KnownOne0;
37 CurDAG->computeKnownBits(N->getOperand(0), KnownZero0, KnownOne0, 0);
38 APInt KnownZero1, KnownOne1;
39 CurDAG->computeKnownBits(N->getOperand(1), KnownZero1, KnownOne1, 0);
40 return (~KnownZero0 & ~KnownZero1) == 0;
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),
50 return N->getFlags()->hasNoUnsignedWrap();
53 // We don't need a regPlusES because external symbols never have constant
54 // offsets folded into them, so we can just use add.
56 let Defs = [ARGUMENTS] in {
59 // FIXME: When we can break syntax compatibility, reorder the fields in the
60 // asmstrings to match the binary encoding.
61 def LOAD_I32 : I<(outs I32:$dst),
62 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
63 [], "i32.load\t$dst, ${off}(${addr})${p2align}", 0x28>;
64 def LOAD_I64 : I<(outs I64:$dst),
65 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
66 [], "i64.load\t$dst, ${off}(${addr})${p2align}", 0x29>;
67 def LOAD_F32 : I<(outs F32:$dst),
68 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
69 [], "f32.load\t$dst, ${off}(${addr})${p2align}", 0x2a>;
70 def LOAD_F64 : I<(outs F64:$dst),
71 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
72 [], "f64.load\t$dst, ${off}(${addr})${p2align}", 0x2b>;
74 } // Defs = [ARGUMENTS]
76 // Select loads with no constant offset.
77 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, 0, $addr)>;
78 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, 0, $addr)>;
79 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, 0, $addr)>;
80 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, 0, $addr)>;
82 // Select loads with a constant offset.
83 def : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))),
84 (LOAD_I32 0, imm:$off, $addr)>;
85 def : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))),
86 (LOAD_I64 0, imm:$off, $addr)>;
87 def : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))),
88 (LOAD_F32 0, imm:$off, $addr)>;
89 def : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))),
90 (LOAD_F64 0, imm:$off, $addr)>;
91 def : Pat<(i32 (load (or_is_add I32:$addr, imm:$off))),
92 (LOAD_I32 0, imm:$off, $addr)>;
93 def : Pat<(i64 (load (or_is_add I32:$addr, imm:$off))),
94 (LOAD_I64 0, imm:$off, $addr)>;
95 def : Pat<(f32 (load (or_is_add I32:$addr, imm:$off))),
96 (LOAD_F32 0, imm:$off, $addr)>;
97 def : Pat<(f64 (load (or_is_add I32:$addr, imm:$off))),
98 (LOAD_F64 0, imm:$off, $addr)>;
99 def : Pat<(i32 (load (regPlusGA I32:$addr,
100 (WebAssemblywrapper tglobaladdr:$off)))),
101 (LOAD_I32 0, tglobaladdr:$off, $addr)>;
102 def : Pat<(i64 (load (regPlusGA I32:$addr,
103 (WebAssemblywrapper tglobaladdr:$off)))),
104 (LOAD_I64 0, tglobaladdr:$off, $addr)>;
105 def : Pat<(f32 (load (regPlusGA I32:$addr,
106 (WebAssemblywrapper tglobaladdr:$off)))),
107 (LOAD_F32 0, tglobaladdr:$off, $addr)>;
108 def : Pat<(f64 (load (regPlusGA I32:$addr,
109 (WebAssemblywrapper tglobaladdr:$off)))),
110 (LOAD_F64 0, tglobaladdr:$off, $addr)>;
111 def : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
112 (LOAD_I32 0, texternalsym:$off, $addr)>;
113 def : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
114 (LOAD_I64 0, texternalsym:$off, $addr)>;
115 def : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
116 (LOAD_F32 0, texternalsym:$off, $addr)>;
117 def : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
118 (LOAD_F64 0, texternalsym:$off, $addr)>;
120 // Select loads with just a constant offset.
121 def : Pat<(i32 (load imm:$off)), (LOAD_I32 0, imm:$off, (CONST_I32 0))>;
122 def : Pat<(i64 (load imm:$off)), (LOAD_I64 0, imm:$off, (CONST_I32 0))>;
123 def : Pat<(f32 (load imm:$off)), (LOAD_F32 0, imm:$off, (CONST_I32 0))>;
124 def : Pat<(f64 (load imm:$off)), (LOAD_F64 0, imm:$off, (CONST_I32 0))>;
125 def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
126 (LOAD_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
127 def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
128 (LOAD_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
129 def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
130 (LOAD_F32 0, tglobaladdr:$off, (CONST_I32 0))>;
131 def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
132 (LOAD_F64 0, tglobaladdr:$off, (CONST_I32 0))>;
133 def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
134 (LOAD_I32 0, texternalsym:$off, (CONST_I32 0))>;
135 def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
136 (LOAD_I64 0, texternalsym:$off, (CONST_I32 0))>;
137 def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
138 (LOAD_F32 0, texternalsym:$off, (CONST_I32 0))>;
139 def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
140 (LOAD_F64 0, texternalsym:$off, (CONST_I32 0))>;
142 let Defs = [ARGUMENTS] in {
145 def LOAD8_S_I32 : I<(outs I32:$dst),
146 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
147 [], "i32.load8_s\t$dst, ${off}(${addr})${p2align}", 0x2c>;
148 def LOAD8_U_I32 : I<(outs I32:$dst),
149 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
150 [], "i32.load8_u\t$dst, ${off}(${addr})${p2align}", 0x2d>;
151 def LOAD16_S_I32 : I<(outs I32:$dst),
152 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
153 [], "i32.load16_s\t$dst, ${off}(${addr})${p2align}", 0x2e>;
154 def LOAD16_U_I32 : I<(outs I32:$dst),
155 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
156 [], "i32.load16_u\t$dst, ${off}(${addr})${p2align}", 0x2f>;
157 def LOAD8_S_I64 : I<(outs I64:$dst),
158 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
159 [], "i64.load8_s\t$dst, ${off}(${addr})${p2align}", 0x30>;
160 def LOAD8_U_I64 : I<(outs I64:$dst),
161 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
162 [], "i64.load8_u\t$dst, ${off}(${addr})${p2align}", 0x31>;
163 def LOAD16_S_I64 : I<(outs I64:$dst),
164 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
165 [], "i64.load16_s\t$dst, ${off}(${addr})${p2align}", 0x32>;
166 def LOAD16_U_I64 : I<(outs I64:$dst),
167 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
168 [], "i64.load16_u\t$dst, ${off}(${addr})${p2align}", 0x33>;
169 def LOAD32_S_I64 : I<(outs I64:$dst),
170 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
171 [], "i64.load32_s\t$dst, ${off}(${addr})${p2align}", 0x34>;
172 def LOAD32_U_I64 : I<(outs I64:$dst),
173 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
174 [], "i64.load32_u\t$dst, ${off}(${addr})${p2align}", 0x35>;
176 } // Defs = [ARGUMENTS]
178 // Select extending loads with no constant offset.
179 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, 0, $addr)>;
180 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, 0, $addr)>;
181 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, 0, $addr)>;
182 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, 0, $addr)>;
183 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, 0, $addr)>;
184 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, 0, $addr)>;
185 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, 0, $addr)>;
186 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, 0, $addr)>;
187 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, 0, $addr)>;
188 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, 0, $addr)>;
190 // Select extending loads with a constant offset.
191 def : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
192 (LOAD8_S_I32 0, imm:$off, $addr)>;
193 def : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
194 (LOAD8_U_I32 0, imm:$off, $addr)>;
195 def : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
196 (LOAD16_S_I32 0, imm:$off, $addr)>;
197 def : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
198 (LOAD16_U_I32 0, imm:$off, $addr)>;
199 def : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
200 (LOAD8_S_I64 0, imm:$off, $addr)>;
201 def : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
202 (LOAD8_U_I64 0, imm:$off, $addr)>;
203 def : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
204 (LOAD16_S_I64 0, imm:$off, $addr)>;
205 def : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
206 (LOAD16_U_I64 0, imm:$off, $addr)>;
207 def : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))),
208 (LOAD32_S_I64 0, imm:$off, $addr)>;
209 def : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))),
210 (LOAD32_U_I64 0, imm:$off, $addr)>;
211 def : Pat<(i32 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
212 (LOAD8_S_I32 0, imm:$off, $addr)>;
213 def : Pat<(i32 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
214 (LOAD8_U_I32 0, imm:$off, $addr)>;
215 def : Pat<(i32 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
216 (LOAD16_S_I32 0, imm:$off, $addr)>;
217 def : Pat<(i32 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
218 (LOAD16_U_I32 0, imm:$off, $addr)>;
219 def : Pat<(i64 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
220 (LOAD8_S_I64 0, imm:$off, $addr)>;
221 def : Pat<(i64 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
222 (LOAD8_U_I64 0, imm:$off, $addr)>;
223 def : Pat<(i64 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
224 (LOAD16_S_I64 0, imm:$off, $addr)>;
225 def : Pat<(i64 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
226 (LOAD16_U_I64 0, imm:$off, $addr)>;
227 def : Pat<(i64 (sextloadi32 (or_is_add I32:$addr, imm:$off))),
228 (LOAD32_S_I64 0, imm:$off, $addr)>;
229 def : Pat<(i64 (zextloadi32 (or_is_add I32:$addr, imm:$off))),
230 (LOAD32_U_I64 0, imm:$off, $addr)>;
231 def : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr,
232 (WebAssemblywrapper tglobaladdr:$off)))),
233 (LOAD8_S_I32 0, tglobaladdr:$off, $addr)>;
234 def : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr,
235 (WebAssemblywrapper tglobaladdr:$off)))),
236 (LOAD8_U_I32 0, tglobaladdr:$off, $addr)>;
237 def : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr,
238 (WebAssemblywrapper tglobaladdr:$off)))),
239 (LOAD16_S_I32 0, tglobaladdr:$off, $addr)>;
240 def : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr,
241 (WebAssemblywrapper tglobaladdr:$off)))),
242 (LOAD16_U_I32 0, tglobaladdr:$off, $addr)>;
243 def : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr,
244 (WebAssemblywrapper tglobaladdr:$off)))),
245 (LOAD8_S_I64 0, tglobaladdr:$off, $addr)>;
246 def : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr,
247 (WebAssemblywrapper tglobaladdr:$off)))),
248 (LOAD8_U_I64 0, tglobaladdr:$off, $addr)>;
249 def : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr,
250 (WebAssemblywrapper tglobaladdr:$off)))),
251 (LOAD16_S_I64 0, tglobaladdr:$off, $addr)>;
252 def : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr,
253 (WebAssemblywrapper tglobaladdr:$off)))),
254 (LOAD16_U_I64 0, tglobaladdr:$off, $addr)>;
255 def : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr,
256 (WebAssemblywrapper tglobaladdr:$off)))),
257 (LOAD32_S_I64 0, tglobaladdr:$off, $addr)>;
258 def : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr,
259 (WebAssemblywrapper tglobaladdr:$off)))),
260 (LOAD32_U_I64 0, tglobaladdr:$off, $addr)>;
261 def : Pat<(i32 (sextloadi8 (add I32:$addr,
262 (WebAssemblywrapper texternalsym:$off)))),
263 (LOAD8_S_I32 0, texternalsym:$off, $addr)>;
264 def : Pat<(i32 (zextloadi8 (add I32:$addr,
265 (WebAssemblywrapper texternalsym:$off)))),
266 (LOAD8_U_I32 0, texternalsym:$off, $addr)>;
267 def : Pat<(i32 (sextloadi16 (add I32:$addr,
268 (WebAssemblywrapper texternalsym:$off)))),
269 (LOAD16_S_I32 0, texternalsym:$off, $addr)>;
270 def : Pat<(i32 (zextloadi16 (add I32:$addr,
271 (WebAssemblywrapper texternalsym:$off)))),
272 (LOAD16_U_I32 0, texternalsym:$off, $addr)>;
273 def : Pat<(i64 (sextloadi8 (add I32:$addr,
274 (WebAssemblywrapper texternalsym:$off)))),
275 (LOAD8_S_I64 0, texternalsym:$off, $addr)>;
276 def : Pat<(i64 (zextloadi8 (add I32:$addr,
277 (WebAssemblywrapper texternalsym:$off)))),
278 (LOAD8_U_I64 0, texternalsym:$off, $addr)>;
279 def : Pat<(i64 (sextloadi16 (add I32:$addr,
280 (WebAssemblywrapper texternalsym:$off)))),
281 (LOAD16_S_I64 0, texternalsym:$off, $addr)>;
282 def : Pat<(i64 (zextloadi16 (add I32:$addr,
283 (WebAssemblywrapper texternalsym:$off)))),
284 (LOAD16_U_I64 0, texternalsym:$off, $addr)>;
285 def : Pat<(i64 (sextloadi32 (add I32:$addr,
286 (WebAssemblywrapper texternalsym:$off)))),
287 (LOAD32_S_I64 0, texternalsym:$off, $addr)>;
288 def : Pat<(i64 (zextloadi32 (add I32:$addr,
289 (WebAssemblywrapper texternalsym:$off)))),
290 (LOAD32_U_I64 0, texternalsym:$off, $addr)>;
292 // Select extending loads with just a constant offset.
293 def : Pat<(i32 (sextloadi8 imm:$off)),
294 (LOAD8_S_I32 0, imm:$off, (CONST_I32 0))>;
295 def : Pat<(i32 (zextloadi8 imm:$off)),
296 (LOAD8_U_I32 0, imm:$off, (CONST_I32 0))>;
297 def : Pat<(i32 (sextloadi16 imm:$off)),
298 (LOAD16_S_I32 0, imm:$off, (CONST_I32 0))>;
299 def : Pat<(i32 (zextloadi16 imm:$off)),
300 (LOAD16_U_I32 0, imm:$off, (CONST_I32 0))>;
301 def : Pat<(i64 (sextloadi8 imm:$off)),
302 (LOAD8_S_I64 0, imm:$off, (CONST_I32 0))>;
303 def : Pat<(i64 (zextloadi8 imm:$off)),
304 (LOAD8_U_I64 0, imm:$off, (CONST_I32 0))>;
305 def : Pat<(i64 (sextloadi16 imm:$off)),
306 (LOAD16_S_I64 0, imm:$off, (CONST_I32 0))>;
307 def : Pat<(i64 (zextloadi16 imm:$off)),
308 (LOAD16_U_I64 0, imm:$off, (CONST_I32 0))>;
309 def : Pat<(i64 (sextloadi32 imm:$off)),
310 (LOAD32_S_I64 0, imm:$off, (CONST_I32 0))>;
311 def : Pat<(i64 (zextloadi32 imm:$off)),
312 (LOAD32_U_I64 0, imm:$off, (CONST_I32 0))>;
313 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
314 (LOAD8_S_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
315 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
316 (LOAD8_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
317 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
318 (LOAD16_S_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
319 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
320 (LOAD16_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
321 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
322 (LOAD8_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
323 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
324 (LOAD8_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
325 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
326 (LOAD16_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
327 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
328 (LOAD16_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
329 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
330 (LOAD32_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
331 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
332 (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
333 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
334 (LOAD8_S_I32 0, texternalsym:$off, (CONST_I32 0))>;
335 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
336 (LOAD8_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
337 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
338 (LOAD16_S_I32 0, texternalsym:$off, (CONST_I32 0))>;
339 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
340 (LOAD16_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
341 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
342 (LOAD8_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
343 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
344 (LOAD8_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
345 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
346 (LOAD16_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
347 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
348 (LOAD16_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
349 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
350 (LOAD32_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
351 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
352 (LOAD32_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
354 // Resolve "don't care" extending loads to zero-extending loads. This is
355 // somewhat arbitrary, but zero-extending is conceptually simpler.
357 // Select "don't care" extending loads with no constant offset.
358 def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, 0, $addr)>;
359 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, 0, $addr)>;
360 def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, 0, $addr)>;
361 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, 0, $addr)>;
362 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, 0, $addr)>;
364 // Select "don't care" extending loads with a constant offset.
365 def : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
366 (LOAD8_U_I32 0, imm:$off, $addr)>;
367 def : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
368 (LOAD16_U_I32 0, imm:$off, $addr)>;
369 def : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
370 (LOAD8_U_I64 0, imm:$off, $addr)>;
371 def : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
372 (LOAD16_U_I64 0, imm:$off, $addr)>;
373 def : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))),
374 (LOAD32_U_I64 0, imm:$off, $addr)>;
375 def : Pat<(i32 (extloadi8 (or_is_add I32:$addr, imm:$off))),
376 (LOAD8_U_I32 0, imm:$off, $addr)>;
377 def : Pat<(i32 (extloadi16 (or_is_add I32:$addr, imm:$off))),
378 (LOAD16_U_I32 0, imm:$off, $addr)>;
379 def : Pat<(i64 (extloadi8 (or_is_add I32:$addr, imm:$off))),
380 (LOAD8_U_I64 0, imm:$off, $addr)>;
381 def : Pat<(i64 (extloadi16 (or_is_add I32:$addr, imm:$off))),
382 (LOAD16_U_I64 0, imm:$off, $addr)>;
383 def : Pat<(i64 (extloadi32 (or_is_add I32:$addr, imm:$off))),
384 (LOAD32_U_I64 0, imm:$off, $addr)>;
385 def : Pat<(i32 (extloadi8 (regPlusGA I32:$addr,
386 (WebAssemblywrapper tglobaladdr:$off)))),
387 (LOAD8_U_I32 0, tglobaladdr:$off, $addr)>;
388 def : Pat<(i32 (extloadi16 (regPlusGA I32:$addr,
389 (WebAssemblywrapper tglobaladdr:$off)))),
390 (LOAD16_U_I32 0, tglobaladdr:$off, $addr)>;
391 def : Pat<(i64 (extloadi8 (regPlusGA I32:$addr,
392 (WebAssemblywrapper tglobaladdr:$off)))),
393 (LOAD8_U_I64 0, tglobaladdr:$off, $addr)>;
394 def : Pat<(i64 (extloadi16 (regPlusGA I32:$addr,
395 (WebAssemblywrapper tglobaladdr:$off)))),
396 (LOAD16_U_I64 0, tglobaladdr:$off, $addr)>;
397 def : Pat<(i64 (extloadi32 (regPlusGA I32:$addr,
398 (WebAssemblywrapper tglobaladdr:$off)))),
399 (LOAD32_U_I64 0, tglobaladdr:$off, $addr)>;
400 def : Pat<(i32 (extloadi8 (add I32:$addr,
401 (WebAssemblywrapper texternalsym:$off)))),
402 (LOAD8_U_I32 0, texternalsym:$off, $addr)>;
403 def : Pat<(i32 (extloadi16 (add I32:$addr,
404 (WebAssemblywrapper texternalsym:$off)))),
405 (LOAD16_U_I32 0, texternalsym:$off, $addr)>;
406 def : Pat<(i64 (extloadi8 (add I32:$addr,
407 (WebAssemblywrapper texternalsym:$off)))),
408 (LOAD8_U_I64 0, texternalsym:$off, $addr)>;
409 def : Pat<(i64 (extloadi16 (add I32:$addr,
410 (WebAssemblywrapper texternalsym:$off)))),
411 (LOAD16_U_I64 0, texternalsym:$off, $addr)>;
412 def : Pat<(i64 (extloadi32 (add I32:$addr,
413 (WebAssemblywrapper texternalsym:$off)))),
414 (LOAD32_U_I64 0, texternalsym:$off, $addr)>;
416 // Select "don't care" extending loads with just a constant offset.
417 def : Pat<(i32 (extloadi8 imm:$off)),
418 (LOAD8_U_I32 0, imm:$off, (CONST_I32 0))>;
419 def : Pat<(i32 (extloadi16 imm:$off)),
420 (LOAD16_U_I32 0, imm:$off, (CONST_I32 0))>;
421 def : Pat<(i64 (extloadi8 imm:$off)),
422 (LOAD8_U_I64 0, imm:$off, (CONST_I32 0))>;
423 def : Pat<(i64 (extloadi16 imm:$off)),
424 (LOAD16_U_I64 0, imm:$off, (CONST_I32 0))>;
425 def : Pat<(i64 (extloadi32 imm:$off)),
426 (LOAD32_U_I64 0, imm:$off, (CONST_I32 0))>;
427 def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
428 (LOAD8_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
429 def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
430 (LOAD16_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
431 def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
432 (LOAD8_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
433 def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
434 (LOAD16_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
435 def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
436 (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
437 def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
438 (LOAD8_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
439 def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
440 (LOAD16_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
441 def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
442 (LOAD8_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
443 def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
444 (LOAD16_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
445 def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
446 (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
448 let Defs = [ARGUMENTS] in {
451 // Note: WebAssembly inverts SelectionDAG's usual operand order.
452 def STORE_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
454 "i32.store\t${off}(${addr})${p2align}, $val", 0x36>;
455 def STORE_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
457 "i64.store\t${off}(${addr})${p2align}, $val", 0x37>;
458 def STORE_F32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
460 "f32.store\t${off}(${addr})${p2align}, $val", 0x38>;
461 def STORE_F64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
463 "f64.store\t${off}(${addr})${p2align}, $val", 0x39>;
465 } // Defs = [ARGUMENTS]
467 // Select stores with no constant offset.
468 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, 0, I32:$addr, I32:$val)>;
469 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, 0, I32:$addr, I64:$val)>;
470 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, 0, I32:$addr, F32:$val)>;
471 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, 0, I32:$addr, F64:$val)>;
473 // Select stores with a constant offset.
474 def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)),
475 (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
476 def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)),
477 (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
478 def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)),
479 (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
480 def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)),
481 (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
482 def : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)),
483 (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
484 def : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)),
485 (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
486 def : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)),
487 (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
488 def : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)),
489 (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
490 def : Pat<(store I32:$val, (regPlusGA I32:$addr,
491 (WebAssemblywrapper tglobaladdr:$off))),
492 (STORE_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
493 def : Pat<(store I64:$val, (regPlusGA I32:$addr,
494 (WebAssemblywrapper tglobaladdr:$off))),
495 (STORE_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
496 def : Pat<(store F32:$val, (regPlusGA I32:$addr,
497 (WebAssemblywrapper tglobaladdr:$off))),
498 (STORE_F32 0, tglobaladdr:$off, I32:$addr, F32:$val)>;
499 def : Pat<(store F64:$val, (regPlusGA I32:$addr,
500 (WebAssemblywrapper tglobaladdr:$off))),
501 (STORE_F64 0, tglobaladdr:$off, I32:$addr, F64:$val)>;
502 def : Pat<(store I32:$val, (add I32:$addr,
503 (WebAssemblywrapper texternalsym:$off))),
504 (STORE_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
505 def : Pat<(store I64:$val, (add I32:$addr,
506 (WebAssemblywrapper texternalsym:$off))),
507 (STORE_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
508 def : Pat<(store F32:$val, (add I32:$addr,
509 (WebAssemblywrapper texternalsym:$off))),
510 (STORE_F32 0, texternalsym:$off, I32:$addr, F32:$val)>;
511 def : Pat<(store F64:$val, (add I32:$addr,
512 (WebAssemblywrapper texternalsym:$off))),
513 (STORE_F64 0, texternalsym:$off, I32:$addr, F64:$val)>;
515 // Select stores with just a constant offset.
516 def : Pat<(store I32:$val, imm:$off),
517 (STORE_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
518 def : Pat<(store I64:$val, imm:$off),
519 (STORE_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
520 def : Pat<(store F32:$val, imm:$off),
521 (STORE_F32 0, imm:$off, (CONST_I32 0), F32:$val)>;
522 def : Pat<(store F64:$val, imm:$off),
523 (STORE_F64 0, imm:$off, (CONST_I32 0), F64:$val)>;
524 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
525 (STORE_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
526 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
527 (STORE_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
528 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
529 (STORE_F32 0, tglobaladdr:$off, (CONST_I32 0), F32:$val)>;
530 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
531 (STORE_F64 0, tglobaladdr:$off, (CONST_I32 0), F64:$val)>;
532 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
533 (STORE_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
534 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
535 (STORE_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
536 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
537 (STORE_F32 0, texternalsym:$off, (CONST_I32 0), F32:$val)>;
538 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
539 (STORE_F64 0, texternalsym:$off, (CONST_I32 0), F64:$val)>;
541 let Defs = [ARGUMENTS] in {
544 def STORE8_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
546 "i32.store8\t${off}(${addr})${p2align}, $val", 0x3a>;
547 def STORE16_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
549 "i32.store16\t${off}(${addr})${p2align}, $val", 0x3b>;
550 def STORE8_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
552 "i64.store8\t${off}(${addr})${p2align}, $val", 0x3c>;
553 def STORE16_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
555 "i64.store16\t${off}(${addr})${p2align}, $val", 0x3d>;
556 def STORE32_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
558 "i64.store32\t${off}(${addr})${p2align}, $val", 0x3e>;
560 } // Defs = [ARGUMENTS]
562 // Select truncating stores with no constant offset.
563 def : Pat<(truncstorei8 I32:$val, I32:$addr),
564 (STORE8_I32 0, 0, I32:$addr, I32:$val)>;
565 def : Pat<(truncstorei16 I32:$val, I32:$addr),
566 (STORE16_I32 0, 0, I32:$addr, I32:$val)>;
567 def : Pat<(truncstorei8 I64:$val, I32:$addr),
568 (STORE8_I64 0, 0, I32:$addr, I64:$val)>;
569 def : Pat<(truncstorei16 I64:$val, I32:$addr),
570 (STORE16_I64 0, 0, I32:$addr, I64:$val)>;
571 def : Pat<(truncstorei32 I64:$val, I32:$addr),
572 (STORE32_I64 0, 0, I32:$addr, I64:$val)>;
574 // Select truncating stores with a constant offset.
575 def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)),
576 (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
577 def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)),
578 (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
579 def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)),
580 (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
581 def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)),
582 (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
583 def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)),
584 (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
585 def : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)),
586 (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
587 def : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)),
588 (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
589 def : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)),
590 (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
591 def : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)),
592 (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
593 def : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)),
594 (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
595 def : Pat<(truncstorei8 I32:$val,
596 (regPlusGA I32:$addr,
597 (WebAssemblywrapper tglobaladdr:$off))),
598 (STORE8_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
599 def : Pat<(truncstorei16 I32:$val,
600 (regPlusGA I32:$addr,
601 (WebAssemblywrapper tglobaladdr:$off))),
602 (STORE16_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
603 def : Pat<(truncstorei8 I64:$val,
604 (regPlusGA I32:$addr,
605 (WebAssemblywrapper tglobaladdr:$off))),
606 (STORE8_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
607 def : Pat<(truncstorei16 I64:$val,
608 (regPlusGA I32:$addr,
609 (WebAssemblywrapper tglobaladdr:$off))),
610 (STORE16_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
611 def : Pat<(truncstorei32 I64:$val,
612 (regPlusGA I32:$addr,
613 (WebAssemblywrapper tglobaladdr:$off))),
614 (STORE32_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
615 def : Pat<(truncstorei8 I32:$val, (add I32:$addr,
616 (WebAssemblywrapper texternalsym:$off))),
617 (STORE8_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
618 def : Pat<(truncstorei16 I32:$val,
620 (WebAssemblywrapper texternalsym:$off))),
621 (STORE16_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
622 def : Pat<(truncstorei8 I64:$val,
624 (WebAssemblywrapper texternalsym:$off))),
625 (STORE8_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
626 def : Pat<(truncstorei16 I64:$val,
628 (WebAssemblywrapper texternalsym:$off))),
629 (STORE16_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
630 def : Pat<(truncstorei32 I64:$val,
632 (WebAssemblywrapper texternalsym:$off))),
633 (STORE32_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
635 // Select truncating stores with just a constant offset.
636 def : Pat<(truncstorei8 I32:$val, imm:$off),
637 (STORE8_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
638 def : Pat<(truncstorei16 I32:$val, imm:$off),
639 (STORE16_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
640 def : Pat<(truncstorei8 I64:$val, imm:$off),
641 (STORE8_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
642 def : Pat<(truncstorei16 I64:$val, imm:$off),
643 (STORE16_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
644 def : Pat<(truncstorei32 I64:$val, imm:$off),
645 (STORE32_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
646 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
647 (STORE8_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
648 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
649 (STORE16_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
650 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
651 (STORE8_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
652 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
653 (STORE16_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
654 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
655 (STORE32_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
656 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
657 (STORE8_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
658 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
659 (STORE16_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
660 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
661 (STORE8_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
662 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
663 (STORE16_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
664 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
665 (STORE32_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
667 let Defs = [ARGUMENTS] in {
669 // Current memory size.
670 def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
672 "current_memory\t$dst", 0x3f>,
673 Requires<[HasAddr32]>;
676 def GROW_MEMORY_I32 : I<(outs), (ins i32imm:$flags, I32:$delta),
678 "grow_memory\t$delta", 0x40>,
679 Requires<[HasAddr32]>;
681 } // Defs = [ARGUMENTS]
683 def : Pat<(int_wasm_current_memory),
684 (CURRENT_MEMORY_I32 0)>;
685 def : Pat<(int_wasm_grow_memory I32:$delta),
686 (GROW_MEMORY_I32 0, $delta)>;