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