blob: 85fd1f5078b772f6dc6c294b2d91704ba08dcb50 [file] [log] [blame]
JF Bastien5ca0bac2015-07-10 18:23:10 +00001// 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
Dan Gohman9c54d3b2015-11-25 18:13:18 +000015// TODO:
JF Bastien73ff6af2015-08-31 22:24:11 +000016// - HasAddr64
JF Bastien73ff6af2015-08-31 22:24:11 +000017// - WebAssemblyTargetLowering having to do with atomics
Dan Gohman4b9d7912015-12-15 22:01:29 +000018// - Each has optional alignment.
JF Bastien73ff6af2015-08-31 22:24:11 +000019
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
Dan Gohman4b9d7912015-12-15 22:01:29 +000024// 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.
27def regPlusImm : PatFrag<(ops node:$off, node:$addr),
28 (add node:$addr, node:$off),
29 [{ return N->getFlags()->hasNoUnsignedWrap(); }]>;
30
Dan Gohmanfb3e0592015-11-25 19:36:19 +000031let Defs = [ARGUMENTS] in {
32
JF Bastien73ff6af2015-08-31 22:24:11 +000033// Basic load.
Dan Gohmane3d7b582015-12-15 03:21:48 +000034def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +000035 "i32.load\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +000036def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +000037 "i64.load\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +000038def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +000039 "f32.load\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +000040def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +000041 "f64.load\t$dst, $off($addr)">;
JF Bastien73ff6af2015-08-31 22:24:11 +000042
Dan Gohman4b9d7912015-12-15 22:01:29 +000043} // Defs = [ARGUMENTS]
44
45// Select loads with no constant offset.
46def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>;
47def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>;
48def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>;
49def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>;
50
51// Select loads with a constant offset.
52def : Pat<(i32 (load (regPlusImm imm:$off, I32:$addr))),
53 (LOAD_I32 imm:$off, $addr)>;
54def : Pat<(i64 (load (regPlusImm imm:$off, I32:$addr))),
55 (LOAD_I64 imm:$off, $addr)>;
56def : Pat<(f32 (load (regPlusImm imm:$off, I32:$addr))),
57 (LOAD_F32 imm:$off, $addr)>;
58def : Pat<(f64 (load (regPlusImm imm:$off, I32:$addr))),
59 (LOAD_F64 imm:$off, $addr)>;
60def : Pat<(i32 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
61 (LOAD_I32 tglobaladdr:$off, $addr)>;
62def : Pat<(i64 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
63 (LOAD_I64 tglobaladdr:$off, $addr)>;
64def : Pat<(f32 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
65 (LOAD_F32 tglobaladdr:$off, $addr)>;
66def : Pat<(f64 (load (regPlusImm tglobaladdr:$off, I32:$addr))),
67 (LOAD_F64 tglobaladdr:$off, $addr)>;
68def : Pat<(i32 (load (regPlusImm texternalsym:$off, I32:$addr))),
69 (LOAD_I32 texternalsym:$off, $addr)>;
70def : Pat<(i64 (load (regPlusImm texternalsym:$off, I32:$addr))),
71 (LOAD_I64 texternalsym:$off, $addr)>;
72def : Pat<(f32 (load (regPlusImm texternalsym:$off, I32:$addr))),
73 (LOAD_F32 texternalsym:$off, $addr)>;
74def : Pat<(f64 (load (regPlusImm texternalsym:$off, I32:$addr))),
75 (LOAD_F64 texternalsym:$off, $addr)>;
76
77// Select loads with just a constant offset.
78def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0))>;
79def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0))>;
80def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0))>;
81def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0))>;
82def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))),
83 (LOAD_I32 tglobaladdr:$off, (CONST_I32 0))>;
84def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))),
85 (LOAD_I64 tglobaladdr:$off, (CONST_I32 0))>;
86def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))),
87 (LOAD_F32 tglobaladdr:$off, (CONST_I32 0))>;
88def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))),
89 (LOAD_F64 tglobaladdr:$off, (CONST_I32 0))>;
90def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))),
91 (LOAD_I32 texternalsym:$off, (CONST_I32 0))>;
92def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))),
93 (LOAD_I64 texternalsym:$off, (CONST_I32 0))>;
94def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))),
95 (LOAD_F32 texternalsym:$off, (CONST_I32 0))>;
96def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))),
97 (LOAD_F64 texternalsym:$off, (CONST_I32 0))>;
98
99let Defs = [ARGUMENTS] in {
100
JF Bastien73ff6af2015-08-31 22:24:11 +0000101// Extending load.
Dan Gohmane3d7b582015-12-15 03:21:48 +0000102def LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000103 "i32.load8_s\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000104def LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000105 "i32.load8_u\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000106def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000107 "i32.load16_s\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000108def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000109 "i32.load16_u\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000110def LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000111 "i64.load8_s\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000112def LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000113 "i64.load8_u\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000114def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000115 "i64.load16_s\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000116def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000117 "i64.load16_u\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000118def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000119 "i64.load32_s\t$dst, $off($addr)">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000120def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000121 "i64.load32_u\t$dst, $off($addr)">;
JF Bastien73ff6af2015-08-31 22:24:11 +0000122
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000123} // Defs = [ARGUMENTS]
124
Derek Schuff9d779522015-12-05 00:26:39 +0000125// Select extending loads with no constant offset.
126def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>;
127def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>;
128def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>;
129def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
130def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>;
131def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>;
132def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>;
133def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
134def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>;
135def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
136
Dan Gohman4b9d7912015-12-15 22:01:29 +0000137// Select extending loads with a constant offset.
138def : Pat<(i32 (sextloadi8 (regPlusImm imm:$off, I32:$addr))),
139 (LOAD8_S_I32 imm:$off, $addr)>;
140def : Pat<(i32 (zextloadi8 (regPlusImm imm:$off, I32:$addr))),
141 (LOAD8_U_I32 imm:$off, $addr)>;
142def : Pat<(i32 (sextloadi16 (regPlusImm imm:$off, I32:$addr))),
143 (LOAD16_S_I32 imm:$off, $addr)>;
144def : Pat<(i32 (zextloadi16 (regPlusImm imm:$off, I32:$addr))),
145 (LOAD16_U_I32 imm:$off, $addr)>;
146def : Pat<(i64 (sextloadi8 (regPlusImm imm:$off, I32:$addr))),
147 (LOAD8_S_I64 imm:$off, $addr)>;
148def : Pat<(i64 (zextloadi8 (regPlusImm imm:$off, I32:$addr))),
149 (LOAD8_U_I64 imm:$off, $addr)>;
150def : Pat<(i64 (sextloadi16 (regPlusImm imm:$off, I32:$addr))),
151 (LOAD16_S_I64 imm:$off, $addr)>;
152def : Pat<(i64 (zextloadi16 (regPlusImm imm:$off, I32:$addr))),
153 (LOAD16_U_I64 imm:$off, $addr)>;
154def : Pat<(i64 (sextloadi32 (regPlusImm imm:$off, I32:$addr))),
155 (LOAD32_S_I64 imm:$off, $addr)>;
156def : Pat<(i64 (zextloadi32 (regPlusImm imm:$off, I32:$addr))),
157 (LOAD32_U_I64 imm:$off, $addr)>;
158def : Pat<(i32 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
159 (LOAD8_S_I32 tglobaladdr:$off, $addr)>;
160def : Pat<(i32 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
161 (LOAD8_U_I32 tglobaladdr:$off, $addr)>;
162def : Pat<(i32 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
163 (LOAD16_S_I32 tglobaladdr:$off, $addr)>;
164def : Pat<(i32 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
165 (LOAD16_U_I32 tglobaladdr:$off, $addr)>;
166def : Pat<(i64 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
167 (LOAD8_S_I64 tglobaladdr:$off, $addr)>;
168def : Pat<(i64 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
169 (LOAD8_U_I64 tglobaladdr:$off, $addr)>;
170def : Pat<(i64 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
171 (LOAD16_S_I64 tglobaladdr:$off, $addr)>;
172def : Pat<(i64 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
173 (LOAD16_U_I64 tglobaladdr:$off, $addr)>;
174def : Pat<(i64 (sextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
175 (LOAD32_S_I64 tglobaladdr:$off, $addr)>;
176def : Pat<(i64 (zextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
177 (LOAD32_U_I64 tglobaladdr:$off, $addr)>;
178def : Pat<(i32 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
179 (LOAD8_S_I32 texternalsym:$off, $addr)>;
180def : Pat<(i32 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
181 (LOAD8_U_I32 texternalsym:$off, $addr)>;
182def : Pat<(i32 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
183 (LOAD16_S_I32 texternalsym:$off, $addr)>;
184def : Pat<(i32 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
185 (LOAD16_U_I32 texternalsym:$off, $addr)>;
186def : Pat<(i64 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
187 (LOAD8_S_I64 texternalsym:$off, $addr)>;
188def : Pat<(i64 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
189 (LOAD8_U_I64 texternalsym:$off, $addr)>;
190def : Pat<(i64 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
191 (LOAD16_S_I64 texternalsym:$off, $addr)>;
192def : Pat<(i64 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
193 (LOAD16_U_I64 texternalsym:$off, $addr)>;
194def : Pat<(i64 (sextloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
195 (LOAD32_S_I64 texternalsym:$off, $addr)>;
196def : Pat<(i64 (zextloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
197 (LOAD32_U_I64 texternalsym:$off, $addr)>;
198
199// Select extending loads with just a constant offset.
200def : Pat<(i32 (sextloadi8 imm:$off)), (LOAD8_S_I32 imm:$off, (CONST_I32 0))>;
201def : Pat<(i32 (zextloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>;
202def : Pat<(i32 (sextloadi16 imm:$off)), (LOAD16_S_I32 imm:$off, (CONST_I32 0))>;
203def : Pat<(i32 (zextloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>;
204def : Pat<(i64 (sextloadi8 imm:$off)), (LOAD8_S_I64 imm:$off, (CONST_I32 0))>;
205def : Pat<(i64 (zextloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>;
206def : Pat<(i64 (sextloadi16 imm:$off)), (LOAD16_S_I64 imm:$off, (CONST_I32 0))>;
207def : Pat<(i64 (zextloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>;
208def : Pat<(i64 (sextloadi32 imm:$off)), (LOAD32_S_I64 imm:$off, (CONST_I32 0))>;
209def : Pat<(i64 (zextloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>;
210def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
211 (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0))>;
212def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
213 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
214def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
215 (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0))>;
216def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
217 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
218def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
219 (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
220def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))),
221 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
222def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
223 (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
224def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))),
225 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
226def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
227 (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0))>;
228def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))),
229 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
230def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
231 (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0))>;
232def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
233 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>;
234def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
235 (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0))>;
236def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
237 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>;
238def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))),
239 (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0))>;
240def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))),
241 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>;
242def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))),
243 (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0))>;
244def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))),
245 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>;
246def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))),
247 (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0))>;
248def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))),
249 (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0))>;
250
251// Resolve "don't care" extending loads to zero-extending loads. This is
252// somewhat arbitrary, but zero-extending is conceptually simpler.
253
254// Select "don't care" extending loads with no constant offset.
Derek Schuff9d779522015-12-05 00:26:39 +0000255def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>;
256def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>;
257def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>;
258def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>;
259def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000260
Dan Gohman4b9d7912015-12-15 22:01:29 +0000261// Select "don't care" extending loads with a constant offset.
262def : Pat<(i32 (extloadi8 (regPlusImm imm:$off, I32:$addr))),
263 (LOAD8_U_I32 imm:$off, $addr)>;
264def : Pat<(i32 (extloadi16 (regPlusImm imm:$off, I32:$addr))),
265 (LOAD16_U_I32 imm:$off, $addr)>;
266def : Pat<(i64 (extloadi8 (regPlusImm imm:$off, I32:$addr))),
267 (LOAD8_U_I64 imm:$off, $addr)>;
268def : Pat<(i64 (extloadi16 (regPlusImm imm:$off, I32:$addr))),
269 (LOAD16_U_I64 imm:$off, $addr)>;
270def : Pat<(i64 (extloadi32 (regPlusImm imm:$off, I32:$addr))),
271 (LOAD32_U_I64 imm:$off, $addr)>;
272def : Pat<(i32 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
273 (LOAD8_U_I32 tglobaladdr:$off, $addr)>;
274def : Pat<(i32 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
275 (LOAD16_U_I32 tglobaladdr:$off, $addr)>;
276def : Pat<(i64 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))),
277 (LOAD8_U_I64 tglobaladdr:$off, $addr)>;
278def : Pat<(i64 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))),
279 (LOAD16_U_I64 tglobaladdr:$off, $addr)>;
280def : Pat<(i64 (extloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))),
281 (LOAD32_U_I64 tglobaladdr:$off, $addr)>;
282def : Pat<(i32 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
283 (LOAD8_U_I32 texternalsym:$off, $addr)>;
284def : Pat<(i32 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
285 (LOAD16_U_I32 texternalsym:$off, $addr)>;
286def : Pat<(i64 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))),
287 (LOAD8_U_I64 texternalsym:$off, $addr)>;
288def : Pat<(i64 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))),
289 (LOAD16_U_I64 texternalsym:$off, $addr)>;
290def : Pat<(i64 (extloadi32 (regPlusImm texternalsym:$off, I32:$addr))),
291 (LOAD32_U_I64 texternalsym:$off, $addr)>;
292
293// Select "don't care" extending loads with just a constant offset.
294def : Pat<(i32 (extloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>;
295def : Pat<(i32 (extloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>;
296def : Pat<(i64 (extloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>;
297def : Pat<(i64 (extloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>;
298def : Pat<(i64 (extloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>;
299def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
300 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
301def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
302 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>;
303def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))),
304 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
305def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))),
306 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
307def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))),
308 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
309def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
310 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>;
311def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
312 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>;
313def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))),
314 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>;
315def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))),
316 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>;
317def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))),
318 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>;
319
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000320let Defs = [ARGUMENTS] in {
321
JF Bastien73ff6af2015-08-31 22:24:11 +0000322// Basic store.
Dan Gohman7054ac12015-11-23 21:16:35 +0000323// Note that we split the patterns out of the instruction definitions because
324// WebAssembly's stores return their operand value, and tablegen doesn't like
325// instruction definition patterns that don't reference all of the output
326// operands.
JF Bastien73ff6af2015-08-31 22:24:11 +0000327// Note: WebAssembly inverts SelectionDAG's usual operand order.
Dan Gohmane3d7b582015-12-15 03:21:48 +0000328def STORE_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000329 "i32.store\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000330def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000331 "i64.store\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000332def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, F32:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000333 "f32.store\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000334def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, F64:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000335 "f64.store\t$dst, $off($addr), $val">;
Dan Gohman7054ac12015-11-23 21:16:35 +0000336
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000337} // Defs = [ARGUMENTS]
338
Dan Gohman4b9d7912015-12-15 22:01:29 +0000339// Select stores with no constant offset.
Derek Schuff9d779522015-12-05 00:26:39 +0000340def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>;
341def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>;
342def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>;
343def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>;
344
Dan Gohman4b9d7912015-12-15 22:01:29 +0000345// Select stores with a constant offset.
346def : Pat<(store I32:$val, (regPlusImm imm:$off, I32:$addr)),
347 (STORE_I32 imm:$off, I32:$addr, I32:$val)>;
348def : Pat<(store I64:$val, (regPlusImm imm:$off, I32:$addr)),
349 (STORE_I64 imm:$off, I32:$addr, I64:$val)>;
350def : Pat<(store F32:$val, (regPlusImm imm:$off, I32:$addr)),
351 (STORE_F32 imm:$off, I32:$addr, F32:$val)>;
352def : Pat<(store F64:$val, (regPlusImm imm:$off, I32:$addr)),
353 (STORE_F64 imm:$off, I32:$addr, F64:$val)>;
354def : Pat<(store I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
355 (STORE_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
356def : Pat<(store I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
357 (STORE_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
358def : Pat<(store F32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
359 (STORE_F32 tglobaladdr:$off, I32:$addr, F32:$val)>;
360def : Pat<(store F64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
361 (STORE_F64 tglobaladdr:$off, I32:$addr, F64:$val)>;
362def : Pat<(store I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
363 (STORE_I32 texternalsym:$off, I32:$addr, I32:$val)>;
364def : Pat<(store I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
365 (STORE_I64 texternalsym:$off, I32:$addr, I64:$val)>;
366def : Pat<(store F32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
367 (STORE_F32 texternalsym:$off, I32:$addr, F32:$val)>;
368def : Pat<(store F64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
369 (STORE_F64 texternalsym:$off, I32:$addr, F64:$val)>;
370
371// Select stores with just a constant offset.
372def : Pat<(store I32:$val, imm:$off),
373 (STORE_I32 imm:$off, (CONST_I32 0), I32:$val)>;
374def : Pat<(store I64:$val, imm:$off),
375 (STORE_I64 imm:$off, (CONST_I32 0), I64:$val)>;
376def : Pat<(store F32:$val, imm:$off),
377 (STORE_F32 imm:$off, (CONST_I32 0), F32:$val)>;
378def : Pat<(store F64:$val, imm:$off),
379 (STORE_F64 imm:$off, (CONST_I32 0), F64:$val)>;
380def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
381 (STORE_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
382def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
383 (STORE_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
384def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)),
385 (STORE_F32 tglobaladdr:$off, (CONST_I32 0), F32:$val)>;
386def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)),
387 (STORE_F64 tglobaladdr:$off, (CONST_I32 0), F64:$val)>;
388def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)),
389 (STORE_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
390def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)),
391 (STORE_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
392def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)),
393 (STORE_F32 texternalsym:$off, (CONST_I32 0), F32:$val)>;
394def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)),
395 (STORE_F64 texternalsym:$off, (CONST_I32 0), F64:$val)>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000396
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000397let Defs = [ARGUMENTS] in {
398
JF Bastien73ff6af2015-08-31 22:24:11 +0000399// Truncating store.
Dan Gohmane3d7b582015-12-15 03:21:48 +0000400def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000401 "i32.store8\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000402def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000403 "i32.store16\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000404def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000405 "i64.store8\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000406def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000407 "i64.store16\t$dst, $off($addr), $val">;
Dan Gohmane3d7b582015-12-15 03:21:48 +0000408def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [],
Derek Schuff9d779522015-12-05 00:26:39 +0000409 "i64.store32\t$dst, $off($addr), $val">;
Dan Gohman7054ac12015-11-23 21:16:35 +0000410
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000411} // Defs = [ARGUMENTS]
412
Dan Gohman4b9d7912015-12-15 22:01:29 +0000413// Select truncating stores with no constant offset.
Dan Gohman7054ac12015-11-23 21:16:35 +0000414def : Pat<(truncstorei8 I32:$val, I32:$addr),
Derek Schuff9d779522015-12-05 00:26:39 +0000415 (STORE8_I32 0, I32:$addr, I32:$val)>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000416def : Pat<(truncstorei16 I32:$val, I32:$addr),
Derek Schuff9d779522015-12-05 00:26:39 +0000417 (STORE16_I32 0, I32:$addr, I32:$val)>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000418def : Pat<(truncstorei8 I64:$val, I32:$addr),
Derek Schuff9d779522015-12-05 00:26:39 +0000419 (STORE8_I64 0, I32:$addr, I64:$val)>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000420def : Pat<(truncstorei16 I64:$val, I32:$addr),
Derek Schuff9d779522015-12-05 00:26:39 +0000421 (STORE16_I64 0, I32:$addr, I64:$val)>;
Dan Gohman7054ac12015-11-23 21:16:35 +0000422def : Pat<(truncstorei32 I64:$val, I32:$addr),
Derek Schuff9d779522015-12-05 00:26:39 +0000423 (STORE32_I64 0, I32:$addr, I64:$val)>;
JF Bastien73ff6af2015-08-31 22:24:11 +0000424
Dan Gohman4b9d7912015-12-15 22:01:29 +0000425// Select truncating stores with a constant offset.
426def : Pat<(truncstorei8 I32:$val, (regPlusImm imm:$off, I32:$addr)),
427 (STORE8_I32 imm:$off, I32:$addr, I32:$val)>;
428def : Pat<(truncstorei16 I32:$val, (regPlusImm imm:$off, I32:$addr)),
429 (STORE16_I32 imm:$off, I32:$addr, I32:$val)>;
430def : Pat<(truncstorei8 I64:$val, (regPlusImm imm:$off, I32:$addr)),
431 (STORE8_I64 imm:$off, I32:$addr, I64:$val)>;
432def : Pat<(truncstorei16 I64:$val, (regPlusImm imm:$off, I32:$addr)),
433 (STORE16_I64 imm:$off, I32:$addr, I64:$val)>;
434def : Pat<(truncstorei32 I64:$val, (regPlusImm imm:$off, I32:$addr)),
435 (STORE32_I64 imm:$off, I32:$addr, I64:$val)>;
436def : Pat<(truncstorei8 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
437 (STORE8_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
438def : Pat<(truncstorei16 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
439 (STORE16_I32 tglobaladdr:$off, I32:$addr, I32:$val)>;
440def : Pat<(truncstorei8 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
441 (STORE8_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
442def : Pat<(truncstorei16 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
443 (STORE16_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
444def : Pat<(truncstorei32 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)),
445 (STORE32_I64 tglobaladdr:$off, I32:$addr, I64:$val)>;
446def : Pat<(truncstorei8 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
447 (STORE8_I32 texternalsym:$off, I32:$addr, I32:$val)>;
448def : Pat<(truncstorei16 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)),
449 (STORE16_I32 texternalsym:$off, I32:$addr, I32:$val)>;
450def : Pat<(truncstorei8 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
451 (STORE8_I64 texternalsym:$off, I32:$addr, I64:$val)>;
452def : Pat<(truncstorei16 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
453 (STORE16_I64 texternalsym:$off, I32:$addr, I64:$val)>;
454def : Pat<(truncstorei32 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)),
455 (STORE32_I64 texternalsym:$off, I32:$addr, I64:$val)>;
456
457// Select truncating stores with just a constant offset.
458def : Pat<(truncstorei8 I32:$val, imm:$off),
459 (STORE8_I32 imm:$off, (CONST_I32 0), I32:$val)>;
460def : Pat<(truncstorei16 I32:$val, imm:$off),
461 (STORE16_I32 imm:$off, (CONST_I32 0), I32:$val)>;
462def : Pat<(truncstorei8 I64:$val, imm:$off),
463 (STORE8_I64 imm:$off, (CONST_I32 0), I64:$val)>;
464def : Pat<(truncstorei16 I64:$val, imm:$off),
465 (STORE16_I64 imm:$off, (CONST_I32 0), I64:$val)>;
466def : Pat<(truncstorei32 I64:$val, imm:$off),
467 (STORE32_I64 imm:$off, (CONST_I32 0), I64:$val)>;
468def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
469 (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
470def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)),
471 (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>;
472def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
473 (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
474def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
475 (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
476def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)),
477 (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>;
478def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)),
479 (STORE8_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
480def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)),
481 (STORE16_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>;
482def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)),
483 (STORE8_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
484def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)),
485 (STORE16_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
486def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)),
487 (STORE32_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>;
488
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000489let Defs = [ARGUMENTS] in {
490
Dan Gohman72f16922015-10-02 19:21:15 +0000491// Memory size.
Dan Gohmanf4333242015-11-13 20:19:11 +0000492def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins),
Dan Gohmanaf29bd42015-11-05 20:42:30 +0000493 [(set I32:$dst, (int_wasm_memory_size))],
Dan Gohman192dddc2015-11-23 22:37:29 +0000494 "memory_size\t$dst">,
Dan Gohman72f16922015-10-02 19:21:15 +0000495 Requires<[HasAddr32]>;
Dan Gohmanf4333242015-11-13 20:19:11 +0000496def MEMORY_SIZE_I64 : I<(outs I64:$dst), (ins),
Dan Gohmanaf29bd42015-11-05 20:42:30 +0000497 [(set I64:$dst, (int_wasm_memory_size))],
Dan Gohman192dddc2015-11-23 22:37:29 +0000498 "memory_size\t$dst">,
Dan Gohman72f16922015-10-02 19:21:15 +0000499 Requires<[HasAddr64]>;
Dan Gohmanbaba8c62015-10-02 20:10:26 +0000500
Dan Gohmand7ffb912015-11-05 20:16:59 +0000501// Grow memory.
Dan Gohmanf4333242015-11-13 20:19:11 +0000502def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta),
Dan Gohmanaf29bd42015-11-05 20:42:30 +0000503 [(int_wasm_grow_memory I32:$delta)],
Dan Gohman192dddc2015-11-23 22:37:29 +0000504 "grow_memory\t$delta">,
Dan Gohmand7ffb912015-11-05 20:16:59 +0000505 Requires<[HasAddr32]>;
Dan Gohmanf4333242015-11-13 20:19:11 +0000506def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta),
Dan Gohmanaf29bd42015-11-05 20:42:30 +0000507 [(int_wasm_grow_memory I64:$delta)],
Dan Gohman192dddc2015-11-23 22:37:29 +0000508 "grow_memory\t$delta">,
Dan Gohmand7ffb912015-11-05 20:16:59 +0000509 Requires<[HasAddr64]>;
Dan Gohmanfb3e0592015-11-25 19:36:19 +0000510
511} // Defs = [ARGUMENTS]