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. 27 def 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. 32 def 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. 45 def 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 58 let Defs = [ARGUMENTS] in { 59 60 // Basic load. 61 def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, 62 P2Align:$p2align), [], 63 "i32.load\t$dst, ${off}(${addr})${p2align}">; 64 def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 65 P2Align:$p2align), [], 66 "i64.load\t$dst, ${off}(${addr})${p2align}">; 67 def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, 68 P2Align:$p2align), [], 69 "f32.load\t$dst, ${off}(${addr})${p2align}">; 70 def 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. 77 def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr, 0)>; 78 def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr, 0)>; 79 def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr, 0)>; 80 def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr, 0)>; 81 82 // Select loads with a constant offset. 83 def : Pat<(i32 (load (regPlusImm I32:$addr, imm:$off))), 84 (LOAD_I32 imm:$off, $addr, 0)>; 85 def : Pat<(i64 (load (regPlusImm I32:$addr, imm:$off))), 86 (LOAD_I64 imm:$off, $addr, 0)>; 87 def : Pat<(f32 (load (regPlusImm I32:$addr, imm:$off))), 88 (LOAD_F32 imm:$off, $addr, 0)>; 89 def : Pat<(f64 (load (regPlusImm I32:$addr, imm:$off))), 90 (LOAD_F64 imm:$off, $addr, 0)>; 91 def : Pat<(i32 (load (or_is_add I32:$addr, imm:$off))), 92 (LOAD_I32 imm:$off, $addr, 0)>; 93 def : Pat<(i64 (load (or_is_add I32:$addr, imm:$off))), 94 (LOAD_I64 imm:$off, $addr, 0)>; 95 def : Pat<(f32 (load (or_is_add I32:$addr, imm:$off))), 96 (LOAD_F32 imm:$off, $addr, 0)>; 97 def : Pat<(f64 (load (or_is_add I32:$addr, imm:$off))), 98 (LOAD_F64 imm:$off, $addr, 0)>; 99 def : Pat<(i32 (load (regPlusGA I32:$addr, 100 (WebAssemblywrapper tglobaladdr:$off)))), 101 (LOAD_I32 tglobaladdr:$off, $addr, 0)>; 102 def : Pat<(i64 (load (regPlusGA I32:$addr, 103 (WebAssemblywrapper tglobaladdr:$off)))), 104 (LOAD_I64 tglobaladdr:$off, $addr, 0)>; 105 def : Pat<(f32 (load (regPlusGA I32:$addr, 106 (WebAssemblywrapper tglobaladdr:$off)))), 107 (LOAD_F32 tglobaladdr:$off, $addr, 0)>; 108 def : Pat<(f64 (load (regPlusGA I32:$addr, 109 (WebAssemblywrapper tglobaladdr:$off)))), 110 (LOAD_F64 tglobaladdr:$off, $addr, 0)>; 111 def : Pat<(i32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 112 (LOAD_I32 texternalsym:$off, $addr, 0)>; 113 def : Pat<(i64 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 114 (LOAD_I64 texternalsym:$off, $addr, 0)>; 115 def : Pat<(f32 (load (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 116 (LOAD_F32 texternalsym:$off, $addr, 0)>; 117 def : 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. 121 def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0), 0)>; 122 def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0), 0)>; 123 def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0), 0)>; 124 def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0), 0)>; 125 def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))), 126 (LOAD_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 127 def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))), 128 (LOAD_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 129 def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))), 130 (LOAD_F32 tglobaladdr:$off, (CONST_I32 0), 0)>; 131 def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))), 132 (LOAD_F64 tglobaladdr:$off, (CONST_I32 0), 0)>; 133 def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))), 134 (LOAD_I32 texternalsym:$off, (CONST_I32 0), 0)>; 135 def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))), 136 (LOAD_I64 texternalsym:$off, (CONST_I32 0), 0)>; 137 def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))), 138 (LOAD_F32 texternalsym:$off, (CONST_I32 0), 0)>; 139 def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))), 140 (LOAD_F64 texternalsym:$off, (CONST_I32 0), 0)>; 141 142 let Defs = [ARGUMENTS] in { 143 144 // Extending load. 145 def LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, 146 P2Align:$p2align), [], 147 "i32.load8_s\t$dst, ${off}(${addr})${p2align}">; 148 def LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, 149 P2Align:$p2align), [], 150 "i32.load8_u\t$dst, ${off}(${addr})${p2align}">; 151 def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, 152 P2Align:$p2align), [], 153 "i32.load16_s\t$dst, ${off}(${addr})${p2align}">; 154 def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, 155 P2Align:$p2align), [], 156 "i32.load16_u\t$dst, ${off}(${addr})${p2align}">; 157 def LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 158 P2Align:$p2align), [], 159 "i64.load8_s\t$dst, ${off}(${addr})${p2align}">; 160 def LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 161 P2Align:$p2align), [], 162 "i64.load8_u\t$dst, ${off}(${addr})${p2align}">; 163 def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 164 P2Align:$p2align), [], 165 "i64.load16_s\t$dst, ${off}(${addr})${p2align}">; 166 def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 167 P2Align:$p2align), [], 168 "i64.load16_u\t$dst, ${off}(${addr})${p2align}">; 169 def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, 170 P2Align:$p2align), [], 171 "i64.load32_s\t$dst, ${off}(${addr})${p2align}">; 172 def 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. 179 def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr, 0)>; 180 def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>; 181 def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr, 0)>; 182 def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>; 183 def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr, 0)>; 184 def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>; 185 def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr, 0)>; 186 def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>; 187 def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr, 0)>; 188 def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>; 189 190 // Select extending loads with a constant offset. 191 def : Pat<(i32 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), 192 (LOAD8_S_I32 imm:$off, $addr, 0)>; 193 def : Pat<(i32 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), 194 (LOAD8_U_I32 imm:$off, $addr, 0)>; 195 def : Pat<(i32 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), 196 (LOAD16_S_I32 imm:$off, $addr, 0)>; 197 def : Pat<(i32 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), 198 (LOAD16_U_I32 imm:$off, $addr, 0)>; 199 def : Pat<(i64 (sextloadi8 (regPlusImm I32:$addr, imm:$off))), 200 (LOAD8_S_I64 imm:$off, $addr, 0)>; 201 def : Pat<(i64 (zextloadi8 (regPlusImm I32:$addr, imm:$off))), 202 (LOAD8_U_I64 imm:$off, $addr, 0)>; 203 def : Pat<(i64 (sextloadi16 (regPlusImm I32:$addr, imm:$off))), 204 (LOAD16_S_I64 imm:$off, $addr, 0)>; 205 def : Pat<(i64 (zextloadi16 (regPlusImm I32:$addr, imm:$off))), 206 (LOAD16_U_I64 imm:$off, $addr, 0)>; 207 def : Pat<(i64 (sextloadi32 (regPlusImm I32:$addr, imm:$off))), 208 (LOAD32_S_I64 imm:$off, $addr, 0)>; 209 def : Pat<(i64 (zextloadi32 (regPlusImm I32:$addr, imm:$off))), 210 (LOAD32_U_I64 imm:$off, $addr, 0)>; 211 def : Pat<(i32 (sextloadi8 (or_is_add I32:$addr, imm:$off))), 212 (LOAD8_S_I32 imm:$off, $addr, 0)>; 213 def : Pat<(i32 (zextloadi8 (or_is_add I32:$addr, imm:$off))), 214 (LOAD8_U_I32 imm:$off, $addr, 0)>; 215 def : Pat<(i32 (sextloadi16 (or_is_add I32:$addr, imm:$off))), 216 (LOAD16_S_I32 imm:$off, $addr, 0)>; 217 def : Pat<(i32 (zextloadi16 (or_is_add I32:$addr, imm:$off))), 218 (LOAD16_U_I32 imm:$off, $addr, 0)>; 219 def : Pat<(i64 (sextloadi8 (or_is_add I32:$addr, imm:$off))), 220 (LOAD8_S_I64 imm:$off, $addr, 0)>; 221 def : Pat<(i64 (zextloadi8 (or_is_add I32:$addr, imm:$off))), 222 (LOAD8_U_I64 imm:$off, $addr, 0)>; 223 def : Pat<(i64 (sextloadi16 (or_is_add I32:$addr, imm:$off))), 224 (LOAD16_S_I64 imm:$off, $addr, 0)>; 225 def : Pat<(i64 (zextloadi16 (or_is_add I32:$addr, imm:$off))), 226 (LOAD16_U_I64 imm:$off, $addr, 0)>; 227 def : Pat<(i64 (sextloadi32 (or_is_add I32:$addr, imm:$off))), 228 (LOAD32_S_I64 imm:$off, $addr, 0)>; 229 def : Pat<(i64 (zextloadi32 (or_is_add I32:$addr, imm:$off))), 230 (LOAD32_U_I64 imm:$off, $addr, 0)>; 231 def : Pat<(i32 (sextloadi8 (regPlusGA I32:$addr, 232 (WebAssemblywrapper tglobaladdr:$off)))), 233 (LOAD8_S_I32 tglobaladdr:$off, $addr, 0)>; 234 def : Pat<(i32 (zextloadi8 (regPlusGA I32:$addr, 235 (WebAssemblywrapper tglobaladdr:$off)))), 236 (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>; 237 def : Pat<(i32 (sextloadi16 (regPlusGA I32:$addr, 238 (WebAssemblywrapper tglobaladdr:$off)))), 239 (LOAD16_S_I32 tglobaladdr:$off, $addr, 0)>; 240 def : Pat<(i32 (zextloadi16 (regPlusGA I32:$addr, 241 (WebAssemblywrapper tglobaladdr:$off)))), 242 (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>; 243 def : Pat<(i64 (sextloadi8 (regPlusGA I32:$addr, 244 (WebAssemblywrapper tglobaladdr:$off)))), 245 (LOAD8_S_I64 tglobaladdr:$off, $addr, 0)>; 246 def : Pat<(i64 (zextloadi8 (regPlusGA I32:$addr, 247 (WebAssemblywrapper tglobaladdr:$off)))), 248 (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>; 249 def : Pat<(i64 (sextloadi16 (regPlusGA I32:$addr, 250 (WebAssemblywrapper tglobaladdr:$off)))), 251 (LOAD16_S_I64 tglobaladdr:$off, $addr, 0)>; 252 def : Pat<(i64 (zextloadi16 (regPlusGA I32:$addr, 253 (WebAssemblywrapper tglobaladdr:$off)))), 254 (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>; 255 def : Pat<(i64 (sextloadi32 (regPlusGA I32:$addr, 256 (WebAssemblywrapper tglobaladdr:$off)))), 257 (LOAD32_S_I64 tglobaladdr:$off, $addr, 0)>; 258 def : Pat<(i64 (zextloadi32 (regPlusGA I32:$addr, 259 (WebAssemblywrapper tglobaladdr:$off)))), 260 (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>; 261 def : Pat<(i32 (sextloadi8 (add I32:$addr, 262 (WebAssemblywrapper texternalsym:$off)))), 263 (LOAD8_S_I32 texternalsym:$off, $addr, 0)>; 264 def : Pat<(i32 (zextloadi8 (add I32:$addr, 265 (WebAssemblywrapper texternalsym:$off)))), 266 (LOAD8_U_I32 texternalsym:$off, $addr, 0)>; 267 def : Pat<(i32 (sextloadi16 (add I32:$addr, 268 (WebAssemblywrapper texternalsym:$off)))), 269 (LOAD16_S_I32 texternalsym:$off, $addr, 0)>; 270 def : Pat<(i32 (zextloadi16 (add I32:$addr, 271 (WebAssemblywrapper texternalsym:$off)))), 272 (LOAD16_U_I32 texternalsym:$off, $addr, 0)>; 273 def : Pat<(i64 (sextloadi8 (add I32:$addr, 274 (WebAssemblywrapper texternalsym:$off)))), 275 (LOAD8_S_I64 texternalsym:$off, $addr, 0)>; 276 def : Pat<(i64 (zextloadi8 (add I32:$addr, 277 (WebAssemblywrapper texternalsym:$off)))), 278 (LOAD8_U_I64 texternalsym:$off, $addr, 0)>; 279 def : Pat<(i64 (sextloadi16 (add I32:$addr, 280 (WebAssemblywrapper texternalsym:$off)))), 281 (LOAD16_S_I64 texternalsym:$off, $addr, 0)>; 282 def : Pat<(i64 (zextloadi16 (add I32:$addr, 283 (WebAssemblywrapper texternalsym:$off)))), 284 (LOAD16_U_I64 texternalsym:$off, $addr, 0)>; 285 def : Pat<(i64 (sextloadi32 (add I32:$addr, 286 (WebAssemblywrapper texternalsym:$off)))), 287 (LOAD32_S_I64 texternalsym:$off, $addr, 0)>; 288 def : 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. 293 def : Pat<(i32 (sextloadi8 imm:$off)), 294 (LOAD8_S_I32 imm:$off, (CONST_I32 0), 0)>; 295 def : Pat<(i32 (zextloadi8 imm:$off)), 296 (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>; 297 def : Pat<(i32 (sextloadi16 imm:$off)), 298 (LOAD16_S_I32 imm:$off, (CONST_I32 0), 0)>; 299 def : Pat<(i32 (zextloadi16 imm:$off)), 300 (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>; 301 def : Pat<(i64 (sextloadi8 imm:$off)), 302 (LOAD8_S_I64 imm:$off, (CONST_I32 0), 0)>; 303 def : Pat<(i64 (zextloadi8 imm:$off)), 304 (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>; 305 def : Pat<(i64 (sextloadi16 imm:$off)), 306 (LOAD16_S_I64 imm:$off, (CONST_I32 0), 0)>; 307 def : Pat<(i64 (zextloadi16 imm:$off)), 308 (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>; 309 def : Pat<(i64 (sextloadi32 imm:$off)), 310 (LOAD32_S_I64 imm:$off, (CONST_I32 0), 0)>; 311 def : Pat<(i64 (zextloadi32 imm:$off)), 312 (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>; 313 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 314 (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 315 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 316 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 317 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 318 (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 319 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 320 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 321 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 322 (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 323 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 324 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 325 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 326 (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 327 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 328 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 329 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 330 (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 331 def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 332 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 333 def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 334 (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0), 0)>; 335 def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 336 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; 337 def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 338 (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0), 0)>; 339 def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 340 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; 341 def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 342 (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; 343 def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 344 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; 345 def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 346 (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; 347 def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 348 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; 349 def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))), 350 (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0), 0)>; 351 def : 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. 358 def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr, 0)>; 359 def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr, 0)>; 360 def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr, 0)>; 361 def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr, 0)>; 362 def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr, 0)>; 363 364 // Select "don't care" extending loads with a constant offset. 365 def : Pat<(i32 (extloadi8 (regPlusImm I32:$addr, imm:$off))), 366 (LOAD8_U_I32 imm:$off, $addr, 0)>; 367 def : Pat<(i32 (extloadi16 (regPlusImm I32:$addr, imm:$off))), 368 (LOAD16_U_I32 imm:$off, $addr, 0)>; 369 def : Pat<(i64 (extloadi8 (regPlusImm I32:$addr, imm:$off))), 370 (LOAD8_U_I64 imm:$off, $addr, 0)>; 371 def : Pat<(i64 (extloadi16 (regPlusImm I32:$addr, imm:$off))), 372 (LOAD16_U_I64 imm:$off, $addr, 0)>; 373 def : Pat<(i64 (extloadi32 (regPlusImm I32:$addr, imm:$off))), 374 (LOAD32_U_I64 imm:$off, $addr, 0)>; 375 def : Pat<(i32 (extloadi8 (or_is_add I32:$addr, imm:$off))), 376 (LOAD8_U_I32 imm:$off, $addr, 0)>; 377 def : Pat<(i32 (extloadi16 (or_is_add I32:$addr, imm:$off))), 378 (LOAD16_U_I32 imm:$off, $addr, 0)>; 379 def : Pat<(i64 (extloadi8 (or_is_add I32:$addr, imm:$off))), 380 (LOAD8_U_I64 imm:$off, $addr, 0)>; 381 def : Pat<(i64 (extloadi16 (or_is_add I32:$addr, imm:$off))), 382 (LOAD16_U_I64 imm:$off, $addr, 0)>; 383 def : Pat<(i64 (extloadi32 (or_is_add I32:$addr, imm:$off))), 384 (LOAD32_U_I64 imm:$off, $addr, 0)>; 385 def : Pat<(i32 (extloadi8 (regPlusGA I32:$addr, 386 (WebAssemblywrapper tglobaladdr:$off)))), 387 (LOAD8_U_I32 tglobaladdr:$off, $addr, 0)>; 388 def : Pat<(i32 (extloadi16 (regPlusGA I32:$addr, 389 (WebAssemblywrapper tglobaladdr:$off)))), 390 (LOAD16_U_I32 tglobaladdr:$off, $addr, 0)>; 391 def : Pat<(i64 (extloadi8 (regPlusGA I32:$addr, 392 (WebAssemblywrapper tglobaladdr:$off)))), 393 (LOAD8_U_I64 tglobaladdr:$off, $addr, 0)>; 394 def : Pat<(i64 (extloadi16 (regPlusGA I32:$addr, 395 (WebAssemblywrapper tglobaladdr:$off)))), 396 (LOAD16_U_I64 tglobaladdr:$off, $addr, 0)>; 397 def : Pat<(i64 (extloadi32 (regPlusGA I32:$addr, 398 (WebAssemblywrapper tglobaladdr:$off)))), 399 (LOAD32_U_I64 tglobaladdr:$off, $addr, 0)>; 400 def : Pat<(i32 (extloadi8 (add I32:$addr, 401 (WebAssemblywrapper texternalsym:$off)))), 402 (LOAD8_U_I32 texternalsym:$off, $addr, 0)>; 403 def : Pat<(i32 (extloadi16 (add I32:$addr, 404 (WebAssemblywrapper texternalsym:$off)))), 405 (LOAD16_U_I32 texternalsym:$off, $addr, 0)>; 406 def : Pat<(i64 (extloadi8 (add I32:$addr, 407 (WebAssemblywrapper texternalsym:$off)))), 408 (LOAD8_U_I64 texternalsym:$off, $addr, 0)>; 409 def : Pat<(i64 (extloadi16 (add I32:$addr, 410 (WebAssemblywrapper texternalsym:$off)))), 411 (LOAD16_U_I64 texternalsym:$off, $addr, 0)>; 412 def : 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. 417 def : Pat<(i32 (extloadi8 imm:$off)), 418 (LOAD8_U_I32 imm:$off, (CONST_I32 0), 0)>; 419 def : Pat<(i32 (extloadi16 imm:$off)), 420 (LOAD16_U_I32 imm:$off, (CONST_I32 0), 0)>; 421 def : Pat<(i64 (extloadi8 imm:$off)), 422 (LOAD8_U_I64 imm:$off, (CONST_I32 0), 0)>; 423 def : Pat<(i64 (extloadi16 imm:$off)), 424 (LOAD16_U_I64 imm:$off, (CONST_I32 0), 0)>; 425 def : Pat<(i64 (extloadi32 imm:$off)), 426 (LOAD32_U_I64 imm:$off, (CONST_I32 0), 0)>; 427 def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 428 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 429 def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 430 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0), 0)>; 431 def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 432 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 433 def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 434 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 435 def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))), 436 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 437 def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 438 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; 439 def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 440 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0), 0)>; 441 def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 442 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; 443 def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 444 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0), 0)>; 445 def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))), 446 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0), 0)>; 447 448 let 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. 456 def 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">; 459 def 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">; 462 def 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">; 465 def 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. 472 def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, 0, I32:$val)>; 473 def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, 0, I64:$val)>; 474 def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, 0, F32:$val)>; 475 def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, 0, F64:$val)>; 476 477 // Select stores with a constant offset. 478 def : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)), 479 (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>; 480 def : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)), 481 (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>; 482 def : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)), 483 (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>; 484 def : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)), 485 (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>; 486 def : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)), 487 (STORE_I32 imm:$off, I32:$addr, 0, I32:$val)>; 488 def : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)), 489 (STORE_I64 imm:$off, I32:$addr, 0, I64:$val)>; 490 def : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)), 491 (STORE_F32 imm:$off, I32:$addr, 0, F32:$val)>; 492 def : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)), 493 (STORE_F64 imm:$off, I32:$addr, 0, F64:$val)>; 494 def : Pat<(store I32:$val, (regPlusGA I32:$addr, 495 (WebAssemblywrapper tglobaladdr:$off))), 496 (STORE_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; 497 def : Pat<(store I64:$val, (regPlusGA I32:$addr, 498 (WebAssemblywrapper tglobaladdr:$off))), 499 (STORE_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; 500 def : Pat<(store F32:$val, (regPlusGA I32:$addr, 501 (WebAssemblywrapper tglobaladdr:$off))), 502 (STORE_F32 tglobaladdr:$off, I32:$addr, 0, F32:$val)>; 503 def : Pat<(store F64:$val, (regPlusGA I32:$addr, 504 (WebAssemblywrapper tglobaladdr:$off))), 505 (STORE_F64 tglobaladdr:$off, I32:$addr, 0, F64:$val)>; 506 def : Pat<(store I32:$val, (add I32:$addr, 507 (WebAssemblywrapper texternalsym:$off))), 508 (STORE_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; 509 def : Pat<(store I64:$val, (add I32:$addr, 510 (WebAssemblywrapper texternalsym:$off))), 511 (STORE_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; 512 def : Pat<(store F32:$val, (add I32:$addr, 513 (WebAssemblywrapper texternalsym:$off))), 514 (STORE_F32 texternalsym:$off, I32:$addr, 0, F32:$val)>; 515 def : 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. 520 def : Pat<(store I32:$val, imm:$off), 521 (STORE_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; 522 def : Pat<(store I64:$val, imm:$off), 523 (STORE_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; 524 def : Pat<(store F32:$val, imm:$off), 525 (STORE_F32 imm:$off, (CONST_I32 0), 0, F32:$val)>; 526 def : Pat<(store F64:$val, imm:$off), 527 (STORE_F64 imm:$off, (CONST_I32 0), 0, F64:$val)>; 528 def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 529 (STORE_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; 530 def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 531 (STORE_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; 532 def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)), 533 (STORE_F32 tglobaladdr:$off, (CONST_I32 0), 0, F32:$val)>; 534 def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)), 535 (STORE_F64 tglobaladdr:$off, (CONST_I32 0), 0, F64:$val)>; 536 def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)), 537 (STORE_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; 538 def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)), 539 (STORE_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; 540 def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)), 541 (STORE_F32 texternalsym:$off, (CONST_I32 0), 0, F32:$val)>; 542 def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), 543 (STORE_F64 texternalsym:$off, (CONST_I32 0), 0, F64:$val)>; 544 545 let Defs = [ARGUMENTS] in { 546 547 // Truncating store. 548 def 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">; 551 def 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">; 554 def 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">; 557 def 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">; 560 def 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. 567 def : Pat<(truncstorei8 I32:$val, I32:$addr), 568 (STORE8_I32 0, I32:$addr, 0, I32:$val)>; 569 def : Pat<(truncstorei16 I32:$val, I32:$addr), 570 (STORE16_I32 0, I32:$addr, 0, I32:$val)>; 571 def : Pat<(truncstorei8 I64:$val, I32:$addr), 572 (STORE8_I64 0, I32:$addr, 0, I64:$val)>; 573 def : Pat<(truncstorei16 I64:$val, I32:$addr), 574 (STORE16_I64 0, I32:$addr, 0, I64:$val)>; 575 def : Pat<(truncstorei32 I64:$val, I32:$addr), 576 (STORE32_I64 0, I32:$addr, 0, I64:$val)>; 577 578 // Select truncating stores with a constant offset. 579 def : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)), 580 (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>; 581 def : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)), 582 (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>; 583 def : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)), 584 (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>; 585 def : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)), 586 (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>; 587 def : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)), 588 (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>; 589 def : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)), 590 (STORE8_I32 imm:$off, I32:$addr, 0, I32:$val)>; 591 def : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)), 592 (STORE16_I32 imm:$off, I32:$addr, 0, I32:$val)>; 593 def : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)), 594 (STORE8_I64 imm:$off, I32:$addr, 0, I64:$val)>; 595 def : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)), 596 (STORE16_I64 imm:$off, I32:$addr, 0, I64:$val)>; 597 def : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)), 598 (STORE32_I64 imm:$off, I32:$addr, 0, I64:$val)>; 599 def : Pat<(truncstorei8 I32:$val, 600 (regPlusGA I32:$addr, 601 (WebAssemblywrapper tglobaladdr:$off))), 602 (STORE8_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; 603 def : Pat<(truncstorei16 I32:$val, 604 (regPlusGA I32:$addr, 605 (WebAssemblywrapper tglobaladdr:$off))), 606 (STORE16_I32 tglobaladdr:$off, I32:$addr, 0, I32:$val)>; 607 def : Pat<(truncstorei8 I64:$val, 608 (regPlusGA I32:$addr, 609 (WebAssemblywrapper tglobaladdr:$off))), 610 (STORE8_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; 611 def : Pat<(truncstorei16 I64:$val, 612 (regPlusGA I32:$addr, 613 (WebAssemblywrapper tglobaladdr:$off))), 614 (STORE16_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; 615 def : Pat<(truncstorei32 I64:$val, 616 (regPlusGA I32:$addr, 617 (WebAssemblywrapper tglobaladdr:$off))), 618 (STORE32_I64 tglobaladdr:$off, I32:$addr, 0, I64:$val)>; 619 def : Pat<(truncstorei8 I32:$val, (add I32:$addr, 620 (WebAssemblywrapper texternalsym:$off))), 621 (STORE8_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; 622 def : Pat<(truncstorei16 I32:$val, 623 (add I32:$addr, 624 (WebAssemblywrapper texternalsym:$off))), 625 (STORE16_I32 texternalsym:$off, I32:$addr, 0, I32:$val)>; 626 def : Pat<(truncstorei8 I64:$val, 627 (add I32:$addr, 628 (WebAssemblywrapper texternalsym:$off))), 629 (STORE8_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; 630 def : Pat<(truncstorei16 I64:$val, 631 (add I32:$addr, 632 (WebAssemblywrapper texternalsym:$off))), 633 (STORE16_I64 texternalsym:$off, I32:$addr, 0, I64:$val)>; 634 def : 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. 640 def : Pat<(truncstorei8 I32:$val, imm:$off), 641 (STORE8_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; 642 def : Pat<(truncstorei16 I32:$val, imm:$off), 643 (STORE16_I32 imm:$off, (CONST_I32 0), 0, I32:$val)>; 644 def : Pat<(truncstorei8 I64:$val, imm:$off), 645 (STORE8_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; 646 def : Pat<(truncstorei16 I64:$val, imm:$off), 647 (STORE16_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; 648 def : Pat<(truncstorei32 I64:$val, imm:$off), 649 (STORE32_I64 imm:$off, (CONST_I32 0), 0, I64:$val)>; 650 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 651 (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; 652 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 653 (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), 0, I32:$val)>; 654 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 655 (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; 656 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 657 (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; 658 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 659 (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), 0, I64:$val)>; 660 def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)), 661 (STORE8_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; 662 def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)), 663 (STORE16_I32 texternalsym:$off, (CONST_I32 0), 0, I32:$val)>; 664 def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)), 665 (STORE8_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; 666 def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)), 667 (STORE16_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; 668 def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)), 669 (STORE32_I64 texternalsym:$off, (CONST_I32 0), 0, I64:$val)>; 670 671 let Defs = [ARGUMENTS] in { 672 673 // Current memory size. 674 def CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins), 675 [(set I32:$dst, (int_wasm_current_memory))], 676 "current_memory\t$dst">, 677 Requires<[HasAddr32]>; 678 def 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. 684 def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta), 685 [(int_wasm_grow_memory I32:$delta)], 686 "grow_memory\t$delta">, 687 Requires<[HasAddr32]>; 688 def 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