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:$off, node:$addr), 28 (add node:$addr, node:$off), 29 [{ return N->getFlags()->hasNoUnsignedWrap(); }]>; 30 31let Defs = [ARGUMENTS] in { 32 33// Basic load. 34def LOAD_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 35 "i32.load\t$dst, ${off}(${addr})">; 36def LOAD_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 37 "i64.load\t$dst, ${off}(${addr})">; 38def LOAD_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr), [], 39 "f32.load\t$dst, ${off}(${addr})">; 40def LOAD_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr), [], 41 "f64.load\t$dst, ${off}(${addr})">; 42 43} // Defs = [ARGUMENTS] 44 45// Select loads with no constant offset. 46def : Pat<(i32 (load I32:$addr)), (LOAD_I32 0, $addr)>; 47def : Pat<(i64 (load I32:$addr)), (LOAD_I64 0, $addr)>; 48def : Pat<(f32 (load I32:$addr)), (LOAD_F32 0, $addr)>; 49def : Pat<(f64 (load I32:$addr)), (LOAD_F64 0, $addr)>; 50 51// Select loads with a constant offset. 52def : Pat<(i32 (load (regPlusImm imm:$off, I32:$addr))), 53 (LOAD_I32 imm:$off, $addr)>; 54def : Pat<(i64 (load (regPlusImm imm:$off, I32:$addr))), 55 (LOAD_I64 imm:$off, $addr)>; 56def : Pat<(f32 (load (regPlusImm imm:$off, I32:$addr))), 57 (LOAD_F32 imm:$off, $addr)>; 58def : Pat<(f64 (load (regPlusImm imm:$off, I32:$addr))), 59 (LOAD_F64 imm:$off, $addr)>; 60def : Pat<(i32 (load (regPlusImm tglobaladdr:$off, I32:$addr))), 61 (LOAD_I32 tglobaladdr:$off, $addr)>; 62def : Pat<(i64 (load (regPlusImm tglobaladdr:$off, I32:$addr))), 63 (LOAD_I64 tglobaladdr:$off, $addr)>; 64def : Pat<(f32 (load (regPlusImm tglobaladdr:$off, I32:$addr))), 65 (LOAD_F32 tglobaladdr:$off, $addr)>; 66def : Pat<(f64 (load (regPlusImm tglobaladdr:$off, I32:$addr))), 67 (LOAD_F64 tglobaladdr:$off, $addr)>; 68def : Pat<(i32 (load (regPlusImm texternalsym:$off, I32:$addr))), 69 (LOAD_I32 texternalsym:$off, $addr)>; 70def : Pat<(i64 (load (regPlusImm texternalsym:$off, I32:$addr))), 71 (LOAD_I64 texternalsym:$off, $addr)>; 72def : Pat<(f32 (load (regPlusImm texternalsym:$off, I32:$addr))), 73 (LOAD_F32 texternalsym:$off, $addr)>; 74def : Pat<(f64 (load (regPlusImm texternalsym:$off, I32:$addr))), 75 (LOAD_F64 texternalsym:$off, $addr)>; 76 77// Select loads with just a constant offset. 78def : Pat<(i32 (load imm:$off)), (LOAD_I32 imm:$off, (CONST_I32 0))>; 79def : Pat<(i64 (load imm:$off)), (LOAD_I64 imm:$off, (CONST_I32 0))>; 80def : Pat<(f32 (load imm:$off)), (LOAD_F32 imm:$off, (CONST_I32 0))>; 81def : Pat<(f64 (load imm:$off)), (LOAD_F64 imm:$off, (CONST_I32 0))>; 82def : Pat<(i32 (load (WebAssemblywrapper tglobaladdr:$off))), 83 (LOAD_I32 tglobaladdr:$off, (CONST_I32 0))>; 84def : Pat<(i64 (load (WebAssemblywrapper tglobaladdr:$off))), 85 (LOAD_I64 tglobaladdr:$off, (CONST_I32 0))>; 86def : Pat<(f32 (load (WebAssemblywrapper tglobaladdr:$off))), 87 (LOAD_F32 tglobaladdr:$off, (CONST_I32 0))>; 88def : Pat<(f64 (load (WebAssemblywrapper tglobaladdr:$off))), 89 (LOAD_F64 tglobaladdr:$off, (CONST_I32 0))>; 90def : Pat<(i32 (load (WebAssemblywrapper texternalsym:$off))), 91 (LOAD_I32 texternalsym:$off, (CONST_I32 0))>; 92def : Pat<(i64 (load (WebAssemblywrapper texternalsym:$off))), 93 (LOAD_I64 texternalsym:$off, (CONST_I32 0))>; 94def : Pat<(f32 (load (WebAssemblywrapper texternalsym:$off))), 95 (LOAD_F32 texternalsym:$off, (CONST_I32 0))>; 96def : Pat<(f64 (load (WebAssemblywrapper texternalsym:$off))), 97 (LOAD_F64 texternalsym:$off, (CONST_I32 0))>; 98 99let Defs = [ARGUMENTS] in { 100 101// Extending load. 102def LOAD8_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 103 "i32.load8_s\t$dst, ${off}(${addr})">; 104def LOAD8_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 105 "i32.load8_u\t$dst, ${off}(${addr})">; 106def LOAD16_S_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 107 "i32.load16_s\t$dst, ${off}(${addr})">; 108def LOAD16_U_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr), [], 109 "i32.load16_u\t$dst, ${off}(${addr})">; 110def LOAD8_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 111 "i64.load8_s\t$dst, ${off}(${addr})">; 112def LOAD8_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 113 "i64.load8_u\t$dst, ${off}(${addr})">; 114def LOAD16_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 115 "i64.load16_s\t$dst, ${off}(${addr})">; 116def LOAD16_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 117 "i64.load16_u\t$dst, ${off}(${addr})">; 118def LOAD32_S_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 119 "i64.load32_s\t$dst, ${off}(${addr})">; 120def LOAD32_U_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr), [], 121 "i64.load32_u\t$dst, ${off}(${addr})">; 122 123} // Defs = [ARGUMENTS] 124 125// Select extending loads with no constant offset. 126def : Pat<(i32 (sextloadi8 I32:$addr)), (LOAD8_S_I32 0, $addr)>; 127def : Pat<(i32 (zextloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; 128def : Pat<(i32 (sextloadi16 I32:$addr)), (LOAD16_S_I32 0, $addr)>; 129def : Pat<(i32 (zextloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; 130def : Pat<(i64 (sextloadi8 I32:$addr)), (LOAD8_S_I64 0, $addr)>; 131def : Pat<(i64 (zextloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; 132def : Pat<(i64 (sextloadi16 I32:$addr)), (LOAD16_S_I64 0, $addr)>; 133def : Pat<(i64 (zextloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; 134def : Pat<(i64 (sextloadi32 I32:$addr)), (LOAD32_S_I64 0, $addr)>; 135def : Pat<(i64 (zextloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; 136 137// Select extending loads with a constant offset. 138def : Pat<(i32 (sextloadi8 (regPlusImm imm:$off, I32:$addr))), 139 (LOAD8_S_I32 imm:$off, $addr)>; 140def : Pat<(i32 (zextloadi8 (regPlusImm imm:$off, I32:$addr))), 141 (LOAD8_U_I32 imm:$off, $addr)>; 142def : Pat<(i32 (sextloadi16 (regPlusImm imm:$off, I32:$addr))), 143 (LOAD16_S_I32 imm:$off, $addr)>; 144def : Pat<(i32 (zextloadi16 (regPlusImm imm:$off, I32:$addr))), 145 (LOAD16_U_I32 imm:$off, $addr)>; 146def : Pat<(i64 (sextloadi8 (regPlusImm imm:$off, I32:$addr))), 147 (LOAD8_S_I64 imm:$off, $addr)>; 148def : Pat<(i64 (zextloadi8 (regPlusImm imm:$off, I32:$addr))), 149 (LOAD8_U_I64 imm:$off, $addr)>; 150def : Pat<(i64 (sextloadi16 (regPlusImm imm:$off, I32:$addr))), 151 (LOAD16_S_I64 imm:$off, $addr)>; 152def : Pat<(i64 (zextloadi16 (regPlusImm imm:$off, I32:$addr))), 153 (LOAD16_U_I64 imm:$off, $addr)>; 154def : Pat<(i64 (sextloadi32 (regPlusImm imm:$off, I32:$addr))), 155 (LOAD32_S_I64 imm:$off, $addr)>; 156def : Pat<(i64 (zextloadi32 (regPlusImm imm:$off, I32:$addr))), 157 (LOAD32_U_I64 imm:$off, $addr)>; 158def : Pat<(i32 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 159 (LOAD8_S_I32 tglobaladdr:$off, $addr)>; 160def : Pat<(i32 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 161 (LOAD8_U_I32 tglobaladdr:$off, $addr)>; 162def : Pat<(i32 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 163 (LOAD16_S_I32 tglobaladdr:$off, $addr)>; 164def : Pat<(i32 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 165 (LOAD16_U_I32 tglobaladdr:$off, $addr)>; 166def : Pat<(i64 (sextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 167 (LOAD8_S_I64 tglobaladdr:$off, $addr)>; 168def : Pat<(i64 (zextloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 169 (LOAD8_U_I64 tglobaladdr:$off, $addr)>; 170def : Pat<(i64 (sextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 171 (LOAD16_S_I64 tglobaladdr:$off, $addr)>; 172def : Pat<(i64 (zextloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 173 (LOAD16_U_I64 tglobaladdr:$off, $addr)>; 174def : Pat<(i64 (sextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))), 175 (LOAD32_S_I64 tglobaladdr:$off, $addr)>; 176def : Pat<(i64 (zextloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))), 177 (LOAD32_U_I64 tglobaladdr:$off, $addr)>; 178def : Pat<(i32 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 179 (LOAD8_S_I32 texternalsym:$off, $addr)>; 180def : Pat<(i32 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 181 (LOAD8_U_I32 texternalsym:$off, $addr)>; 182def : Pat<(i32 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 183 (LOAD16_S_I32 texternalsym:$off, $addr)>; 184def : Pat<(i32 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 185 (LOAD16_U_I32 texternalsym:$off, $addr)>; 186def : Pat<(i64 (sextloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 187 (LOAD8_S_I64 texternalsym:$off, $addr)>; 188def : Pat<(i64 (zextloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 189 (LOAD8_U_I64 texternalsym:$off, $addr)>; 190def : Pat<(i64 (sextloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 191 (LOAD16_S_I64 texternalsym:$off, $addr)>; 192def : Pat<(i64 (zextloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 193 (LOAD16_U_I64 texternalsym:$off, $addr)>; 194def : Pat<(i64 (sextloadi32 (regPlusImm texternalsym:$off, I32:$addr))), 195 (LOAD32_S_I64 texternalsym:$off, $addr)>; 196def : Pat<(i64 (zextloadi32 (regPlusImm texternalsym:$off, I32:$addr))), 197 (LOAD32_U_I64 texternalsym:$off, $addr)>; 198 199// Select extending loads with just a constant offset. 200def : Pat<(i32 (sextloadi8 imm:$off)), (LOAD8_S_I32 imm:$off, (CONST_I32 0))>; 201def : Pat<(i32 (zextloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; 202def : Pat<(i32 (sextloadi16 imm:$off)), (LOAD16_S_I32 imm:$off, (CONST_I32 0))>; 203def : Pat<(i32 (zextloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; 204def : Pat<(i64 (sextloadi8 imm:$off)), (LOAD8_S_I64 imm:$off, (CONST_I32 0))>; 205def : Pat<(i64 (zextloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; 206def : Pat<(i64 (sextloadi16 imm:$off)), (LOAD16_S_I64 imm:$off, (CONST_I32 0))>; 207def : Pat<(i64 (zextloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; 208def : Pat<(i64 (sextloadi32 imm:$off)), (LOAD32_S_I64 imm:$off, (CONST_I32 0))>; 209def : Pat<(i64 (zextloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; 210def : Pat<(i32 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 211 (LOAD8_S_I32 tglobaladdr:$off, (CONST_I32 0))>; 212def : Pat<(i32 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 213 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 214def : Pat<(i32 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 215 (LOAD16_S_I32 tglobaladdr:$off, (CONST_I32 0))>; 216def : Pat<(i32 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 217 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 218def : Pat<(i64 (sextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 219 (LOAD8_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 220def : Pat<(i64 (zextloadi8 (WebAssemblywrapper tglobaladdr:$off))), 221 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 222def : Pat<(i64 (sextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 223 (LOAD16_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 224def : Pat<(i64 (zextloadi16 (WebAssemblywrapper tglobaladdr:$off))), 225 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 226def : Pat<(i64 (sextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 227 (LOAD32_S_I64 tglobaladdr:$off, (CONST_I32 0))>; 228def : Pat<(i64 (zextloadi32 (WebAssemblywrapper tglobaladdr:$off))), 229 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 230def : Pat<(i32 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 231 (LOAD8_S_I32 texternalsym:$off, (CONST_I32 0))>; 232def : Pat<(i32 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 233 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; 234def : Pat<(i32 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 235 (LOAD16_S_I32 texternalsym:$off, (CONST_I32 0))>; 236def : Pat<(i32 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 237 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; 238def : Pat<(i64 (sextloadi8 (WebAssemblywrapper texternalsym:$off))), 239 (LOAD8_S_I64 texternalsym:$off, (CONST_I32 0))>; 240def : Pat<(i64 (zextloadi8 (WebAssemblywrapper texternalsym:$off))), 241 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; 242def : Pat<(i64 (sextloadi16 (WebAssemblywrapper texternalsym:$off))), 243 (LOAD16_S_I64 texternalsym:$off, (CONST_I32 0))>; 244def : Pat<(i64 (zextloadi16 (WebAssemblywrapper texternalsym:$off))), 245 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; 246def : Pat<(i64 (sextloadi32 (WebAssemblywrapper texternalsym:$off))), 247 (LOAD32_S_I64 texternalsym:$off, (CONST_I32 0))>; 248def : Pat<(i64 (zextloadi32 (WebAssemblywrapper texternalsym:$off))), 249 (LOAD32_U_I64 texternalsym:$off, (CONST_I32 0))>; 250 251// Resolve "don't care" extending loads to zero-extending loads. This is 252// somewhat arbitrary, but zero-extending is conceptually simpler. 253 254// Select "don't care" extending loads with no constant offset. 255def : Pat<(i32 (extloadi8 I32:$addr)), (LOAD8_U_I32 0, $addr)>; 256def : Pat<(i32 (extloadi16 I32:$addr)), (LOAD16_U_I32 0, $addr)>; 257def : Pat<(i64 (extloadi8 I32:$addr)), (LOAD8_U_I64 0, $addr)>; 258def : Pat<(i64 (extloadi16 I32:$addr)), (LOAD16_U_I64 0, $addr)>; 259def : Pat<(i64 (extloadi32 I32:$addr)), (LOAD32_U_I64 0, $addr)>; 260 261// Select "don't care" extending loads with a constant offset. 262def : Pat<(i32 (extloadi8 (regPlusImm imm:$off, I32:$addr))), 263 (LOAD8_U_I32 imm:$off, $addr)>; 264def : Pat<(i32 (extloadi16 (regPlusImm imm:$off, I32:$addr))), 265 (LOAD16_U_I32 imm:$off, $addr)>; 266def : Pat<(i64 (extloadi8 (regPlusImm imm:$off, I32:$addr))), 267 (LOAD8_U_I64 imm:$off, $addr)>; 268def : Pat<(i64 (extloadi16 (regPlusImm imm:$off, I32:$addr))), 269 (LOAD16_U_I64 imm:$off, $addr)>; 270def : Pat<(i64 (extloadi32 (regPlusImm imm:$off, I32:$addr))), 271 (LOAD32_U_I64 imm:$off, $addr)>; 272def : Pat<(i32 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 273 (LOAD8_U_I32 tglobaladdr:$off, $addr)>; 274def : Pat<(i32 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 275 (LOAD16_U_I32 tglobaladdr:$off, $addr)>; 276def : Pat<(i64 (extloadi8 (regPlusImm tglobaladdr:$off, I32:$addr))), 277 (LOAD8_U_I64 tglobaladdr:$off, $addr)>; 278def : Pat<(i64 (extloadi16 (regPlusImm tglobaladdr:$off, I32:$addr))), 279 (LOAD16_U_I64 tglobaladdr:$off, $addr)>; 280def : Pat<(i64 (extloadi32 (regPlusImm tglobaladdr:$off, I32:$addr))), 281 (LOAD32_U_I64 tglobaladdr:$off, $addr)>; 282def : Pat<(i32 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 283 (LOAD8_U_I32 texternalsym:$off, $addr)>; 284def : Pat<(i32 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 285 (LOAD16_U_I32 texternalsym:$off, $addr)>; 286def : Pat<(i64 (extloadi8 (regPlusImm texternalsym:$off, I32:$addr))), 287 (LOAD8_U_I64 texternalsym:$off, $addr)>; 288def : Pat<(i64 (extloadi16 (regPlusImm texternalsym:$off, I32:$addr))), 289 (LOAD16_U_I64 texternalsym:$off, $addr)>; 290def : Pat<(i64 (extloadi32 (regPlusImm texternalsym:$off, I32:$addr))), 291 (LOAD32_U_I64 texternalsym:$off, $addr)>; 292 293// Select "don't care" extending loads with just a constant offset. 294def : Pat<(i32 (extloadi8 imm:$off)), (LOAD8_U_I32 imm:$off, (CONST_I32 0))>; 295def : Pat<(i32 (extloadi16 imm:$off)), (LOAD16_U_I32 imm:$off, (CONST_I32 0))>; 296def : Pat<(i64 (extloadi8 imm:$off)), (LOAD8_U_I64 imm:$off, (CONST_I32 0))>; 297def : Pat<(i64 (extloadi16 imm:$off)), (LOAD16_U_I64 imm:$off, (CONST_I32 0))>; 298def : Pat<(i64 (extloadi32 imm:$off)), (LOAD32_U_I64 imm:$off, (CONST_I32 0))>; 299def : Pat<(i32 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 300 (LOAD8_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 301def : Pat<(i32 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 302 (LOAD16_U_I32 tglobaladdr:$off, (CONST_I32 0))>; 303def : Pat<(i64 (extloadi8 (WebAssemblywrapper tglobaladdr:$off))), 304 (LOAD8_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 305def : Pat<(i64 (extloadi16 (WebAssemblywrapper tglobaladdr:$off))), 306 (LOAD16_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 307def : Pat<(i64 (extloadi32 (WebAssemblywrapper tglobaladdr:$off))), 308 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 309def : Pat<(i32 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 310 (LOAD8_U_I32 texternalsym:$off, (CONST_I32 0))>; 311def : Pat<(i32 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 312 (LOAD16_U_I32 texternalsym:$off, (CONST_I32 0))>; 313def : Pat<(i64 (extloadi8 (WebAssemblywrapper texternalsym:$off))), 314 (LOAD8_U_I64 texternalsym:$off, (CONST_I32 0))>; 315def : Pat<(i64 (extloadi16 (WebAssemblywrapper texternalsym:$off))), 316 (LOAD16_U_I64 texternalsym:$off, (CONST_I32 0))>; 317def : Pat<(i64 (extloadi32 (WebAssemblywrapper texternalsym:$off))), 318 (LOAD32_U_I64 tglobaladdr:$off, (CONST_I32 0))>; 319 320let Defs = [ARGUMENTS] in { 321 322// Basic store. 323// Note that we split the patterns out of the instruction definitions because 324// WebAssembly's stores return their operand value, and tablegen doesn't like 325// instruction definition patterns that don't reference all of the output 326// operands. 327// Note: WebAssembly inverts SelectionDAG's usual operand order. 328def STORE_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 329 "i32.store\t$dst, ${off}(${addr}), $val">; 330def STORE_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 331 "i64.store\t$dst, ${off}(${addr}), $val">; 332def STORE_F32 : I<(outs F32:$dst), (ins i32imm:$off, I32:$addr, F32:$val), [], 333 "f32.store\t$dst, ${off}(${addr}), $val">; 334def STORE_F64 : I<(outs F64:$dst), (ins i32imm:$off, I32:$addr, F64:$val), [], 335 "f64.store\t$dst, ${off}(${addr}), $val">; 336 337} // Defs = [ARGUMENTS] 338 339// Select stores with no constant offset. 340def : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, I32:$addr, I32:$val)>; 341def : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, I32:$addr, I64:$val)>; 342def : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, I32:$addr, F32:$val)>; 343def : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, I32:$addr, F64:$val)>; 344 345// Select stores with a constant offset. 346def : Pat<(store I32:$val, (regPlusImm imm:$off, I32:$addr)), 347 (STORE_I32 imm:$off, I32:$addr, I32:$val)>; 348def : Pat<(store I64:$val, (regPlusImm imm:$off, I32:$addr)), 349 (STORE_I64 imm:$off, I32:$addr, I64:$val)>; 350def : Pat<(store F32:$val, (regPlusImm imm:$off, I32:$addr)), 351 (STORE_F32 imm:$off, I32:$addr, F32:$val)>; 352def : Pat<(store F64:$val, (regPlusImm imm:$off, I32:$addr)), 353 (STORE_F64 imm:$off, I32:$addr, F64:$val)>; 354def : Pat<(store I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 355 (STORE_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 356def : Pat<(store I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 357 (STORE_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 358def : Pat<(store F32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 359 (STORE_F32 tglobaladdr:$off, I32:$addr, F32:$val)>; 360def : Pat<(store F64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 361 (STORE_F64 tglobaladdr:$off, I32:$addr, F64:$val)>; 362def : Pat<(store I32:$val, (regPlusImm texternalsym:$off, I32:$addr)), 363 (STORE_I32 texternalsym:$off, I32:$addr, I32:$val)>; 364def : Pat<(store I64:$val, (regPlusImm texternalsym:$off, I32:$addr)), 365 (STORE_I64 texternalsym:$off, I32:$addr, I64:$val)>; 366def : Pat<(store F32:$val, (regPlusImm texternalsym:$off, I32:$addr)), 367 (STORE_F32 texternalsym:$off, I32:$addr, F32:$val)>; 368def : Pat<(store F64:$val, (regPlusImm texternalsym:$off, I32:$addr)), 369 (STORE_F64 texternalsym:$off, I32:$addr, F64:$val)>; 370 371// Select stores with just a constant offset. 372def : Pat<(store I32:$val, imm:$off), 373 (STORE_I32 imm:$off, (CONST_I32 0), I32:$val)>; 374def : Pat<(store I64:$val, imm:$off), 375 (STORE_I64 imm:$off, (CONST_I32 0), I64:$val)>; 376def : Pat<(store F32:$val, imm:$off), 377 (STORE_F32 imm:$off, (CONST_I32 0), F32:$val)>; 378def : Pat<(store F64:$val, imm:$off), 379 (STORE_F64 imm:$off, (CONST_I32 0), F64:$val)>; 380def : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 381 (STORE_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 382def : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 383 (STORE_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 384def : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)), 385 (STORE_F32 tglobaladdr:$off, (CONST_I32 0), F32:$val)>; 386def : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)), 387 (STORE_F64 tglobaladdr:$off, (CONST_I32 0), F64:$val)>; 388def : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)), 389 (STORE_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 390def : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)), 391 (STORE_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 392def : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)), 393 (STORE_F32 texternalsym:$off, (CONST_I32 0), F32:$val)>; 394def : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), 395 (STORE_F64 texternalsym:$off, (CONST_I32 0), F64:$val)>; 396 397let Defs = [ARGUMENTS] in { 398 399// Truncating store. 400def STORE8_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 401 "i32.store8\t$dst, ${off}(${addr}), $val">; 402def STORE16_I32 : I<(outs I32:$dst), (ins i32imm:$off, I32:$addr, I32:$val), [], 403 "i32.store16\t$dst, ${off}(${addr}), $val">; 404def STORE8_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 405 "i64.store8\t$dst, ${off}(${addr}), $val">; 406def STORE16_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 407 "i64.store16\t$dst, ${off}(${addr}), $val">; 408def STORE32_I64 : I<(outs I64:$dst), (ins i32imm:$off, I32:$addr, I64:$val), [], 409 "i64.store32\t$dst, ${off}(${addr}), $val">; 410 411} // Defs = [ARGUMENTS] 412 413// Select truncating stores with no constant offset. 414def : Pat<(truncstorei8 I32:$val, I32:$addr), 415 (STORE8_I32 0, I32:$addr, I32:$val)>; 416def : Pat<(truncstorei16 I32:$val, I32:$addr), 417 (STORE16_I32 0, I32:$addr, I32:$val)>; 418def : Pat<(truncstorei8 I64:$val, I32:$addr), 419 (STORE8_I64 0, I32:$addr, I64:$val)>; 420def : Pat<(truncstorei16 I64:$val, I32:$addr), 421 (STORE16_I64 0, I32:$addr, I64:$val)>; 422def : Pat<(truncstorei32 I64:$val, I32:$addr), 423 (STORE32_I64 0, I32:$addr, I64:$val)>; 424 425// Select truncating stores with a constant offset. 426def : Pat<(truncstorei8 I32:$val, (regPlusImm imm:$off, I32:$addr)), 427 (STORE8_I32 imm:$off, I32:$addr, I32:$val)>; 428def : Pat<(truncstorei16 I32:$val, (regPlusImm imm:$off, I32:$addr)), 429 (STORE16_I32 imm:$off, I32:$addr, I32:$val)>; 430def : Pat<(truncstorei8 I64:$val, (regPlusImm imm:$off, I32:$addr)), 431 (STORE8_I64 imm:$off, I32:$addr, I64:$val)>; 432def : Pat<(truncstorei16 I64:$val, (regPlusImm imm:$off, I32:$addr)), 433 (STORE16_I64 imm:$off, I32:$addr, I64:$val)>; 434def : Pat<(truncstorei32 I64:$val, (regPlusImm imm:$off, I32:$addr)), 435 (STORE32_I64 imm:$off, I32:$addr, I64:$val)>; 436def : Pat<(truncstorei8 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 437 (STORE8_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 438def : Pat<(truncstorei16 I32:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 439 (STORE16_I32 tglobaladdr:$off, I32:$addr, I32:$val)>; 440def : Pat<(truncstorei8 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 441 (STORE8_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 442def : Pat<(truncstorei16 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 443 (STORE16_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 444def : Pat<(truncstorei32 I64:$val, (regPlusImm tglobaladdr:$off, I32:$addr)), 445 (STORE32_I64 tglobaladdr:$off, I32:$addr, I64:$val)>; 446def : Pat<(truncstorei8 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)), 447 (STORE8_I32 texternalsym:$off, I32:$addr, I32:$val)>; 448def : Pat<(truncstorei16 I32:$val, (regPlusImm texternalsym:$off, I32:$addr)), 449 (STORE16_I32 texternalsym:$off, I32:$addr, I32:$val)>; 450def : Pat<(truncstorei8 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)), 451 (STORE8_I64 texternalsym:$off, I32:$addr, I64:$val)>; 452def : Pat<(truncstorei16 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)), 453 (STORE16_I64 texternalsym:$off, I32:$addr, I64:$val)>; 454def : Pat<(truncstorei32 I64:$val, (regPlusImm texternalsym:$off, I32:$addr)), 455 (STORE32_I64 texternalsym:$off, I32:$addr, I64:$val)>; 456 457// Select truncating stores with just a constant offset. 458def : Pat<(truncstorei8 I32:$val, imm:$off), 459 (STORE8_I32 imm:$off, (CONST_I32 0), I32:$val)>; 460def : Pat<(truncstorei16 I32:$val, imm:$off), 461 (STORE16_I32 imm:$off, (CONST_I32 0), I32:$val)>; 462def : Pat<(truncstorei8 I64:$val, imm:$off), 463 (STORE8_I64 imm:$off, (CONST_I32 0), I64:$val)>; 464def : Pat<(truncstorei16 I64:$val, imm:$off), 465 (STORE16_I64 imm:$off, (CONST_I32 0), I64:$val)>; 466def : Pat<(truncstorei32 I64:$val, imm:$off), 467 (STORE32_I64 imm:$off, (CONST_I32 0), I64:$val)>; 468def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 469 (STORE8_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 470def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 471 (STORE16_I32 tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 472def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 473 (STORE8_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 474def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 475 (STORE16_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 476def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 477 (STORE32_I64 tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 478def : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)), 479 (STORE8_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 480def : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)), 481 (STORE16_I32 texternalsym:$off, (CONST_I32 0), I32:$val)>; 482def : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)), 483 (STORE8_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 484def : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)), 485 (STORE16_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 486def : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)), 487 (STORE32_I64 texternalsym:$off, (CONST_I32 0), I64:$val)>; 488 489let Defs = [ARGUMENTS] in { 490 491// Memory size. 492def MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins), 493 [(set I32:$dst, (int_wasm_memory_size))], 494 "memory_size\t$dst">, 495 Requires<[HasAddr32]>; 496def MEMORY_SIZE_I64 : I<(outs I64:$dst), (ins), 497 [(set I64:$dst, (int_wasm_memory_size))], 498 "memory_size\t$dst">, 499 Requires<[HasAddr64]>; 500 501// Grow memory. 502def GROW_MEMORY_I32 : I<(outs), (ins I32:$delta), 503 [(int_wasm_grow_memory I32:$delta)], 504 "grow_memory\t$delta">, 505 Requires<[HasAddr32]>; 506def GROW_MEMORY_I64 : I<(outs), (ins I64:$delta), 507 [(int_wasm_grow_memory I64:$delta)], 508 "grow_memory\t$delta">, 509 Requires<[HasAddr64]>; 510 511} // Defs = [ARGUMENTS] 512