1286425Sdim// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*-
2286425Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6286425Sdim//
7286425Sdim//===----------------------------------------------------------------------===//
8286425Sdim///
9286425Sdim/// \file
10341825Sdim/// WebAssembly Memory operand code-gen constructs.
11286425Sdim///
12286425Sdim//===----------------------------------------------------------------------===//
13286425Sdim
14296417Sdim// TODO:
15296417Sdim//  - HasAddr64
16296417Sdim//  - WebAssemblyTargetLowering having to do with atomics
17296417Sdim//  - Each has optional alignment.
18296417Sdim
19296417Sdim// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16
20296417Sdim// local types. These memory-only types instead zero- or sign-extend into local
21296417Sdim// types when loading, and truncate when storing.
22296417Sdim
23296417Sdim// WebAssembly constant offsets are performed as unsigned with infinite
24296417Sdim// precision, so we need to check for NoUnsignedWrap so that we don't fold an
25296417Sdim// offset for an add that needs wrapping.
26296417Sdimdef regPlusImm : PatFrag<(ops node:$addr, node:$off),
27296417Sdim                         (add node:$addr, node:$off),
28321369Sdim                         [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
29296417Sdim
30309124Sdim// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
31309124Sdimdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
32309124Sdim  if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
33309124Sdim    return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
34309124Sdim
35344779Sdim  KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
36344779Sdim  KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
37321369Sdim  return (~Known0.Zero & ~Known1.Zero) == 0;
38309124Sdim}]>;
39309124Sdim
40296417Sdim// We don't need a regPlusES because external symbols never have constant
41296417Sdim// offsets folded into them, so we can just use add.
42296417Sdim
43327952Sdim// Defines atomic and non-atomic loads, regular and extending.
44341825Sdimmulticlass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> {
45353358Sdim  let mayLoad = 1, UseNamedOperandTable = 1 in
46341825Sdim  defm "": I<(outs rc:$dst),
47341825Sdim             (ins P2Align:$p2align, offset32_op:$off, I32:$addr),
48341825Sdim             (outs), (ins P2Align:$p2align, offset32_op:$off),
49341825Sdim             [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"),
50344779Sdim             !strconcat(Name, "\t${off}${p2align}"), Opcode>;
51341825Sdim}
52327952Sdim
53296417Sdim// Basic load.
54314564Sdim// FIXME: When we can break syntax compatibility, reorder the fields in the
55314564Sdim// asmstrings to match the binary encoding.
56341825Sdimdefm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>;
57341825Sdimdefm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>;
58341825Sdimdefm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>;
59341825Sdimdefm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>;
60296417Sdim
61296417Sdim// Select loads with no constant offset.
62341825Sdimclass LoadPatNoOffset<ValueType ty, PatFrag kind, NI inst> :
63341825Sdim  Pat<(ty (kind I32:$addr)), (inst 0, 0, I32:$addr)>;
64296417Sdim
65327952Sdimdef : LoadPatNoOffset<i32, load, LOAD_I32>;
66327952Sdimdef : LoadPatNoOffset<i64, load, LOAD_I64>;
67327952Sdimdef : LoadPatNoOffset<f32, load, LOAD_F32>;
68327952Sdimdef : LoadPatNoOffset<f64, load, LOAD_F64>;
69327952Sdim
70327952Sdim
71296417Sdim// Select loads with a constant offset.
72296417Sdim
73327952Sdim// Pattern with address + immediate offset
74341825Sdimclass LoadPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
75341825Sdim  Pat<(ty (kind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, I32:$addr)>;
76327952Sdim
77327952Sdimdef : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>;
78327952Sdimdef : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>;
79327952Sdimdef : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>;
80327952Sdimdef : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>;
81327952Sdimdef : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>;
82327952Sdimdef : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>;
83327952Sdimdef : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>;
84327952Sdimdef : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>;
85327952Sdim
86296417Sdim// Select loads with just a constant offset.
87341825Sdimclass LoadPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
88341825Sdim  Pat<(ty (kind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>;
89296417Sdim
90327952Sdimdef : LoadPatOffsetOnly<i32, load, LOAD_I32>;
91327952Sdimdef : LoadPatOffsetOnly<i64, load, LOAD_I64>;
92327952Sdimdef : LoadPatOffsetOnly<f32, load, LOAD_F32>;
93327952Sdimdef : LoadPatOffsetOnly<f64, load, LOAD_F64>;
94327952Sdim
95341825Sdimclass LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
96341825Sdim  Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))),
97353358Sdim      (inst 0, tglobaladdr:$off, (CONST_I32 0))>, Requires<[IsNotPIC]>;
98327952Sdim
99327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>;
100327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>;
101327952Sdimdef : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>;
102327952Sdimdef : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>;
103327952Sdim
104296417Sdim// Extending load.
105341825Sdimdefm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>;
106341825Sdimdefm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>;
107341825Sdimdefm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>;
108341825Sdimdefm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>;
109341825Sdimdefm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>;
110341825Sdimdefm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>;
111341825Sdimdefm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>;
112341825Sdimdefm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>;
113341825Sdimdefm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>;
114341825Sdimdefm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>;
115296417Sdim
116296417Sdim// Select extending loads with no constant offset.
117327952Sdimdef : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>;
118327952Sdimdef : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>;
119327952Sdimdef : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>;
120327952Sdimdef : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>;
121327952Sdimdef : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>;
122327952Sdimdef : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>;
123327952Sdimdef : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>;
124327952Sdimdef : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>;
125327952Sdimdef : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>;
126327952Sdimdef : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>;
127296417Sdim
128296417Sdim// Select extending loads with a constant offset.
129327952Sdimdef : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>;
130327952Sdimdef : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>;
131327952Sdimdef : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>;
132327952Sdimdef : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>;
133327952Sdimdef : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>;
134327952Sdimdef : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>;
135327952Sdimdef : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>;
136327952Sdimdef : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>;
137327952Sdimdef : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>;
138327952Sdimdef : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>;
139296417Sdim
140327952Sdimdef : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>;
141327952Sdimdef : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>;
142327952Sdimdef : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>;
143327952Sdimdef : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>;
144327952Sdimdef : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>;
145327952Sdimdef : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>;
146327952Sdimdef : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>;
147327952Sdimdef : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>;
148327952Sdimdef : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>;
149327952Sdimdef : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>;
150327952Sdim
151296417Sdim// Select extending loads with just a constant offset.
152327952Sdimdef : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>;
153327952Sdimdef : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>;
154327952Sdimdef : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>;
155327952Sdimdef : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>;
156296417Sdim
157327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>;
158327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>;
159327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>;
160327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>;
161327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>;
162327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>;
163327952Sdim
164327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>;
165327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>;
166327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>;
167327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>;
168327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>;
169327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>;
170327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>;
171327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>;
172327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>;
173327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>;
174327952Sdim
175296417Sdim// Resolve "don't care" extending loads to zero-extending loads. This is
176296417Sdim// somewhat arbitrary, but zero-extending is conceptually simpler.
177296417Sdim
178296417Sdim// Select "don't care" extending loads with no constant offset.
179327952Sdimdef : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>;
180327952Sdimdef : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>;
181327952Sdimdef : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>;
182327952Sdimdef : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>;
183327952Sdimdef : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>;
184296417Sdim
185296417Sdim// Select "don't care" extending loads with a constant offset.
186327952Sdimdef : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>;
187327952Sdimdef : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>;
188327952Sdimdef : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>;
189327952Sdimdef : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>;
190327952Sdimdef : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>;
191327952Sdimdef : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>;
192327952Sdimdef : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>;
193327952Sdimdef : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>;
194327952Sdimdef : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>;
195327952Sdimdef : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>;
196296417Sdim
197296417Sdim// Select "don't care" extending loads with just a constant offset.
198327952Sdimdef : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>;
199327952Sdimdef : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>;
200327952Sdimdef : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>;
201327952Sdimdef : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>;
202327952Sdimdef : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>;
203327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>;
204327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>;
205327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>;
206327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>;
207327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>;
208296417Sdim
209341825Sdim// Defines atomic and non-atomic stores, regular and truncating
210341825Sdimmulticlass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> {
211353358Sdim  let mayStore = 1, UseNamedOperandTable = 1 in
212341825Sdim  defm "" : I<(outs),
213341825Sdim              (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val),
214341825Sdim              (outs),
215341825Sdim              (ins P2Align:$p2align, offset32_op:$off), [],
216341825Sdim              !strconcat(Name, "\t${off}(${addr})${p2align}, $val"),
217344779Sdim              !strconcat(Name, "\t${off}${p2align}"), Opcode>;
218341825Sdim}
219296417Sdim// Basic store.
220296417Sdim// Note: WebAssembly inverts SelectionDAG's usual operand order.
221341825Sdimdefm STORE_I32  : WebAssemblyStore<I32, "i32.store", 0x36>;
222341825Sdimdefm STORE_I64  : WebAssemblyStore<I64, "i64.store", 0x37>;
223341825Sdimdefm STORE_F32  : WebAssemblyStore<F32, "f32.store", 0x38>;
224341825Sdimdefm STORE_F64  : WebAssemblyStore<F64, "f64.store", 0x39>;
225296417Sdim
226296417Sdim// Select stores with no constant offset.
227341825Sdimclass StorePatNoOffset<ValueType ty, PatFrag node, NI inst> :
228341825Sdim  Pat<(node ty:$val, I32:$addr), (inst 0, 0, I32:$addr, ty:$val)>;
229296417Sdim
230341825Sdimdef : StorePatNoOffset<i32, store, STORE_I32>;
231341825Sdimdef : StorePatNoOffset<i64, store, STORE_I64>;
232341825Sdimdef : StorePatNoOffset<f32, store, STORE_F32>;
233341825Sdimdef : StorePatNoOffset<f64, store, STORE_F64>;
234341825Sdim
235296417Sdim// Select stores with a constant offset.
236341825Sdimclass StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> :
237341825Sdim  Pat<(kind ty:$val, (operand I32:$addr, imm:$off)),
238341825Sdim      (inst 0, imm:$off, I32:$addr, ty:$val)>;
239296417Sdim
240341825Sdimdef : StorePatImmOff<i32, store, regPlusImm, STORE_I32>;
241341825Sdimdef : StorePatImmOff<i64, store, regPlusImm, STORE_I64>;
242341825Sdimdef : StorePatImmOff<f32, store, regPlusImm, STORE_F32>;
243341825Sdimdef : StorePatImmOff<f64, store, regPlusImm, STORE_F64>;
244341825Sdimdef : StorePatImmOff<i32, store, or_is_add, STORE_I32>;
245341825Sdimdef : StorePatImmOff<i64, store, or_is_add, STORE_I64>;
246341825Sdimdef : StorePatImmOff<f32, store, or_is_add, STORE_F32>;
247341825Sdimdef : StorePatImmOff<f64, store, or_is_add, STORE_F64>;
248341825Sdim
249296417Sdim// Select stores with just a constant offset.
250341825Sdimclass StorePatOffsetOnly<ValueType ty, PatFrag kind, NI inst> :
251341825Sdim  Pat<(kind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>;
252341825Sdimdef : StorePatOffsetOnly<i32, store, STORE_I32>;
253341825Sdimdef : StorePatOffsetOnly<i64, store, STORE_I64>;
254341825Sdimdef : StorePatOffsetOnly<f32, store, STORE_F32>;
255341825Sdimdef : StorePatOffsetOnly<f64, store, STORE_F64>;
256296417Sdim
257341825Sdimclass StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> :
258341825Sdim  Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)),
259353358Sdim      (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>, Requires<[IsNotPIC]>;
260341825Sdimdef : StorePatGlobalAddrOffOnly<i32, store, STORE_I32>;
261341825Sdimdef : StorePatGlobalAddrOffOnly<i64, store, STORE_I64>;
262341825Sdimdef : StorePatGlobalAddrOffOnly<f32, store, STORE_F32>;
263341825Sdimdef : StorePatGlobalAddrOffOnly<f64, store, STORE_F64>;
264341825Sdim
265296417Sdim// Truncating store.
266341825Sdimdefm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
267341825Sdimdefm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>;
268341825Sdimdefm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>;
269341825Sdimdefm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
270341825Sdimdefm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
271296417Sdim
272296417Sdim// Select truncating stores with no constant offset.
273341825Sdimdef : StorePatNoOffset<i32, truncstorei8, STORE8_I32>;
274341825Sdimdef : StorePatNoOffset<i32, truncstorei16, STORE16_I32>;
275341825Sdimdef : StorePatNoOffset<i64, truncstorei8, STORE8_I64>;
276341825Sdimdef : StorePatNoOffset<i64, truncstorei16, STORE16_I64>;
277341825Sdimdef : StorePatNoOffset<i64, truncstorei32, STORE32_I64>;
278296417Sdim
279296417Sdim// Select truncating stores with a constant offset.
280341825Sdimdef : StorePatImmOff<i32, truncstorei8, regPlusImm, STORE8_I32>;
281341825Sdimdef : StorePatImmOff<i32, truncstorei16, regPlusImm, STORE16_I32>;
282341825Sdimdef : StorePatImmOff<i64, truncstorei8, regPlusImm, STORE8_I64>;
283341825Sdimdef : StorePatImmOff<i64, truncstorei16, regPlusImm, STORE16_I64>;
284341825Sdimdef : StorePatImmOff<i64, truncstorei32, regPlusImm, STORE32_I64>;
285341825Sdimdef : StorePatImmOff<i32, truncstorei8, or_is_add, STORE8_I32>;
286341825Sdimdef : StorePatImmOff<i32, truncstorei16, or_is_add, STORE16_I32>;
287341825Sdimdef : StorePatImmOff<i64, truncstorei8, or_is_add, STORE8_I64>;
288341825Sdimdef : StorePatImmOff<i64, truncstorei16, or_is_add, STORE16_I64>;
289341825Sdimdef : StorePatImmOff<i64, truncstorei32, or_is_add, STORE32_I64>;
290296417Sdim
291296417Sdim// Select truncating stores with just a constant offset.
292341825Sdimdef : StorePatOffsetOnly<i32, truncstorei8, STORE8_I32>;
293341825Sdimdef : StorePatOffsetOnly<i32, truncstorei16, STORE16_I32>;
294341825Sdimdef : StorePatOffsetOnly<i64, truncstorei8, STORE8_I64>;
295341825Sdimdef : StorePatOffsetOnly<i64, truncstorei16, STORE16_I64>;
296341825Sdimdef : StorePatOffsetOnly<i64, truncstorei32, STORE32_I64>;
297341825Sdimdef : StorePatGlobalAddrOffOnly<i32, truncstorei8, STORE8_I32>;
298341825Sdimdef : StorePatGlobalAddrOffOnly<i32, truncstorei16, STORE16_I32>;
299341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei8, STORE8_I64>;
300341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei16, STORE16_I64>;
301341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei32, STORE32_I64>;
302296417Sdim
303309124Sdim// Current memory size.
304341825Sdimdefm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags),
305341825Sdim                         (outs), (ins i32imm:$flags),
306341825Sdim                         [(set I32:$dst,
307341825Sdim                           (int_wasm_memory_size (i32 imm:$flags)))],
308341825Sdim                         "memory.size\t$dst, $flags", "memory.size\t$flags",
309341825Sdim                         0x3f>,
310341825Sdim                       Requires<[HasAddr32]>;
311296417Sdim
312296417Sdim// Grow memory.
313341825Sdimdefm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta),
314344779Sdim                         (outs), (ins i32imm:$flags),
315341825Sdim                         [(set I32:$dst,
316341825Sdim                           (int_wasm_memory_grow (i32 imm:$flags),
317341825Sdim                             I32:$delta))],
318341825Sdim                         "memory.grow\t$dst, $flags, $delta",
319344779Sdim                         "memory.grow\t$flags", 0x40>,
320341825Sdim                       Requires<[HasAddr32]>;
321