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