WebAssemblyInstrMemory.td revision 321369
1286425Sdim// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
2286425Sdim//
3286425Sdim//                     The LLVM Compiler Infrastructure
4286425Sdim//
5286425Sdim// This file is distributed under the University of Illinois Open Source
6286425Sdim// License. See LICENSE.TXT for details.
7286425Sdim//
8286425Sdim//===----------------------------------------------------------------------===//
9286425Sdim///
10286425Sdim/// \file
11286425Sdim/// \brief WebAssembly Memory operand code-gen constructs.
12286425Sdim///
13286425Sdim//===----------------------------------------------------------------------===//
14286425Sdim
15296417Sdim// TODO:
16296417Sdim//  - HasAddr64
17296417Sdim//  - WebAssemblyTargetLowering having to do with atomics
18296417Sdim//  - Each has optional alignment.
19296417Sdim
20296417Sdim// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
21296417Sdim// local types. These memory-only types instead zero- or sign-extend into local
22296417Sdim// types when loading, and truncate when storing.
23296417Sdim
24296417Sdim// WebAssembly constant offsets are performed as unsigned with infinite
25296417Sdim// precision, so we need to check for NoUnsignedWrap so that we don't fold an
26296417Sdim// offset for an add that needs wrapping.
27296417Sdimdef regPlusImm : PatFrag<(ops node:$addr, node:$off),
28296417Sdim                         (add node:$addr, node:$off),
29321369Sdim                         [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
30296417Sdim
31309124Sdim// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
32309124Sdimdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
33309124Sdim  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
34309124Sdim    return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
35309124Sdim
36321369Sdim  KnownBits Known0;
37321369Sdim  CurDAG->computeKnownBits(N->getOperand(0), Known0, 0);
38321369Sdim  KnownBits Known1;
39321369Sdim  CurDAG->computeKnownBits(N->getOperand(1), Known1, 0);
40321369Sdim  return (~Known0.Zero & ~Known1.Zero) == 0;
41309124Sdim}]>;
42309124Sdim
43296417Sdim// GlobalAddresses are conceptually unsigned values, so we can also fold them
44314564Sdim// into immediate values as long as the add is 'nuw'.
45314564Sdim// TODO: We'd like to also match GA offsets but there are cases where the
46314564Sdim// register can have a negative value. Find out what more we can do.
47296417Sdimdef regPlusGA : PatFrag<(ops node:$addr, node:$off),
48296417Sdim                        (add node:$addr, node:$off),
49296417Sdim                        [{
50321369Sdim  return N->getFlags().hasNoUnsignedWrap();
51296417Sdim}]>;
52296417Sdim
53296417Sdim// We don't need a regPlusES because external symbols never have constant
54296417Sdim// offsets folded into them, so we can just use add.
55296417Sdim
56296417Sdimlet Defs = [ARGUMENTS] in {
57296417Sdim
58296417Sdim// Basic load.
59314564Sdim// FIXME: When we can break syntax compatibility, reorder the fields in the
60314564Sdim// asmstrings to match the binary encoding.
61314564Sdimdef LOAD_I32 : I<(outs I32:$dst),
62314564Sdim                 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
63314564Sdim                 [], "i32.load\t$dst, ${off}(${addr})${p2align}", 0x28>;
64314564Sdimdef LOAD_I64 : I<(outs I64:$dst),
65314564Sdim                 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
66314564Sdim                 [], "i64.load\t$dst, ${off}(${addr})${p2align}", 0x29>;
67314564Sdimdef LOAD_F32 : I<(outs F32:$dst),
68314564Sdim                 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
69314564Sdim                 [], "f32.load\t$dst, ${off}(${addr})${p2align}", 0x2a>;
70314564Sdimdef LOAD_F64 : I<(outs F64:$dst),
71314564Sdim                 (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
72314564Sdim                 [], "f64.load\t$dst, ${off}(${addr})${p2align}", 0x2b>;
73296417Sdim
74296417Sdim} // Defs = [ARGUMENTS]
75296417Sdim
76296417Sdim// Select loads with no constant offset.
77314564Sdimdef : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, 0, $addr)>;
78314564Sdimdef : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, 0, $addr)>;
79314564Sdimdef : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, 0, $addr)>;
80314564Sdimdef : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, 0, $addr)>;
81296417Sdim
82296417Sdim// Select loads with a constant offset.
83296417Sdimdef : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))),
84314564Sdim          (LOAD_I32 0, imm:$off, $addr)>;
85296417Sdimdef : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))),
86314564Sdim          (LOAD_I64 0, imm:$off, $addr)>;
87296417Sdimdef : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))),
88314564Sdim          (LOAD_F32 0, imm:$off, $addr)>;
89296417Sdimdef : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))),
90314564Sdim          (LOAD_F64 0, imm:$off, $addr)>;
91309124Sdimdef : Pat<(i32 (load (or_is_add I32:$addr, imm:$off))),
92314564Sdim          (LOAD_I32 0, imm:$off, $addr)>;
93309124Sdimdef : Pat<(i64 (load (or_is_add I32:$addr, imm:$off))),
94314564Sdim          (LOAD_I64 0, imm:$off, $addr)>;
95309124Sdimdef : Pat<(f32 (load (or_is_add I32:$addr, imm:$off))),
96314564Sdim          (LOAD_F32 0, imm:$off, $addr)>;
97309124Sdimdef : Pat<(f64 (load (or_is_add I32:$addr, imm:$off))),
98314564Sdim          (LOAD_F64 0, imm:$off, $addr)>;
99296417Sdimdef : Pat<(i32 (load (regPlusGA I32:$addr,
100296417Sdim                                (WebAssemblywrapper tglobaladdr:$off)))),
101314564Sdim          (LOAD_I32 0, tglobaladdr:$off, $addr)>;
102296417Sdimdef : Pat<(i64 (load (regPlusGA I32:$addr,
103296417Sdim                                (WebAssemblywrapper tglobaladdr:$off)))),
104314564Sdim          (LOAD_I64 0, tglobaladdr:$off, $addr)>;
105296417Sdimdef : Pat<(f32 (load (regPlusGA I32:$addr,
106296417Sdim                                (WebAssemblywrapper tglobaladdr:$off)))),
107314564Sdim          (LOAD_F32 0, tglobaladdr:$off, $addr)>;
108296417Sdimdef : Pat<(f64 (load (regPlusGA I32:$addr,
109296417Sdim                                (WebAssemblywrapper tglobaladdr:$off)))),
110314564Sdim          (LOAD_F64 0, tglobaladdr:$off, $addr)>;
111296417Sdimdef : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
112314564Sdim          (LOAD_I32 0, texternalsym:$off, $addr)>;
113296417Sdimdef : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
114314564Sdim          (LOAD_I64 0, texternalsym:$off, $addr)>;
115296417Sdimdef : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
116314564Sdim          (LOAD_F32 0, texternalsym:$off, $addr)>;
117296417Sdimdef : Pat<(f64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))),
118314564Sdim          (LOAD_F64 0, texternalsym:$off, $addr)>;
119296417Sdim
120296417Sdim// Select loads with just a constant offset.
121314564Sdimdef : Pat<(i32 (load imm:$off)), (LOAD_I32 0, imm:$off, (CONST_I32 0))>;
122314564Sdimdef : Pat<(i64 (load imm:$off)), (LOAD_I64 0, imm:$off, (CONST_I32 0))>;
123314564Sdimdef : Pat<(f32 (load imm:$off)), (LOAD_F32 0, imm:$off, (CONST_I32 0))>;
124314564Sdimdef : Pat<(f64 (load imm:$off)), (LOAD_F64 0, imm:$off, (CONST_I32 0))>;
125296417Sdimdef : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
126314564Sdim          (LOAD_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
127296417Sdimdef : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
128314564Sdim          (LOAD_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
129296417Sdimdef : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
130314564Sdim          (LOAD_F32 0, tglobaladdr:$off, (CONST_I32 0))>;
131296417Sdimdef : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
132314564Sdim          (LOAD_F64 0, tglobaladdr:$off, (CONST_I32 0))>;
133296417Sdimdef : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
134314564Sdim          (LOAD_I32 0, texternalsym:$off, (CONST_I32 0))>;
135296417Sdimdef : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
136314564Sdim          (LOAD_I64 0, texternalsym:$off, (CONST_I32 0))>;
137296417Sdimdef : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
138314564Sdim          (LOAD_F32 0, texternalsym:$off, (CONST_I32 0))>;
139296417Sdimdef : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
140314564Sdim          (LOAD_F64 0, texternalsym:$off, (CONST_I32 0))>;
141296417Sdim
142296417Sdimlet Defs = [ARGUMENTS] in {
143296417Sdim
144296417Sdim// Extending load.
145314564Sdimdef LOAD8_S_I32  : I<(outs I32:$dst),
146314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
147314564Sdim                     [], "i32.load8_s\t$dst, ${off}(${addr})${p2align}", 0x2c>;
148314564Sdimdef LOAD8_U_I32  : I<(outs I32:$dst),
149314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
150314564Sdim                     [], "i32.load8_u\t$dst, ${off}(${addr})${p2align}", 0x2d>;
151314564Sdimdef LOAD16_S_I32 : I<(outs I32:$dst),
152314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
153314564Sdim                     [], "i32.load16_s\t$dst, ${off}(${addr})${p2align}", 0x2e>;
154314564Sdimdef LOAD16_U_I32 : I<(outs I32:$dst),
155314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
156314564Sdim                     [], "i32.load16_u\t$dst, ${off}(${addr})${p2align}", 0x2f>;
157314564Sdimdef LOAD8_S_I64  : I<(outs I64:$dst),
158314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
159314564Sdim                     [], "i64.load8_s\t$dst, ${off}(${addr})${p2align}", 0x30>;
160314564Sdimdef LOAD8_U_I64  : I<(outs I64:$dst),
161314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
162314564Sdim                     [], "i64.load8_u\t$dst, ${off}(${addr})${p2align}", 0x31>;
163314564Sdimdef LOAD16_S_I64 : I<(outs I64:$dst),
164314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
165314564Sdim                     [], "i64.load16_s\t$dst, ${off}(${addr})${p2align}", 0x32>;
166314564Sdimdef LOAD16_U_I64 : I<(outs I64:$dst),
167314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
168314564Sdim                     [], "i64.load16_u\t$dst, ${off}(${addr})${p2align}", 0x33>;
169314564Sdimdef LOAD32_S_I64 : I<(outs I64:$dst),
170314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
171314564Sdim                     [], "i64.load32_s\t$dst, ${off}(${addr})${p2align}", 0x34>;
172314564Sdimdef LOAD32_U_I64 : I<(outs I64:$dst),
173314564Sdim                     (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
174314564Sdim                     [], "i64.load32_u\t$dst, ${off}(${addr})${p2align}", 0x35>;
175296417Sdim
176296417Sdim} // Defs = [ARGUMENTS]
177296417Sdim
178296417Sdim// Select extending loads with no constant offset.
179314564Sdimdef : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, 0, $addr)>;
180314564Sdimdef : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, 0, $addr)>;
181314564Sdimdef : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, 0, $addr)>;
182314564Sdimdef : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, 0, $addr)>;
183314564Sdimdef : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, 0, $addr)>;
184314564Sdimdef : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, 0, $addr)>;
185314564Sdimdef : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, 0, $addr)>;
186314564Sdimdef : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, 0, $addr)>;
187314564Sdimdef : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, 0, $addr)>;
188314564Sdimdef : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, 0, $addr)>;
189296417Sdim
190296417Sdim// Select extending loads with a constant offset.
191296417Sdimdef : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
192314564Sdim          (LOAD8_S_I32 0, imm:$off, $addr)>;
193296417Sdimdef : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
194314564Sdim          (LOAD8_U_I32 0, imm:$off, $addr)>;
195296417Sdimdef : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
196314564Sdim          (LOAD16_S_I32 0, imm:$off, $addr)>;
197296417Sdimdef : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
198314564Sdim          (LOAD16_U_I32 0, imm:$off, $addr)>;
199296417Sdimdef : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))),
200314564Sdim          (LOAD8_S_I64 0, imm:$off, $addr)>;
201296417Sdimdef : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))),
202314564Sdim          (LOAD8_U_I64 0, imm:$off, $addr)>;
203296417Sdimdef : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))),
204314564Sdim          (LOAD16_S_I64 0, imm:$off, $addr)>;
205296417Sdimdef : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))),
206314564Sdim          (LOAD16_U_I64 0, imm:$off, $addr)>;
207296417Sdimdef : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))),
208314564Sdim          (LOAD32_S_I64 0, imm:$off, $addr)>;
209296417Sdimdef : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))),
210314564Sdim          (LOAD32_U_I64 0, imm:$off, $addr)>;
211309124Sdimdef : Pat<(i32 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
212314564Sdim          (LOAD8_S_I32 0, imm:$off, $addr)>;
213309124Sdimdef : Pat<(i32 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
214314564Sdim          (LOAD8_U_I32 0, imm:$off, $addr)>;
215309124Sdimdef : Pat<(i32 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
216314564Sdim          (LOAD16_S_I32 0, imm:$off, $addr)>;
217309124Sdimdef : Pat<(i32 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
218314564Sdim          (LOAD16_U_I32 0, imm:$off, $addr)>;
219309124Sdimdef : Pat<(i64 (sextloadi8 (or_is_add I32:$addr, imm:$off))),
220314564Sdim          (LOAD8_S_I64 0, imm:$off, $addr)>;
221309124Sdimdef : Pat<(i64 (zextloadi8 (or_is_add I32:$addr, imm:$off))),
222314564Sdim          (LOAD8_U_I64 0, imm:$off, $addr)>;
223309124Sdimdef : Pat<(i64 (sextloadi16 (or_is_add I32:$addr, imm:$off))),
224314564Sdim          (LOAD16_S_I64 0, imm:$off, $addr)>;
225309124Sdimdef : Pat<(i64 (zextloadi16 (or_is_add I32:$addr, imm:$off))),
226314564Sdim          (LOAD16_U_I64 0, imm:$off, $addr)>;
227309124Sdimdef : Pat<(i64 (sextloadi32 (or_is_add I32:$addr, imm:$off))),
228314564Sdim          (LOAD32_S_I64 0, imm:$off, $addr)>;
229309124Sdimdef : Pat<(i64 (zextloadi32 (or_is_add I32:$addr, imm:$off))),
230314564Sdim          (LOAD32_U_I64 0, imm:$off, $addr)>;
231296417Sdimdef : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr,
232296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
233314564Sdim          (LOAD8_S_I32 0, tglobaladdr:$off, $addr)>;
234296417Sdimdef : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr,
235296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
236314564Sdim          (LOAD8_U_I32 0, tglobaladdr:$off, $addr)>;
237296417Sdimdef : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr,
238296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
239314564Sdim          (LOAD16_S_I32 0, tglobaladdr:$off, $addr)>;
240296417Sdimdef : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr,
241296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
242314564Sdim          (LOAD16_U_I32 0, tglobaladdr:$off, $addr)>;
243296417Sdimdef : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr,
244296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
245314564Sdim          (LOAD8_S_I64 0, tglobaladdr:$off, $addr)>;
246296417Sdimdef : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr,
247296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
248314564Sdim          (LOAD8_U_I64 0, tglobaladdr:$off, $addr)>;
249296417Sdimdef : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr,
250296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
251314564Sdim          (LOAD16_S_I64 0, tglobaladdr:$off, $addr)>;
252296417Sdimdef : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr,
253296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
254314564Sdim          (LOAD16_U_I64 0, tglobaladdr:$off, $addr)>;
255296417Sdimdef : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr,
256296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
257314564Sdim          (LOAD32_S_I64 0, tglobaladdr:$off, $addr)>;
258296417Sdimdef : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr,
259296417Sdim                                       (WebAssemblywrapper tglobaladdr:$off)))),
260314564Sdim          (LOAD32_U_I64 0, tglobaladdr:$off, $addr)>;
261296417Sdimdef : Pat<(i32 (sextloadi8 (add I32:$addr,
262296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
263314564Sdim          (LOAD8_S_I32 0, texternalsym:$off, $addr)>;
264296417Sdimdef : Pat<(i32 (zextloadi8 (add I32:$addr,
265296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
266314564Sdim          (LOAD8_U_I32 0, texternalsym:$off, $addr)>;
267296417Sdimdef : Pat<(i32 (sextloadi16 (add I32:$addr,
268296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
269314564Sdim          (LOAD16_S_I32 0, texternalsym:$off, $addr)>;
270296417Sdimdef : Pat<(i32 (zextloadi16 (add I32:$addr,
271296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
272314564Sdim          (LOAD16_U_I32 0, texternalsym:$off, $addr)>;
273296417Sdimdef : Pat<(i64 (sextloadi8 (add I32:$addr,
274296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
275314564Sdim          (LOAD8_S_I64 0, texternalsym:$off, $addr)>;
276296417Sdimdef : Pat<(i64 (zextloadi8 (add I32:$addr,
277296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
278314564Sdim          (LOAD8_U_I64 0, texternalsym:$off, $addr)>;
279296417Sdimdef : Pat<(i64 (sextloadi16 (add I32:$addr,
280296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
281314564Sdim          (LOAD16_S_I64 0, texternalsym:$off, $addr)>;
282296417Sdimdef : Pat<(i64 (zextloadi16 (add I32:$addr,
283296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
284314564Sdim          (LOAD16_U_I64 0, texternalsym:$off, $addr)>;
285296417Sdimdef : Pat<(i64 (sextloadi32 (add I32:$addr,
286296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
287314564Sdim          (LOAD32_S_I64 0, texternalsym:$off, $addr)>;
288296417Sdimdef : Pat<(i64 (zextloadi32 (add I32:$addr,
289296417Sdim                                 (WebAssemblywrapper texternalsym:$off)))),
290314564Sdim          (LOAD32_U_I64 0, texternalsym:$off, $addr)>;
291296417Sdim
292296417Sdim// Select extending loads with just a constant offset.
293309124Sdimdef : Pat<(i32 (sextloadi8 imm:$off)),
294314564Sdim          (LOAD8_S_I32 0, imm:$off, (CONST_I32 0))>;
295309124Sdimdef : Pat<(i32 (zextloadi8 imm:$off)),
296314564Sdim          (LOAD8_U_I32 0, imm:$off, (CONST_I32 0))>;
297309124Sdimdef : Pat<(i32 (sextloadi16 imm:$off)),
298314564Sdim          (LOAD16_S_I32 0, imm:$off, (CONST_I32 0))>;
299309124Sdimdef : Pat<(i32 (zextloadi16 imm:$off)),
300314564Sdim          (LOAD16_U_I32 0, imm:$off, (CONST_I32 0))>;
301309124Sdimdef : Pat<(i64 (sextloadi8 imm:$off)),
302314564Sdim          (LOAD8_S_I64 0, imm:$off, (CONST_I32 0))>;
303309124Sdimdef : Pat<(i64 (zextloadi8 imm:$off)),
304314564Sdim          (LOAD8_U_I64 0, imm:$off, (CONST_I32 0))>;
305309124Sdimdef : Pat<(i64 (sextloadi16 imm:$off)),
306314564Sdim          (LOAD16_S_I64 0, imm:$off, (CONST_I32 0))>;
307309124Sdimdef : Pat<(i64 (zextloadi16 imm:$off)),
308314564Sdim          (LOAD16_U_I64 0, imm:$off, (CONST_I32 0))>;
309309124Sdimdef : Pat<(i64 (sextloadi32 imm:$off)),
310314564Sdim          (LOAD32_S_I64 0, imm:$off, (CONST_I32 0))>;
311309124Sdimdef : Pat<(i64 (zextloadi32 imm:$off)),
312314564Sdim          (LOAD32_U_I64 0, imm:$off, (CONST_I32 0))>;
313296417Sdimdef : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
314314564Sdim          (LOAD8_S_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
315296417Sdimdef : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
316314564Sdim          (LOAD8_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
317296417Sdimdef : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
318314564Sdim          (LOAD16_S_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
319296417Sdimdef : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
320314564Sdim          (LOAD16_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
321296417Sdimdef : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
322314564Sdim          (LOAD8_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
323296417Sdimdef : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
324314564Sdim          (LOAD8_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
325296417Sdimdef : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
326314564Sdim          (LOAD16_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
327296417Sdimdef : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
328314564Sdim          (LOAD16_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
329296417Sdimdef : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
330314564Sdim          (LOAD32_S_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
331296417Sdimdef : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
332314564Sdim          (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
333296417Sdimdef : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
334314564Sdim          (LOAD8_S_I32 0, texternalsym:$off, (CONST_I32 0))>;
335296417Sdimdef : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
336314564Sdim          (LOAD8_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
337296417Sdimdef : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
338314564Sdim          (LOAD16_S_I32 0, texternalsym:$off, (CONST_I32 0))>;
339296417Sdimdef : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
340314564Sdim          (LOAD16_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
341296417Sdimdef : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
342314564Sdim          (LOAD8_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
343296417Sdimdef : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
344314564Sdim          (LOAD8_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
345296417Sdimdef : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
346314564Sdim          (LOAD16_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
347296417Sdimdef : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
348314564Sdim          (LOAD16_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
349296417Sdimdef : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
350314564Sdim          (LOAD32_S_I64 0, texternalsym:$off, (CONST_I32 0))>;
351296417Sdimdef : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
352314564Sdim          (LOAD32_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
353296417Sdim
354296417Sdim// Resolve "don't care" extending loads to zero-extending loads. This is
355296417Sdim// somewhat arbitrary, but zero-extending is conceptually simpler.
356296417Sdim
357296417Sdim// Select "don't care" extending loads with no constant offset.
358314564Sdimdef : Pat<(i32 (extloadi8 I32:$addr)),  (LOAD8_U_I32 0, 0, $addr)>;
359314564Sdimdef : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, 0, $addr)>;
360314564Sdimdef : Pat<(i64 (extloadi8 I32:$addr)),  (LOAD8_U_I64 0, 0, $addr)>;
361314564Sdimdef : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, 0, $addr)>;
362314564Sdimdef : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, 0, $addr)>;
363296417Sdim
364296417Sdim// Select "don't care" extending loads with a constant offset.
365296417Sdimdef : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
366314564Sdim          (LOAD8_U_I32 0, imm:$off, $addr)>;
367296417Sdimdef : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
368314564Sdim          (LOAD16_U_I32 0, imm:$off, $addr)>;
369296417Sdimdef : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))),
370314564Sdim          (LOAD8_U_I64 0, imm:$off, $addr)>;
371296417Sdimdef : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))),
372314564Sdim          (LOAD16_U_I64 0, imm:$off, $addr)>;
373296417Sdimdef : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))),
374314564Sdim          (LOAD32_U_I64 0, imm:$off, $addr)>;
375309124Sdimdef : Pat<(i32 (extloadi8 (or_is_add I32:$addr, imm:$off))),
376314564Sdim          (LOAD8_U_I32 0, imm:$off, $addr)>;
377309124Sdimdef : Pat<(i32 (extloadi16 (or_is_add I32:$addr, imm:$off))),
378314564Sdim          (LOAD16_U_I32 0, imm:$off, $addr)>;
379309124Sdimdef : Pat<(i64 (extloadi8 (or_is_add I32:$addr, imm:$off))),
380314564Sdim          (LOAD8_U_I64 0, imm:$off, $addr)>;
381309124Sdimdef : Pat<(i64 (extloadi16 (or_is_add I32:$addr, imm:$off))),
382314564Sdim          (LOAD16_U_I64 0, imm:$off, $addr)>;
383309124Sdimdef : Pat<(i64 (extloadi32 (or_is_add I32:$addr, imm:$off))),
384314564Sdim          (LOAD32_U_I64 0, imm:$off, $addr)>;
385296417Sdimdef : Pat<(i32 (extloadi8 (regPlusGA I32:$addr,
386296417Sdim                                     (WebAssemblywrapper tglobaladdr:$off)))),
387314564Sdim          (LOAD8_U_I32 0, tglobaladdr:$off, $addr)>;
388296417Sdimdef : Pat<(i32 (extloadi16 (regPlusGA I32:$addr,
389296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
390314564Sdim          (LOAD16_U_I32 0, tglobaladdr:$off, $addr)>;
391296417Sdimdef : Pat<(i64 (extloadi8 (regPlusGA I32:$addr,
392296417Sdim                                     (WebAssemblywrapper tglobaladdr:$off)))),
393314564Sdim          (LOAD8_U_I64 0, tglobaladdr:$off, $addr)>;
394296417Sdimdef : Pat<(i64 (extloadi16 (regPlusGA I32:$addr,
395296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
396314564Sdim          (LOAD16_U_I64 0, tglobaladdr:$off, $addr)>;
397296417Sdimdef : Pat<(i64 (extloadi32 (regPlusGA I32:$addr,
398296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off)))),
399314564Sdim          (LOAD32_U_I64 0, tglobaladdr:$off, $addr)>;
400296417Sdimdef : Pat<(i32 (extloadi8 (add I32:$addr,
401296417Sdim                               (WebAssemblywrapper texternalsym:$off)))),
402314564Sdim          (LOAD8_U_I32 0, texternalsym:$off, $addr)>;
403296417Sdimdef : Pat<(i32 (extloadi16 (add I32:$addr,
404296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
405314564Sdim          (LOAD16_U_I32 0, texternalsym:$off, $addr)>;
406296417Sdimdef : Pat<(i64 (extloadi8 (add I32:$addr,
407296417Sdim                               (WebAssemblywrapper texternalsym:$off)))),
408314564Sdim          (LOAD8_U_I64 0, texternalsym:$off, $addr)>;
409296417Sdimdef : Pat<(i64 (extloadi16 (add I32:$addr,
410296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
411314564Sdim          (LOAD16_U_I64 0, texternalsym:$off, $addr)>;
412296417Sdimdef : Pat<(i64 (extloadi32 (add I32:$addr,
413296417Sdim                                (WebAssemblywrapper texternalsym:$off)))),
414314564Sdim          (LOAD32_U_I64 0, texternalsym:$off, $addr)>;
415296417Sdim
416296417Sdim// Select "don't care" extending loads with just a constant offset.
417309124Sdimdef : Pat<(i32 (extloadi8 imm:$off)),
418314564Sdim          (LOAD8_U_I32 0, imm:$off, (CONST_I32 0))>;
419309124Sdimdef : Pat<(i32 (extloadi16 imm:$off)),
420314564Sdim          (LOAD16_U_I32 0, imm:$off, (CONST_I32 0))>;
421309124Sdimdef : Pat<(i64 (extloadi8 imm:$off)),
422314564Sdim          (LOAD8_U_I64 0, imm:$off, (CONST_I32 0))>;
423309124Sdimdef : Pat<(i64 (extloadi16 imm:$off)),
424314564Sdim          (LOAD16_U_I64 0, imm:$off, (CONST_I32 0))>;
425309124Sdimdef : Pat<(i64 (extloadi32 imm:$off)),
426314564Sdim          (LOAD32_U_I64 0, imm:$off, (CONST_I32 0))>;
427296417Sdimdef : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
428314564Sdim          (LOAD8_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
429296417Sdimdef : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
430314564Sdim          (LOAD16_U_I32 0, tglobaladdr:$off, (CONST_I32 0))>;
431296417Sdimdef : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
432314564Sdim          (LOAD8_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
433296417Sdimdef : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
434314564Sdim          (LOAD16_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
435296417Sdimdef : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
436314564Sdim          (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
437296417Sdimdef : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
438314564Sdim          (LOAD8_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
439296417Sdimdef : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
440314564Sdim          (LOAD16_U_I32 0, texternalsym:$off, (CONST_I32 0))>;
441296417Sdimdef : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
442314564Sdim          (LOAD8_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
443296417Sdimdef : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
444314564Sdim          (LOAD16_U_I64 0, texternalsym:$off, (CONST_I32 0))>;
445296417Sdimdef : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
446314564Sdim          (LOAD32_U_I64 0, tglobaladdr:$off, (CONST_I32 0))>;
447296417Sdim
448296417Sdimlet Defs = [ARGUMENTS] in {
449296417Sdim
450296417Sdim// Basic store.
451296417Sdim// Note: WebAssembly inverts SelectionDAG's usual operand order.
452314564Sdimdef STORE_I32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
453314564Sdim                            I32:$val), [],
454314564Sdim                   "i32.store\t${off}(${addr})${p2align}, $val", 0x36>;
455314564Sdimdef STORE_I64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
456314564Sdim                            I64:$val), [],
457314564Sdim                   "i64.store\t${off}(${addr})${p2align}, $val", 0x37>;
458314564Sdimdef STORE_F32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
459314564Sdim                            F32:$val), [],
460314564Sdim                   "f32.store\t${off}(${addr})${p2align}, $val", 0x38>;
461314564Sdimdef STORE_F64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
462314564Sdim                            F64:$val), [],
463314564Sdim                   "f64.store\t${off}(${addr})${p2align}, $val", 0x39>;
464296417Sdim
465296417Sdim} // Defs = [ARGUMENTS]
466296417Sdim
467296417Sdim// Select stores with no constant offset.
468314564Sdimdef : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, 0, I32:$addr, I32:$val)>;
469314564Sdimdef : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, 0, I32:$addr, I64:$val)>;
470314564Sdimdef : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, 0, I32:$addr, F32:$val)>;
471314564Sdimdef : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, 0, I32:$addr, F64:$val)>;
472296417Sdim
473296417Sdim// Select stores with a constant offset.
474296417Sdimdef : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)),
475314564Sdim          (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
476296417Sdimdef : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)),
477314564Sdim          (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
478296417Sdimdef : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)),
479314564Sdim          (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
480296417Sdimdef : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)),
481314564Sdim          (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
482309124Sdimdef : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)),
483314564Sdim          (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>;
484309124Sdimdef : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)),
485314564Sdim          (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>;
486309124Sdimdef : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)),
487314564Sdim          (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>;
488309124Sdimdef : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)),
489314564Sdim          (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>;
490296417Sdimdef : Pat<(store I32:$val, (regPlusGA I32:$addr,
491296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off))),
492314564Sdim          (STORE_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
493296417Sdimdef : Pat<(store I64:$val, (regPlusGA I32:$addr,
494296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off))),
495314564Sdim          (STORE_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
496296417Sdimdef : Pat<(store F32:$val, (regPlusGA I32:$addr,
497296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off))),
498314564Sdim          (STORE_F32 0, tglobaladdr:$off, I32:$addr, F32:$val)>;
499296417Sdimdef : Pat<(store F64:$val, (regPlusGA I32:$addr,
500296417Sdim                                      (WebAssemblywrapper tglobaladdr:$off))),
501314564Sdim          (STORE_F64 0, tglobaladdr:$off, I32:$addr, F64:$val)>;
502296417Sdimdef : Pat<(store I32:$val, (add I32:$addr,
503296417Sdim                                (WebAssemblywrapper texternalsym:$off))),
504314564Sdim          (STORE_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
505296417Sdimdef : Pat<(store I64:$val, (add I32:$addr,
506296417Sdim                                (WebAssemblywrapper texternalsym:$off))),
507314564Sdim          (STORE_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
508296417Sdimdef : Pat<(store F32:$val, (add I32:$addr,
509296417Sdim                                (WebAssemblywrapper texternalsym:$off))),
510314564Sdim          (STORE_F32 0, texternalsym:$off, I32:$addr, F32:$val)>;
511296417Sdimdef : Pat<(store F64:$val, (add I32:$addr,
512296417Sdim                                (WebAssemblywrapper texternalsym:$off))),
513314564Sdim          (STORE_F64 0, texternalsym:$off, I32:$addr, F64:$val)>;
514296417Sdim
515296417Sdim// Select stores with just a constant offset.
516296417Sdimdef : Pat<(store I32:$val, imm:$off),
517314564Sdim          (STORE_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
518296417Sdimdef : Pat<(store I64:$val, imm:$off),
519314564Sdim          (STORE_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
520296417Sdimdef : Pat<(store F32:$val, imm:$off),
521314564Sdim          (STORE_F32 0, imm:$off, (CONST_I32 0), F32:$val)>;
522296417Sdimdef : Pat<(store F64:$val, imm:$off),
523314564Sdim          (STORE_F64 0, imm:$off, (CONST_I32 0), F64:$val)>;
524296417Sdimdef : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
525314564Sdim          (STORE_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
526296417Sdimdef : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
527314564Sdim          (STORE_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
528296417Sdimdef : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
529314564Sdim          (STORE_F32 0, tglobaladdr:$off, (CONST_I32 0), F32:$val)>;
530296417Sdimdef : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
531314564Sdim          (STORE_F64 0, tglobaladdr:$off, (CONST_I32 0), F64:$val)>;
532296417Sdimdef : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
533314564Sdim          (STORE_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
534296417Sdimdef : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
535314564Sdim          (STORE_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
536296417Sdimdef : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
537314564Sdim          (STORE_F32 0, texternalsym:$off, (CONST_I32 0), F32:$val)>;
538296417Sdimdef : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
539314564Sdim          (STORE_F64 0, texternalsym:$off, (CONST_I32 0), F64:$val)>;
540296417Sdim
541296417Sdimlet Defs = [ARGUMENTS] in {
542296417Sdim
543296417Sdim// Truncating store.
544314564Sdimdef STORE8_I32  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
545314564Sdim                             I32:$val), [],
546314564Sdim                    "i32.store8\t${off}(${addr})${p2align}, $val", 0x3a>;
547314564Sdimdef STORE16_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
548314564Sdim                             I32:$val), [],
549314564Sdim                    "i32.store16\t${off}(${addr})${p2align}, $val", 0x3b>;
550314564Sdimdef STORE8_I64  : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
551314564Sdim                             I64:$val), [],
552314564Sdim                    "i64.store8\t${off}(${addr})${p2align}, $val", 0x3c>;
553314564Sdimdef STORE16_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
554314564Sdim                             I64:$val), [],
555314564Sdim                    "i64.store16\t${off}(${addr})${p2align}, $val", 0x3d>;
556314564Sdimdef STORE32_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr,
557314564Sdim                             I64:$val), [],
558314564Sdim                    "i64.store32\t${off}(${addr})${p2align}, $val", 0x3e>;
559296417Sdim
560296417Sdim} // Defs = [ARGUMENTS]
561296417Sdim
562296417Sdim// Select truncating stores with no constant offset.
563296417Sdimdef : Pat<(truncstorei8 I32:$val, I32:$addr),
564314564Sdim          (STORE8_I32 0, 0, I32:$addr, I32:$val)>;
565296417Sdimdef : Pat<(truncstorei16 I32:$val, I32:$addr),
566314564Sdim          (STORE16_I32 0, 0, I32:$addr, I32:$val)>;
567296417Sdimdef : Pat<(truncstorei8 I64:$val, I32:$addr),
568314564Sdim          (STORE8_I64 0, 0, I32:$addr, I64:$val)>;
569296417Sdimdef : Pat<(truncstorei16 I64:$val, I32:$addr),
570314564Sdim          (STORE16_I64 0, 0, I32:$addr, I64:$val)>;
571296417Sdimdef : Pat<(truncstorei32 I64:$val, I32:$addr),
572314564Sdim          (STORE32_I64 0, 0, I32:$addr, I64:$val)>;
573296417Sdim
574296417Sdim// Select truncating stores with a constant offset.
575296417Sdimdef : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)),
576314564Sdim          (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
577296417Sdimdef : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)),
578314564Sdim          (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
579296417Sdimdef : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)),
580314564Sdim          (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
581296417Sdimdef : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)),
582314564Sdim          (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
583296417Sdimdef : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)),
584314564Sdim          (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
585309124Sdimdef : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)),
586314564Sdim          (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>;
587309124Sdimdef : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)),
588314564Sdim          (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>;
589309124Sdimdef : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)),
590314564Sdim          (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>;
591309124Sdimdef : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)),
592314564Sdim          (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>;
593309124Sdimdef : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)),
594314564Sdim          (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>;
595296417Sdimdef : Pat<(truncstorei8 I32:$val,
596296417Sdim                        (regPlusGA I32:$addr,
597296417Sdim                                   (WebAssemblywrapper tglobaladdr:$off))),
598314564Sdim          (STORE8_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
599296417Sdimdef : Pat<(truncstorei16 I32:$val,
600296417Sdim                         (regPlusGA I32:$addr,
601296417Sdim                                    (WebAssemblywrapper tglobaladdr:$off))),
602314564Sdim          (STORE16_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>;
603296417Sdimdef : Pat<(truncstorei8 I64:$val,
604296417Sdim                        (regPlusGA I32:$addr,
605296417Sdim                                   (WebAssemblywrapper tglobaladdr:$off))),
606314564Sdim          (STORE8_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
607296417Sdimdef : Pat<(truncstorei16 I64:$val,
608296417Sdim                         (regPlusGA I32:$addr,
609296417Sdim                                    (WebAssemblywrapper tglobaladdr:$off))),
610314564Sdim          (STORE16_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
611296417Sdimdef : Pat<(truncstorei32 I64:$val,
612296417Sdim                         (regPlusGA I32:$addr,
613296417Sdim                                    (WebAssemblywrapper tglobaladdr:$off))),
614314564Sdim          (STORE32_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>;
615296417Sdimdef : Pat<(truncstorei8 I32:$val, (add I32:$addr,
616296417Sdim                                       (WebAssemblywrapper texternalsym:$off))),
617314564Sdim          (STORE8_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
618296417Sdimdef : Pat<(truncstorei16 I32:$val,
619296417Sdim                         (add I32:$addr,
620296417Sdim                              (WebAssemblywrapper texternalsym:$off))),
621314564Sdim          (STORE16_I32 0, texternalsym:$off, I32:$addr, I32:$val)>;
622296417Sdimdef : Pat<(truncstorei8 I64:$val,
623296417Sdim                        (add I32:$addr,
624296417Sdim                             (WebAssemblywrapper texternalsym:$off))),
625314564Sdim          (STORE8_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
626296417Sdimdef : Pat<(truncstorei16 I64:$val,
627296417Sdim                         (add I32:$addr,
628296417Sdim                              (WebAssemblywrapper texternalsym:$off))),
629314564Sdim          (STORE16_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
630296417Sdimdef : Pat<(truncstorei32 I64:$val,
631296417Sdim                         (add I32:$addr,
632296417Sdim                              (WebAssemblywrapper texternalsym:$off))),
633314564Sdim          (STORE32_I64 0, texternalsym:$off, I32:$addr, I64:$val)>;
634296417Sdim
635296417Sdim// Select truncating stores with just a constant offset.
636296417Sdimdef : Pat<(truncstorei8 I32:$val, imm:$off),
637314564Sdim          (STORE8_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
638296417Sdimdef : Pat<(truncstorei16 I32:$val, imm:$off),
639314564Sdim          (STORE16_I32 0, imm:$off, (CONST_I32 0), I32:$val)>;
640296417Sdimdef : Pat<(truncstorei8 I64:$val, imm:$off),
641314564Sdim          (STORE8_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
642296417Sdimdef : Pat<(truncstorei16 I64:$val, imm:$off),
643314564Sdim          (STORE16_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
644296417Sdimdef : Pat<(truncstorei32 I64:$val, imm:$off),
645314564Sdim          (STORE32_I64 0, imm:$off, (CONST_I32 0), I64:$val)>;
646296417Sdimdef : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
647314564Sdim          (STORE8_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
648296417Sdimdef : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
649314564Sdim          (STORE16_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
650296417Sdimdef : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
651314564Sdim          (STORE8_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
652296417Sdimdef : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
653314564Sdim          (STORE16_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
654296417Sdimdef : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
655314564Sdim          (STORE32_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
656296417Sdimdef : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
657314564Sdim          (STORE8_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
658296417Sdimdef : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
659314564Sdim          (STORE16_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>;
660296417Sdimdef : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
661314564Sdim          (STORE8_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
662296417Sdimdef : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
663314564Sdim          (STORE16_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
664296417Sdimdef : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
665314564Sdim          (STORE32_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>;
666296417Sdim
667296417Sdimlet Defs = [ARGUMENTS] in {
668296417Sdim
669309124Sdim// Current memory size.
670314564Sdimdef CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
671314564Sdim                           [],
672314564Sdim                           "current_memory\t$dst", 0x3f>,
673309124Sdim                         Requires<[HasAddr32]>;
674296417Sdim
675296417Sdim// Grow memory.
676321369Sdimdef GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
677314564Sdim                        [],
678321369Sdim                        "grow_memory\t$dst, $delta", 0x40>,
679296417Sdim                      Requires<[HasAddr32]>;
680296417Sdim
681296417Sdim} // Defs = [ARGUMENTS]
682314564Sdim
683314564Sdimdef : Pat<(int_wasm_current_memory),
684314564Sdim          (CURRENT_MEMORY_I32 0)>;
685314564Sdimdef : Pat<(int_wasm_grow_memory I32:$delta),
686314564Sdim          (GROW_MEMORY_I32 0, $delta)>;
687