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