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