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