]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td
Update compiler-rt to 3.9.0 release, and update the build glue for
[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   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;
41 }]>;
42
43 // GlobalAddresses are conceptually unsigned values, so we can also fold them
44 // into immediate values as long as their offsets are non-negative.
45 def regPlusGA : PatFrag<(ops node:$addr, node:$off),
46                         (add node:$addr, node:$off),
47                         [{
48   return N->getFlags()->hasNoUnsignedWrap() ||
49          (N->getOperand(1)->getOpcode() == WebAssemblyISD::Wrapper &&
50           isa<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0)) &&
51           cast<GlobalAddressSDNode>(N->getOperand(1)->getOperand(0))
52              ->getOffset() >= 0);
53 }]>;
54
55 // We don't need a regPlusES because external symbols never have constant
56 // offsets folded into them, so we can just use add.
57
58 let Defs = [ARGUMENTS] in {
59
60 // Basic load.
61 def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
62                                    P2Align:$p2align), [],
63                  "i32.load\t$dst, ${off}(${addr})${p2align}">;
64 def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
65                                    P2Align:$p2align), [],
66                  "i64.load\t$dst, ${off}(${addr})${p2align}">;
67 def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr,
68                                    P2Align:$p2align), [],
69                  "f32.load\t$dst, ${off}(${addr})${p2align}">;
70 def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr,
71                                    P2Align:$p2align), [],
72                  "f64.load\t$dst, ${off}(${addr})${p2align}">;
73
74 } // Defs = [ARGUMENTS]
75
76 // Select loads with no constant offset.
77 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr, 0)>;
78 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr, 0)>;
79 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr, 0)>;
80 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr, 0)>;
81
82 // Select loads with a constant offset.
83 def : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))),
84           (LOAD_I32 imm:$off, $addr, 0)>;
85 def : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))),
86           (LOAD_I64 imm:$off, $addr, 0)>;
87 def : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))),
88           (LOAD_F32 imm:$off, $addr, 0)>;
89 def : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))),
90           (LOAD_F64 imm:$off, $addr, 0)>;
91 def : Pat<(i32 (load (or_is_add I32:$addr, imm:$off))),
92           (LOAD_I32 imm:$off, $addr, 0)>;
93 def : Pat<(i64 (load (or_is_add I32:$addr, imm:$off))),
94           (LOAD_I64 imm:$off, $addr, 0)>;
95 def : Pat<(f32 (load (or_is_add I32:$addr, imm:$off))),
96           (LOAD_F32 imm:$off, $addr, 0)>;
97 def : Pat<(f64 (load (or_is_add I32:$addr, imm:$off))),
98           (LOAD_F64 imm:$off, $addr, 0)>;
99 def : Pat<(i32 (load (regPlusGA I32:$addr,
100                                 (WebAssemblywrapper tglobaladdr:$off)))),
101           (LOAD_I32 tglobaladdr:$off, $addr, 0)>;
102 def : Pat<(i64 (load (regPlusGA I32:$addr,
103                                 (WebAssemblywrapper tglobaladdr:$off)))),
104           (LOAD_I64 tglobaladdr:$off, $addr, 0)>;
105 def : Pat<(f32 (load (regPlusGA I32:$addr,
106                                 (WebAssemblywrapper tglobaladdr:$off)))),
107           (LOAD_F32 tglobaladdr:$off, $addr, 0)>;
108 def : Pat<(f64 (load (regPlusGA I32:$addr,
109                                 (WebAssemblywrapper tglobaladdr:$off)))),
110           (LOAD_F64 tglobaladdr:$off, $addr, 0)>;
111 def : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
112           (LOAD_I32 texternalsym:$off, $addr, 0)>;
113 def : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
114           (LOAD_I64 texternalsym:$off, $addr, 0)>;
115 def : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
116           (LOAD_F32 texternalsym:$off, $addr, 0)>;
117 def : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
118           (LOAD_F64 texternalsym:$off, $addr, 0)>;
119
120 // Select loads with just a constant offset.
121 def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0), 0)>;
122 def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0), 0)>;
123 def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0), 0)>;
124 def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0), 0)>;
125 def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
126           (LOAD_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
127 def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
128           (LOAD_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
129 def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
130           (LOAD_F32 tglobaladdr:$off, (CONST_I32 0), 0)>;
131 def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
132           (LOAD_F64 tglobaladdr:$off, (CONST_I32 0), 0)>;
133 def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
134           (LOAD_I32 texternalsym:$off, (CONST_I32 0), 0)>;
135 def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
136           (LOAD_I64 texternalsym:$off, (CONST_I32 0), 0)>;
137 def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
138           (LOAD_F32 texternalsym:$off, (CONST_I32 0), 0)>;
139 def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
140           (LOAD_F64 texternalsym:$off, (CONST_I32 0), 0)>;
141
142 let Defs = [ARGUMENTS] in {
143
144 // Extending load.
145 def LOAD8_S_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
146                                        P2Align:$p2align), [],
147                      "i32.load8_s\t$dst, ${off}(${addr})${p2align}">;
148 def LOAD8_U_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
149                                        P2Align:$p2align), [],
150                      "i32.load8_u\t$dst, ${off}(${addr})${p2align}">;
151 def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
152                                        P2Align:$p2align), [],
153                      "i32.load16_s\t$dst, ${off}(${addr})${p2align}">;
154 def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
155                                        P2Align:$p2align), [],
156                      "i32.load16_u\t$dst, ${off}(${addr})${p2align}">;
157 def LOAD8_S_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
158                                        P2Align:$p2align), [],
159                      "i64.load8_s\t$dst, ${off}(${addr})${p2align}">;
160 def LOAD8_U_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
161                                        P2Align:$p2align), [],
162                      "i64.load8_u\t$dst, ${off}(${addr})${p2align}">;
163 def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
164                                        P2Align:$p2align), [],
165                      "i64.load16_s\t$dst, ${off}(${addr})${p2align}">;
166 def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
167                                        P2Align:$p2align), [],
168                      "i64.load16_u\t$dst, ${off}(${addr})${p2align}">;
169 def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
170                                        P2Align:$p2align), [],
171                      "i64.load32_s\t$dst, ${off}(${addr})${p2align}">;
172 def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
173                                        P2Align:$p2align), [],
174                      "i64.load32_u\t$dst, ${off}(${addr})${p2align}">;
175
176 } // Defs = [ARGUMENTS]
177
178 // Select extending loads with no constant offset.
179 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr, 0)>;
180 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>;
181 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr, 0)>;
182 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>;
183 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr, 0)>;
184 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>;
185 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr, 0)>;
186 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>;
187 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr, 0)>;
188 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>;
189
190 // Select extending loads with a constant offset.
191 def : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
192           (LOAD8_S_I32 imm:$off, $addr, 0)>;
193 def : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
194           (LOAD8_U_I32 imm:$off, $addr, 0)>;
195 def : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
196           (LOAD16_S_I32 imm:$off, $addr, 0)>;
197 def : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
198           (LOAD16_U_I32 imm:$off, $addr, 0)>;
199 def : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
200           (LOAD8_S_I64 imm:$off, $addr, 0)>;
201 def : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
202           (LOAD8_U_I64 imm:$off, $addr, 0)>;
203 def : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
204           (LOAD16_S_I64 imm:$off, $addr, 0)>;
205 def : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
206           (LOAD16_U_I64 imm:$off, $addr, 0)>;
207 def : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))),
208           (LOAD32_S_I64 imm:$off, $addr, 0)>;
209 def : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))),
210           (LOAD32_U_I64 imm:$off, $addr, 0)>;
211 def : Pat<(i32 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
212           (LOAD8_S_I32 imm:$off, $addr, 0)>;
213 def : Pat<(i32 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
214           (LOAD8_U_I32 imm:$off, $addr, 0)>;
215 def : Pat<(i32 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
216           (LOAD16_S_I32 imm:$off, $addr, 0)>;
217 def : Pat<(i32 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
218           (LOAD16_U_I32 imm:$off, $addr, 0)>;
219 def : Pat<(i64 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
220           (LOAD8_S_I64 imm:$off, $addr, 0)>;
221 def : Pat<(i64 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
222           (LOAD8_U_I64 imm:$off, $addr, 0)>;
223 def : Pat<(i64 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
224           (LOAD16_S_I64 imm:$off, $addr, 0)>;
225 def : Pat<(i64 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
226           (LOAD16_U_I64 imm:$off, $addr, 0)>;
227 def : Pat<(i64 (sextloadi32 (or_is_add I32:$addr, imm:$off))),
228           (LOAD32_S_I64 imm:$off, $addr, 0)>;
229 def : Pat<(i64 (zextloadi32 (or_is_add I32:$addr, imm:$off))),
230           (LOAD32_U_I64 imm:$off, $addr, 0)>;
231 def : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr,
232                                       (WebAssemblywrapper tglobaladdr:$off)))),
233           (LOAD8_S_I32 tglobaladdr:$off, $addr, 0)>;
234 def : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr,
235                                       (WebAssemblywrapper tglobaladdr:$off)))),
236           (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>;
237 def : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr,
238                                        (WebAssemblywrapper tglobaladdr:$off)))),
239           (LOAD16_S_I32 tglobaladdr:$off, $addr, 0)>;
240 def : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr,
241                                        (WebAssemblywrapper tglobaladdr:$off)))),
242           (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>;
243 def : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr,
244                                       (WebAssemblywrapper tglobaladdr:$off)))),
245           (LOAD8_S_I64 tglobaladdr:$off, $addr, 0)>;
246 def : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr,
247                                       (WebAssemblywrapper tglobaladdr:$off)))),
248           (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>;
249 def : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr,
250                                        (WebAssemblywrapper tglobaladdr:$off)))),
251           (LOAD16_S_I64 tglobaladdr:$off, $addr, 0)>;
252 def : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr,
253                                        (WebAssemblywrapper tglobaladdr:$off)))),
254           (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>;
255 def : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr,
256                                        (WebAssemblywrapper tglobaladdr:$off)))),
257           (LOAD32_S_I64 tglobaladdr:$off, $addr, 0)>;
258 def : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr,
259                                        (WebAssemblywrapper tglobaladdr:$off)))),
260           (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>;
261 def : Pat<(i32 (sextloadi8 (add I32:$addr,
262                                 (WebAssemblywrapper texternalsym:$off)))),
263           (LOAD8_S_I32 texternalsym:$off, $addr, 0)>;
264 def : Pat<(i32 (zextloadi8 (add I32:$addr,
265                                 (WebAssemblywrapper texternalsym:$off)))),
266           (LOAD8_U_I32 texternalsym:$off, $addr, 0)>;
267 def : Pat<(i32 (sextloadi16 (add I32:$addr,
268                                  (WebAssemblywrapper texternalsym:$off)))),
269           (LOAD16_S_I32 texternalsym:$off, $addr, 0)>;
270 def : Pat<(i32 (zextloadi16 (add I32:$addr,
271                                  (WebAssemblywrapper texternalsym:$off)))),
272           (LOAD16_U_I32 texternalsym:$off, $addr, 0)>;
273 def : Pat<(i64 (sextloadi8 (add I32:$addr,
274                                 (WebAssemblywrapper texternalsym:$off)))),
275           (LOAD8_S_I64 texternalsym:$off, $addr, 0)>;
276 def : Pat<(i64 (zextloadi8 (add I32:$addr,
277                                 (WebAssemblywrapper texternalsym:$off)))),
278           (LOAD8_U_I64 texternalsym:$off, $addr, 0)>;
279 def : Pat<(i64 (sextloadi16 (add I32:$addr,
280                                  (WebAssemblywrapper texternalsym:$off)))),
281           (LOAD16_S_I64 texternalsym:$off, $addr, 0)>;
282 def : Pat<(i64 (zextloadi16 (add I32:$addr,
283                                  (WebAssemblywrapper texternalsym:$off)))),
284           (LOAD16_U_I64 texternalsym:$off, $addr, 0)>;
285 def : Pat<(i64 (sextloadi32 (add I32:$addr,
286                                  (WebAssemblywrapper texternalsym:$off)))),
287           (LOAD32_S_I64 texternalsym:$off, $addr, 0)>;
288 def : Pat<(i64 (zextloadi32 (add I32:$addr,
289                                  (WebAssemblywrapper texternalsym:$off)))),
290           (LOAD32_U_I64 texternalsym:$off, $addr, 0)>;
291
292 // Select extending loads with just a constant offset.
293 def : Pat<(i32 (sextloadi8 imm:$off)),
294           (LOAD8_S_I32 imm:$off, (CONST_I32 0), 0)>;
295 def : Pat<(i32 (zextloadi8 imm:$off)),
296           (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>;
297 def : Pat<(i32 (sextloadi16 imm:$off)),
298           (LOAD16_S_I32 imm:$off, (CONST_I32 0), 0)>;
299 def : Pat<(i32 (zextloadi16 imm:$off)),
300           (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>;
301 def : Pat<(i64 (sextloadi8 imm:$off)),
302           (LOAD8_S_I64 imm:$off, (CONST_I32 0), 0)>;
303 def : Pat<(i64 (zextloadi8 imm:$off)),
304           (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>;
305 def : Pat<(i64 (sextloadi16 imm:$off)),
306           (LOAD16_S_I64 imm:$off, (CONST_I32 0), 0)>;
307 def : Pat<(i64 (zextloadi16 imm:$off)),
308           (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>;
309 def : Pat<(i64 (sextloadi32 imm:$off)),
310           (LOAD32_S_I64 imm:$off, (CONST_I32 0), 0)>;
311 def : Pat<(i64 (zextloadi32 imm:$off)),
312           (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>;
313 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
314           (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
315 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
316           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
317 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
318           (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
319 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
320           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
321 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
322           (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
323 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
324           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
325 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
326           (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
327 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
328           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
329 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
330           (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
331 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
332           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
333 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
334           (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0), 0)>;
335 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
336           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
337 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
338           (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0), 0)>;
339 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
340           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
341 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
342           (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
343 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
344           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
345 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
346           (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
347 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
348           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
349 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
350           (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0), 0)>;
351 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
352           (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
353
354 // Resolve "don't care" extending loads to zero-extending loads. This is
355 // somewhat arbitrary, but zero-extending is conceptually simpler.
356
357 // Select "don't care" extending loads with no constant offset.
358 def : Pat<(i32 (extloadi8 I32:$addr)),  (LOAD8_U_I32 0, $addr, 0)>;
359 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>;
360 def : Pat<(i64 (extloadi8 I32:$addr)),  (LOAD8_U_I64 0, $addr, 0)>;
361 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>;
362 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>;
363
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 imm:$off, $addr, 0)>;
367 def : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
368           (LOAD16_U_I32 imm:$off, $addr, 0)>;
369 def : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
370           (LOAD8_U_I64 imm:$off, $addr, 0)>;
371 def : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
372           (LOAD16_U_I64 imm:$off, $addr, 0)>;
373 def : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))),
374           (LOAD32_U_I64 imm:$off, $addr, 0)>;
375 def : Pat<(i32 (extloadi8 (or_is_add I32:$addr, imm:$off))),
376           (LOAD8_U_I32 imm:$off, $addr, 0)>;
377 def : Pat<(i32 (extloadi16 (or_is_add I32:$addr, imm:$off))),
378           (LOAD16_U_I32 imm:$off, $addr, 0)>;
379 def : Pat<(i64 (extloadi8 (or_is_add I32:$addr, imm:$off))),
380           (LOAD8_U_I64 imm:$off, $addr, 0)>;
381 def : Pat<(i64 (extloadi16 (or_is_add I32:$addr, imm:$off))),
382           (LOAD16_U_I64 imm:$off, $addr, 0)>;
383 def : Pat<(i64 (extloadi32 (or_is_add I32:$addr, imm:$off))),
384           (LOAD32_U_I64 imm:$off, $addr, 0)>;
385 def : Pat<(i32 (extloadi8 (regPlusGA I32:$addr,
386                                      (WebAssemblywrapper tglobaladdr:$off)))),
387           (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>;
388 def : Pat<(i32 (extloadi16 (regPlusGA I32:$addr,
389                                       (WebAssemblywrapper tglobaladdr:$off)))),
390           (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>;
391 def : Pat<(i64 (extloadi8 (regPlusGA I32:$addr,
392                                      (WebAssemblywrapper tglobaladdr:$off)))),
393           (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>;
394 def : Pat<(i64 (extloadi16 (regPlusGA I32:$addr,
395                                       (WebAssemblywrapper tglobaladdr:$off)))),
396           (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>;
397 def : Pat<(i64 (extloadi32 (regPlusGA I32:$addr,
398                                       (WebAssemblywrapper tglobaladdr:$off)))),
399           (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>;
400 def : Pat<(i32 (extloadi8 (add I32:$addr,
401                                (WebAssemblywrapper texternalsym:$off)))),
402           (LOAD8_U_I32 texternalsym:$off, $addr, 0)>;
403 def : Pat<(i32 (extloadi16 (add I32:$addr,
404                                 (WebAssemblywrapper texternalsym:$off)))),
405           (LOAD16_U_I32 texternalsym:$off, $addr, 0)>;
406 def : Pat<(i64 (extloadi8 (add I32:$addr,
407                                (WebAssemblywrapper texternalsym:$off)))),
408           (LOAD8_U_I64 texternalsym:$off, $addr, 0)>;
409 def : Pat<(i64 (extloadi16 (add I32:$addr,
410                                 (WebAssemblywrapper texternalsym:$off)))),
411           (LOAD16_U_I64 texternalsym:$off, $addr, 0)>;
412 def : Pat<(i64 (extloadi32 (add I32:$addr,
413                                 (WebAssemblywrapper texternalsym:$off)))),
414           (LOAD32_U_I64 texternalsym:$off, $addr, 0)>;
415
416 // Select "don't care" extending loads with just a constant offset.
417 def : Pat<(i32 (extloadi8 imm:$off)),
418           (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>;
419 def : Pat<(i32 (extloadi16 imm:$off)),
420           (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>;
421 def : Pat<(i64 (extloadi8 imm:$off)),
422           (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>;
423 def : Pat<(i64 (extloadi16 imm:$off)),
424           (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>;
425 def : Pat<(i64 (extloadi32 imm:$off)),
426           (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>;
427 def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
428           (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
429 def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
430           (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>;
431 def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
432           (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
433 def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
434           (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
435 def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
436           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
437 def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
438           (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
439 def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
440           (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>;
441 def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
442           (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
443 def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
444           (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>;
445 def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
446           (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>;
447
448 let Defs = [ARGUMENTS] in {
449
450 // Basic store.
451 // Note that we split the patterns out of the instruction definitions because
452 // WebAssembly's stores return their operand value, and tablegen doesn't like
453 // instruction definition patterns that don't reference all of the output
454 // operands.
455 // Note: WebAssembly inverts SelectionDAG's usual operand order.
456 def STORE_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
457                                      P2Align:$p2align, I32:$val), [],
458                    "i32.store\t$dst, ${off}(${addr})${p2align}, $val">;
459 def STORE_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
460                                      P2Align:$p2align, I64:$val), [],
461                    "i64.store\t$dst, ${off}(${addr})${p2align}, $val">;
462 def STORE_F32  : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr,
463                                      P2Align:$p2align, F32:$val), [],
464                    "f32.store\t$dst, ${off}(${addr})${p2align}, $val">;
465 def STORE_F64  : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr,
466                                      P2Align:$p2align, F64:$val), [],
467                    "f64.store\t$dst, ${off}(${addr})${p2align}, $val">;
468
469 } // Defs = [ARGUMENTS]
470
471 // Select stores with no constant offset.
472 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, 0, I32:$val)>;
473 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, 0, I64:$val)>;
474 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, 0, F32:$val)>;
475 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, 0, F64:$val)>;
476
477 // Select stores with a constant offset.
478 def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)),
479           (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>;
480 def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)),
481           (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>;
482 def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)),
483           (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>;
484 def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)),
485           (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>;
486 def : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)),
487           (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>;
488 def : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)),
489           (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>;
490 def : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)),
491           (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>;
492 def : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)),
493           (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>;
494 def : Pat<(store I32:$val, (regPlusGA I32:$addr,
495                                       (WebAssemblywrapper tglobaladdr:$off))),
496           (STORE_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
497 def : Pat<(store I64:$val, (regPlusGA I32:$addr,
498                                       (WebAssemblywrapper tglobaladdr:$off))),
499           (STORE_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
500 def : Pat<(store F32:$val, (regPlusGA I32:$addr,
501                                       (WebAssemblywrapper tglobaladdr:$off))),
502           (STORE_F32 tglobaladdr:$off, I32:$addr, 0, F32:$val)>;
503 def : Pat<(store F64:$val, (regPlusGA I32:$addr,
504                                       (WebAssemblywrapper tglobaladdr:$off))),
505           (STORE_F64 tglobaladdr:$off, I32:$addr, 0, F64:$val)>;
506 def : Pat<(store I32:$val, (add I32:$addr,
507                                 (WebAssemblywrapper texternalsym:$off))),
508           (STORE_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
509 def : Pat<(store I64:$val, (add I32:$addr,
510                                 (WebAssemblywrapper texternalsym:$off))),
511           (STORE_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
512 def : Pat<(store F32:$val, (add I32:$addr,
513                                 (WebAssemblywrapper texternalsym:$off))),
514           (STORE_F32 texternalsym:$off, I32:$addr, 0, F32:$val)>;
515 def : Pat<(store F64:$val, (add I32:$addr,
516                                 (WebAssemblywrapper texternalsym:$off))),
517           (STORE_F64 texternalsym:$off, I32:$addr, 0, F64:$val)>;
518
519 // Select stores with just a constant offset.
520 def : Pat<(store I32:$val, imm:$off),
521           (STORE_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
522 def : Pat<(store I64:$val, imm:$off),
523           (STORE_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
524 def : Pat<(store F32:$val, imm:$off),
525           (STORE_F32 imm:$off, (CONST_I32 0), 0, F32:$val)>;
526 def : Pat<(store F64:$val, imm:$off),
527           (STORE_F64 imm:$off, (CONST_I32 0), 0, F64:$val)>;
528 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
529           (STORE_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
530 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
531           (STORE_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
532 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
533           (STORE_F32 tglobaladdr:$off, (CONST_I32 0), 0, F32:$val)>;
534 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
535           (STORE_F64 tglobaladdr:$off, (CONST_I32 0), 0, F64:$val)>;
536 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
537           (STORE_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
538 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
539           (STORE_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
540 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
541           (STORE_F32 texternalsym:$off, (CONST_I32 0), 0, F32:$val)>;
542 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
543           (STORE_F64 texternalsym:$off, (CONST_I32 0), 0, F64:$val)>;
544
545 let Defs = [ARGUMENTS] in {
546
547 // Truncating store.
548 def STORE8_I32  : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
549                                       P2Align:$p2align, I32:$val), [],
550                     "i32.store8\t$dst, ${off}(${addr})${p2align}, $val">;
551 def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr,
552                                       P2Align:$p2align, I32:$val), [],
553                     "i32.store16\t$dst, ${off}(${addr})${p2align}, $val">;
554 def STORE8_I64  : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
555                                       P2Align:$p2align, I64:$val), [],
556                     "i64.store8\t$dst, ${off}(${addr})${p2align}, $val">;
557 def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
558                                       P2Align:$p2align, I64:$val), [],
559                     "i64.store16\t$dst, ${off}(${addr})${p2align}, $val">;
560 def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr,
561                                       P2Align:$p2align, I64:$val), [],
562                     "i64.store32\t$dst, ${off}(${addr})${p2align}, $val">;
563
564 } // Defs = [ARGUMENTS]
565
566 // Select truncating stores with no constant offset.
567 def : Pat<(truncstorei8 I32:$val, I32:$addr),
568           (STORE8_I32 0, I32:$addr, 0, I32:$val)>;
569 def : Pat<(truncstorei16 I32:$val, I32:$addr),
570           (STORE16_I32 0, I32:$addr, 0, I32:$val)>;
571 def : Pat<(truncstorei8 I64:$val, I32:$addr),
572           (STORE8_I64 0, I32:$addr, 0, I64:$val)>;
573 def : Pat<(truncstorei16 I64:$val, I32:$addr),
574           (STORE16_I64 0, I32:$addr, 0, I64:$val)>;
575 def : Pat<(truncstorei32 I64:$val, I32:$addr),
576           (STORE32_I64 0, I32:$addr, 0, I64:$val)>;
577
578 // Select truncating stores with a constant offset.
579 def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)),
580           (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>;
581 def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)),
582           (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>;
583 def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)),
584           (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>;
585 def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)),
586           (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>;
587 def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)),
588           (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>;
589 def : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)),
590           (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>;
591 def : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)),
592           (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>;
593 def : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)),
594           (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>;
595 def : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)),
596           (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>;
597 def : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)),
598           (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>;
599 def : Pat<(truncstorei8 I32:$val,
600                         (regPlusGA I32:$addr,
601                                    (WebAssemblywrapper tglobaladdr:$off))),
602           (STORE8_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
603 def : Pat<(truncstorei16 I32:$val,
604                          (regPlusGA I32:$addr,
605                                     (WebAssemblywrapper tglobaladdr:$off))),
606           (STORE16_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>;
607 def : Pat<(truncstorei8 I64:$val,
608                         (regPlusGA I32:$addr,
609                                    (WebAssemblywrapper tglobaladdr:$off))),
610           (STORE8_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
611 def : Pat<(truncstorei16 I64:$val,
612                          (regPlusGA I32:$addr,
613                                     (WebAssemblywrapper tglobaladdr:$off))),
614           (STORE16_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
615 def : Pat<(truncstorei32 I64:$val,
616                          (regPlusGA I32:$addr,
617                                     (WebAssemblywrapper tglobaladdr:$off))),
618           (STORE32_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>;
619 def : Pat<(truncstorei8 I32:$val, (add I32:$addr,
620                                        (WebAssemblywrapper texternalsym:$off))),
621           (STORE8_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
622 def : Pat<(truncstorei16 I32:$val,
623                          (add I32:$addr,
624                               (WebAssemblywrapper texternalsym:$off))),
625           (STORE16_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>;
626 def : Pat<(truncstorei8 I64:$val,
627                         (add I32:$addr,
628                              (WebAssemblywrapper texternalsym:$off))),
629           (STORE8_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
630 def : Pat<(truncstorei16 I64:$val,
631                          (add I32:$addr,
632                               (WebAssemblywrapper texternalsym:$off))),
633           (STORE16_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
634 def : Pat<(truncstorei32 I64:$val,
635                          (add I32:$addr,
636                               (WebAssemblywrapper texternalsym:$off))),
637           (STORE32_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>;
638
639 // Select truncating stores with just a constant offset.
640 def : Pat<(truncstorei8 I32:$val, imm:$off),
641           (STORE8_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
642 def : Pat<(truncstorei16 I32:$val, imm:$off),
643           (STORE16_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>;
644 def : Pat<(truncstorei8 I64:$val, imm:$off),
645           (STORE8_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
646 def : Pat<(truncstorei16 I64:$val, imm:$off),
647           (STORE16_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
648 def : Pat<(truncstorei32 I64:$val, imm:$off),
649           (STORE32_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>;
650 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
651           (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
652 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
653           (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>;
654 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
655           (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
656 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
657           (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
658 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
659           (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>;
660 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
661           (STORE8_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
662 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
663           (STORE16_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>;
664 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
665           (STORE8_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
666 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
667           (STORE16_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
668 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
669           (STORE32_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>;
670
671 let Defs = [ARGUMENTS] in {
672
673 // Current memory size.
674 def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins),
675                            [(set I32:$dst, (int_wasm_current_memory))],
676                            "current_memory\t$dst">,
677                          Requires<[HasAddr32]>;
678 def CURRENT_MEMORY_I64 : I<(outs I64:$dst), (ins),
679                            [(set I64:$dst, (int_wasm_current_memory))],
680                            "current_memory\t$dst">,
681                          Requires<[HasAddr64]>;
682
683 // Grow memory.
684 def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta),
685                         [(int_wasm_grow_memory I32:$delta)],
686                         "grow_memory\t$delta">,
687                       Requires<[HasAddr32]>;
688 def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta),
689                         [(int_wasm_grow_memory I64:$delta)],
690                         "grow_memory\t$delta">,
691                       Requires<[HasAddr64]>;
692
693 } // Defs = [ARGUMENTS]