WebAssemblyInstrMemory.td revision 327952
1112918Sjeff// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*- 2144518Sdavidxu// 3144518Sdavidxu// The LLVM Compiler Infrastructure 4144518Sdavidxu// 5112918Sjeff// This file is distributed under the University of Illinois Open Source 6112918Sjeff// License. See LICENSE.TXT for details. 7112918Sjeff// 8112918Sjeff//===----------------------------------------------------------------------===// 9112918Sjeff/// 10112918Sjeff/// \file 11112918Sjeff/// \brief WebAssembly Memory operand code-gen constructs. 12112918Sjeff/// 13112918Sjeff//===----------------------------------------------------------------------===// 14112918Sjeff 15112918Sjeff// TODO: 16112918Sjeff// - HasAddr64 17112918Sjeff// - WebAssemblyTargetLowering having to do with atomics 18112918Sjeff// - Each has optional alignment. 19112918Sjeff 20112918Sjeff// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16 21112918Sjeff// local types. These memory-only types instead zero- or sign-extend into local 22112918Sjeff// types when loading, and truncate when storing. 23112918Sjeff 24112918Sjeff// WebAssembly constant offsets are performed as unsigned with infinite 25112918Sjeff// precision, so we need to check for NoUnsignedWrap so that we don't fold an 26112918Sjeff// offset for an add that needs wrapping. 27112918Sjeffdef regPlusImm : PatFrag<(ops node:$addr, node:$off), 28112918Sjeff (add node:$addr, node:$off), 29112918Sjeff [{ return N->getFlags().hasNoUnsignedWrap(); }]>; 30112918Sjeff 31112918Sjeff// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero. 32112918Sjeffdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ 33112918Sjeff if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1))) 34112918Sjeff return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); 35112918Sjeff 36112918Sjeff KnownBits Known0; 37112918Sjeff CurDAG->computeKnownBits(N->getOperand(0), Known0, 0); 38112918Sjeff KnownBits Known1; 39112918Sjeff CurDAG->computeKnownBits(N->getOperand(1), Known1, 0); 40112918Sjeff return (~Known0.Zero & ~Known1.Zero) == 0; 41112918Sjeff}]>; 42112918Sjeff 43112918Sjeff// GlobalAddresses are conceptually unsigned values, so we can also fold them 44112918Sjeff// into immediate values as long as the add is 'nuw'. 45112918Sjeff// TODO: We'd like to also match GA offsets but there are cases where the 46165967Simp// register can have a negative value. Find out what more we can do. 47112918Sjeffdef regPlusGA : PatFrag<(ops node:$addr, node:$off), 48112918Sjeff (add node:$addr, node:$off), 49112918Sjeff [{ 50112918Sjeff return N->getFlags().hasNoUnsignedWrap(); 51112918Sjeff}]>; 52112918Sjeff 53112918Sjeff// We don't need a regPlusES because external symbols never have constant 54112918Sjeff// offsets folded into them, so we can just use add. 55112918Sjeff 56112918Sjefflet Defs = [ARGUMENTS] in { 57112918Sjeff 58112918Sjeff// Defines atomic and non-atomic loads, regular and extending. 59112918Sjeffclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> : 60112918Sjeff I<(outs rc:$dst), 61112918Sjeff (ins P2Align:$p2align, offset32_op:$off, I32:$addr), 62112918Sjeff [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), Opcode>; 63112918Sjeff 64157457Sdavidxu// Basic load. 65144518Sdavidxu// FIXME: When we can break syntax compatibility, reorder the fields in the 66112918Sjeff// asmstrings to match the binary encoding. 67112918Sjeffdef LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>; 68112918Sjeffdef LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>; 69144518Sdavidxudef LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>; 70135301Smtmdef LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>; 71144518Sdavidxu 72112918Sjeff} // Defs = [ARGUMENTS] 73112918Sjeff 74112918Sjeff// Select loads with no constant offset. 75112918Sjeffclass LoadPatNoOffset<ValueType ty, PatFrag node, I inst> : 76112918Sjeff Pat<(ty (node I32:$addr)), (inst 0, 0, $addr)>; 77112918Sjeff 78112918Sjeffdef : LoadPatNoOffset<i32, load, LOAD_I32>; 79112918Sjeffdef : LoadPatNoOffset<i64, load, LOAD_I64>; 80112918Sjeffdef : LoadPatNoOffset<f32, load, LOAD_F32>; 81112918Sjeffdef : LoadPatNoOffset<f64, load, LOAD_F64>; 82112918Sjeff 83112918Sjeff 84112918Sjeff// Select loads with a constant offset. 85112918Sjeff 86112918Sjeff// Pattern with address + immediate offset 87144518Sdavidxuclass LoadPatImmOff<ValueType ty, PatFrag loadkind, PatFrag operand, I inst> : 88157457Sdavidxu Pat<(ty (loadkind (operand I32:$addr, imm:$off))), 89112918Sjeff (inst 0, imm:$off, $addr)>; 90112918Sjeff 91112918Sjeffdef : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>; 92157457Sdavidxudef : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>; 93157457Sdavidxudef : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>; 94157457Sdavidxudef : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>; 95157457Sdavidxudef : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>; 96157457Sdavidxudef : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>; 97157457Sdavidxudef : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>; 98157457Sdavidxudef : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>; 99157457Sdavidxu 100157457Sdavidxuclass LoadPatGlobalAddr<ValueType ty, PatFrag loadkind, I inst> : 101157457Sdavidxu Pat<(ty (loadkind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), 102157457Sdavidxu (inst 0, tglobaladdr:$off, $addr)>; 103157457Sdavidxu 104157457Sdavidxudef : LoadPatGlobalAddr<i32, load, LOAD_I32>; 105157457Sdavidxudef : LoadPatGlobalAddr<i64, load, LOAD_I64>; 106157457Sdavidxudef : LoadPatGlobalAddr<f32, load, LOAD_F32>; 107157457Sdavidxudef : LoadPatGlobalAddr<f64, load, LOAD_F64>; 108157457Sdavidxu 109157457Sdavidxuclass LoadPatExternalSym<ValueType ty, PatFrag loadkind, I inst> : 110157457Sdavidxu Pat<(ty (loadkind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 111157457Sdavidxu (inst 0, texternalsym:$off, $addr)>; 112157457Sdavidxudef : LoadPatExternalSym<i32, load, LOAD_I32>; 113157457Sdavidxudef : LoadPatExternalSym<i64, load, LOAD_I64>; 114157457Sdavidxudef : LoadPatExternalSym<f32, load, LOAD_F32>; 115157457Sdavidxudef : LoadPatExternalSym<f64, load, LOAD_F64>; 116157457Sdavidxu 117157457Sdavidxu 118157457Sdavidxu// Select loads with just a constant offset. 119115260Smtmclass LoadPatOffsetOnly<ValueType ty, PatFrag loadkind, I inst> : 120157457Sdavidxu Pat<(ty (loadkind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>; 121160662Sdavidxu 122160662Sdavidxudef : LoadPatOffsetOnly<i32, load, LOAD_I32>; 123160662Sdavidxudef : LoadPatOffsetOnly<i64, load, LOAD_I64>; 124160662Sdavidxudef : LoadPatOffsetOnly<f32, load, LOAD_F32>; 125160662Sdavidxudef : LoadPatOffsetOnly<f64, load, LOAD_F64>; 126160662Sdavidxu 127160662Sdavidxuclass LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag loadkind, I inst> : 128160662Sdavidxu Pat<(ty (loadkind (WebAssemblywrapper tglobaladdr:$off))), 129157457Sdavidxu (inst 0, tglobaladdr:$off, (CONST_I32 0))>; 130160662Sdavidxu 131160662Sdavidxudef : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>; 132157457Sdavidxudef : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>; 133157457Sdavidxudef : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>; 134157457Sdavidxudef : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>; 135189549Sdavidxu 136179434Sdfrclass LoadPatExternSymOffOnly<ValueType ty, PatFrag loadkind, I inst> : 137189549Sdavidxu Pat<(ty (loadkind (WebAssemblywrapper texternalsym:$off))), 138157457Sdavidxu (inst 0, texternalsym:$off, (CONST_I32 0))>; 139157457Sdavidxudef : LoadPatExternSymOffOnly<i32, load, LOAD_I32>; 140157457Sdavidxudef : LoadPatExternSymOffOnly<i64, load, LOAD_I64>; 141157457Sdavidxudef : LoadPatExternSymOffOnly<f32, load, LOAD_F32>; 142157457Sdavidxudef : LoadPatExternSymOffOnly<f64, load, LOAD_F64>; 143157457Sdavidxu 144157457Sdavidxulet Defs = [ARGUMENTS] in { 145157457Sdavidxu 146157457Sdavidxu// Extending load. 147157457Sdavidxudef LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>; 148157457Sdavidxudef LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>; 149157457Sdavidxudef LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>; 150157457Sdavidxudef LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>; 151160662Sdavidxudef LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>; 152157457Sdavidxudef LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>; 153157457Sdavidxudef LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>; 154157457Sdavidxudef LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x32>; 155157457Sdavidxudef LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>; 156144518Sdavidxudef LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>; 157157457Sdavidxu 158135301Smtm} // Defs = [ARGUMENTS] 159144518Sdavidxu 160135301Smtm// Select extending loads with no constant offset. 161144518Sdavidxudef : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>; 162135301Smtmdef : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>; 163135301Smtmdef : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>; 164144518Sdavidxudef : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>; 165164583Sdavidxudef : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>; 166135301Smtmdef : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>; 167164583Sdavidxudef : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>; 168144518Sdavidxudef : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>; 169144518Sdavidxudef : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>; 170135301Smtmdef : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>; 171135301Smtm 172160662Sdavidxu// Select extending loads with a constant offset. 173112918Sjeffdef : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>; 174112918Sjeffdef : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>; 175160662Sdavidxudef : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>; 176112918Sjeffdef : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>; 177112918Sjeffdef : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>; 178144518Sdavidxudef : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>; 179144518Sdavidxudef : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>; 180112918Sjeffdef : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>; 181164583Sdavidxudef : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>; 182112918Sjeffdef : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>; 183164583Sdavidxu 184112918Sjeffdef : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>; 185144518Sdavidxudef : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>; 186112918Sjeffdef : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>; 187112918Sjeffdef : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>; 188144518Sdavidxudef : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>; 189112918Sjeffdef : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>; 190112918Sjeffdef : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>; 191144518Sdavidxudef : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>; 192112918Sjeffdef : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>; 193144518Sdavidxudef : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>; 194112918Sjeff 195112918Sjeffdef : LoadPatGlobalAddr<i32, sextloadi8, LOAD8_S_I32>; 196164583Sdavidxudef : LoadPatGlobalAddr<i32, zextloadi8, LOAD8_U_I32>; 197112918Sjeffdef : LoadPatGlobalAddr<i32, sextloadi16, LOAD16_S_I32>; 198164583Sdavidxudef : LoadPatGlobalAddr<i32, zextloadi8, LOAD16_U_I32>; 199112918Sjeff 200144518Sdavidxudef : LoadPatGlobalAddr<i64, sextloadi8, LOAD8_S_I64>; 201112918Sjeffdef : LoadPatGlobalAddr<i64, zextloadi8, LOAD8_U_I64>; 202135301Smtmdef : LoadPatGlobalAddr<i64, sextloadi16, LOAD16_S_I64>; 203144518Sdavidxudef : LoadPatGlobalAddr<i64, zextloadi16, LOAD16_U_I64>; 204135301Smtmdef : LoadPatGlobalAddr<i64, sextloadi32, LOAD32_S_I64>; 205135301Smtmdef : LoadPatGlobalAddr<i64, zextloadi32, LOAD32_U_I64>; 206144518Sdavidxu 207135301Smtmdef : LoadPatExternalSym<i32, sextloadi8, LOAD8_S_I32>; 208144518Sdavidxudef : LoadPatExternalSym<i32, zextloadi8, LOAD8_U_I32>; 209135301Smtmdef : LoadPatExternalSym<i32, sextloadi16, LOAD16_S_I32>; 210135301Smtmdef : LoadPatExternalSym<i32, zextloadi16, LOAD16_U_I32>; 211164583Sdavidxudef : LoadPatExternalSym<i64, sextloadi8, LOAD8_S_I64>; 212144518Sdavidxudef : LoadPatExternalSym<i64, zextloadi8, LOAD8_U_I64>; 213164583Sdavidxudef : LoadPatExternalSym<i64, sextloadi16, LOAD16_S_I64>; 214144518Sdavidxudef : LoadPatExternalSym<i64, zextloadi16, LOAD16_U_I64>; 215144518Sdavidxudef : LoadPatExternalSym<i64, sextloadi32, LOAD32_S_I64>; 216135301Smtmdef : LoadPatExternalSym<i64, zextloadi32, LOAD32_U_I64>; 217112918Sjeff 218144518Sdavidxu 219144518Sdavidxu// Select extending loads with just a constant offset. 220112918Sjeffdef : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>; 221144518Sdavidxudef : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>; 222112918Sjeffdef : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>; 223144518Sdavidxudef : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>; 224144518Sdavidxu 225112918Sjeffdef : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>; 226164583Sdavidxudef : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>; 227112918Sjeffdef : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>; 228164583Sdavidxudef : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>; 229112918Sjeffdef : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>; 230112918Sjeffdef : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>; 231112918Sjeff 232112918Sjeffdef : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>; 233144518Sdavidxudef : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>; 234112918Sjeffdef : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>; 235112918Sjeffdef : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>; 236144518Sdavidxudef : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>; 237112918Sjeffdef : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>; 238144518Sdavidxudef : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>; 239112918Sjeffdef : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>; 240112918Sjeffdef : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>; 241112918Sjeffdef : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>; 242164583Sdavidxu 243112918Sjeffdef : LoadPatExternSymOffOnly<i32, sextloadi8, LOAD8_S_I32>; 244112918Sjeffdef : LoadPatExternSymOffOnly<i32, zextloadi8, LOAD8_U_I32>; 245112918Sjeffdef : LoadPatExternSymOffOnly<i32, sextloadi16, LOAD16_S_I32>; 246144518Sdavidxudef : LoadPatExternSymOffOnly<i32, zextloadi16, LOAD16_U_I32>; 247144518Sdavidxudef : LoadPatExternSymOffOnly<i64, sextloadi8, LOAD8_S_I64>; 248144518Sdavidxudef : LoadPatExternSymOffOnly<i64, zextloadi8, LOAD8_U_I64>; 249144518Sdavidxudef : LoadPatExternSymOffOnly<i64, sextloadi16, LOAD16_S_I64>; 250144518Sdavidxudef : LoadPatExternSymOffOnly<i64, zextloadi16, LOAD16_U_I64>; 251144518Sdavidxudef : LoadPatExternSymOffOnly<i64, sextloadi32, LOAD32_S_I64>; 252144518Sdavidxudef : LoadPatExternSymOffOnly<i64, zextloadi32, LOAD32_U_I64>; 253144518Sdavidxu 254144518Sdavidxu// Resolve "don't care" extending loads to zero-extending loads. This is 255144518Sdavidxu// somewhat arbitrary, but zero-extending is conceptually simpler. 256144518Sdavidxu 257144518Sdavidxu// Select "don't care" extending loads with no constant offset. 258189549Sdavidxudef : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>; 259179434Sdfrdef : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>; 260189549Sdavidxudef : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>; 261189549Sdavidxudef : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>; 262189549Sdavidxudef : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>; 263112918Sjeff 264112918Sjeff// Select "don't care" extending loads with a constant offset. 265112918Sjeffdef : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>; 266164583Sdavidxudef : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>; 267112918Sjeffdef : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>; 268144518Sdavidxudef : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>; 269112918Sjeffdef : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>; 270112918Sjeffdef : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>; 271144518Sdavidxudef : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>; 272131181Smtmdef : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>; 273131181Smtmdef : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>; 274144518Sdavidxudef : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>; 275131181Smtmdef : LoadPatGlobalAddr<i32, extloadi8, LOAD8_U_I32>; 276144518Sdavidxudef : LoadPatGlobalAddr<i32, extloadi16, LOAD16_U_I32>; 277131181Smtmdef : LoadPatGlobalAddr<i64, extloadi8, LOAD8_U_I64>; 278131181Smtmdef : LoadPatGlobalAddr<i64, extloadi16, LOAD16_U_I64>; 279164583Sdavidxudef : LoadPatGlobalAddr<i64, extloadi32, LOAD32_U_I64>; 280112918Sjeffdef : LoadPatExternalSym<i32, extloadi8, LOAD8_U_I32>; 281164583Sdavidxudef : LoadPatExternalSym<i32, extloadi16, LOAD16_U_I32>; 282112918Sjeffdef : LoadPatExternalSym<i64, extloadi8, LOAD8_U_I64>; 283144518Sdavidxudef : LoadPatExternalSym<i64, extloadi16, LOAD16_U_I64>; 284112918Sjeffdef : LoadPatExternalSym<i64, extloadi32, LOAD32_U_I64>; 285112918Sjeff 286144518Sdavidxu// Select "don't care" extending loads with just a constant offset. 287135301Smtmdef : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>; 288135301Smtmdef : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>; 289144518Sdavidxudef : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>; 290135301Smtmdef : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>; 291144518Sdavidxudef : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>; 292112918Sjeffdef : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>; 293112918Sjeffdef : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>; 294164583Sdavidxudef : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>; 295112918Sjeffdef : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>; 296164583Sdavidxudef : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>; 297112918Sjeffdef : LoadPatExternSymOffOnly<i32, extloadi8, LOAD8_U_I32>; 298112918Sjeffdef : LoadPatExternSymOffOnly<i32, extloadi16, LOAD16_U_I32>; 299112918Sjeffdef : LoadPatExternSymOffOnly<i64, extloadi8, LOAD8_U_I64>; 300112918Sjeffdef : LoadPatExternSymOffOnly<i64, extloadi16, LOAD16_U_I64>; 301144518Sdavidxudef : LoadPatExternSymOffOnly<i64, extloadi32, LOAD32_U_I64>; 302112918Sjeff 303112918Sjeff 304144518Sdavidxulet Defs = [ARGUMENTS] in { 305144518Sdavidxu 306112918Sjeff// Basic store. 307144518Sdavidxu// Note: WebAssembly inverts SelectionDAG's usual operand order. 308144518Sdavidxudef STORE_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 309112918Sjeff I32:$val), [], 310164583Sdavidxu "i32.store\t${off}(${addr})${p2align}, $val", 0x36>; 311112918Sjeffdef STORE_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 312164583Sdavidxu I64:$val), [], 313112918Sjeff "i64.store\t${off}(${addr})${p2align}, $val", 0x37>; 314144518Sdavidxudef STORE_F32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 315112918Sjeff F32:$val), [], 316112918Sjeff "f32.store\t${off}(${addr})${p2align}, $val", 0x38>; 317144518Sdavidxudef STORE_F64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 318112918Sjeff F64:$val), [], 319112918Sjeff "f64.store\t${off}(${addr})${p2align}, $val", 0x39>; 320144518Sdavidxu 321112918Sjeff} // Defs = [ARGUMENTS] 322144518Sdavidxu 323112918Sjeff// Select stores with no constant offset. 324112918Sjeffdef : Pat<(store I32:$val, I32:$addr), (STORE_I32 0, 0, I32:$addr, I32:$val)>; 325112918Sjeffdef : Pat<(store I64:$val, I32:$addr), (STORE_I64 0, 0, I32:$addr, I64:$val)>; 326112918Sjeffdef : Pat<(store F32:$val, I32:$addr), (STORE_F32 0, 0, I32:$addr, F32:$val)>; 327164583Sdavidxudef : Pat<(store F64:$val, I32:$addr), (STORE_F64 0, 0, I32:$addr, F64:$val)>; 328112918Sjeff 329112918Sjeff// Select stores with a constant offset. 330112918Sjeffdef : Pat<(store I32:$val, (regPlusImm I32:$addr, imm:$off)), 331112918Sjeff (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>; 332112918Sjeffdef : Pat<(store I64:$val, (regPlusImm I32:$addr, imm:$off)), 333112918Sjeff (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>; 334112918Sjeffdef : Pat<(store F32:$val, (regPlusImm I32:$addr, imm:$off)), 335112918Sjeff (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>; 336112918Sjeffdef : Pat<(store F64:$val, (regPlusImm I32:$addr, imm:$off)), 337112918Sjeff (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>; 338112918Sjeffdef : Pat<(store I32:$val, (or_is_add I32:$addr, imm:$off)), 339164583Sdavidxu (STORE_I32 0, imm:$off, I32:$addr, I32:$val)>; 340144518Sdavidxudef : Pat<(store I64:$val, (or_is_add I32:$addr, imm:$off)), 341112918Sjeff (STORE_I64 0, imm:$off, I32:$addr, I64:$val)>; 342112918Sjeffdef : Pat<(store F32:$val, (or_is_add I32:$addr, imm:$off)), 343112918Sjeff (STORE_F32 0, imm:$off, I32:$addr, F32:$val)>; 344144518Sdavidxudef : Pat<(store F64:$val, (or_is_add I32:$addr, imm:$off)), 345112918Sjeff (STORE_F64 0, imm:$off, I32:$addr, F64:$val)>; 346112918Sjeffdef : Pat<(store I32:$val, (regPlusGA I32:$addr, 347144518Sdavidxu (WebAssemblywrapper tglobaladdr:$off))), 348112918Sjeff (STORE_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>; 349144518Sdavidxudef : Pat<(store I64:$val, (regPlusGA I32:$addr, 350112918Sjeff (WebAssemblywrapper tglobaladdr:$off))), 351112918Sjeff (STORE_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>; 352164583Sdavidxudef : Pat<(store F32:$val, (regPlusGA I32:$addr, 353112918Sjeff (WebAssemblywrapper tglobaladdr:$off))), 354164583Sdavidxu (STORE_F32 0, tglobaladdr:$off, I32:$addr, F32:$val)>; 355112918Sjeffdef : Pat<(store F64:$val, (regPlusGA I32:$addr, 356112918Sjeff (WebAssemblywrapper tglobaladdr:$off))), 357112918Sjeff (STORE_F64 0, tglobaladdr:$off, I32:$addr, F64:$val)>; 358112918Sjeffdef : Pat<(store I32:$val, (add I32:$addr, 359160662Sdavidxu (WebAssemblywrapper texternalsym:$off))), 360135301Smtm (STORE_I32 0, texternalsym:$off, I32:$addr, I32:$val)>; 361112918Sjeffdef : Pat<(store I64:$val, (add I32:$addr, 362160662Sdavidxu (WebAssemblywrapper texternalsym:$off))), 363112918Sjeff (STORE_I64 0, texternalsym:$off, I32:$addr, I64:$val)>; 364112918Sjeffdef : Pat<(store F32:$val, (add I32:$addr, 365144518Sdavidxu (WebAssemblywrapper texternalsym:$off))), 366112918Sjeff (STORE_F32 0, texternalsym:$off, I32:$addr, F32:$val)>; 367112918Sjeffdef : Pat<(store F64:$val, (add I32:$addr, 368164583Sdavidxu (WebAssemblywrapper texternalsym:$off))), 369112918Sjeff (STORE_F64 0, texternalsym:$off, I32:$addr, F64:$val)>; 370164583Sdavidxu 371112918Sjeff// Select stores with just a constant offset. 372112918Sjeffdef : Pat<(store I32:$val, imm:$off), 373112918Sjeff (STORE_I32 0, imm:$off, (CONST_I32 0), I32:$val)>; 374112918Sjeffdef : Pat<(store I64:$val, imm:$off), 375144518Sdavidxu (STORE_I64 0, imm:$off, (CONST_I32 0), I64:$val)>; 376112918Sjeffdef : Pat<(store F32:$val, imm:$off), 377112918Sjeff (STORE_F32 0, imm:$off, (CONST_I32 0), F32:$val)>; 378144518Sdavidxudef : Pat<(store F64:$val, imm:$off), 379112918Sjeff (STORE_F64 0, imm:$off, (CONST_I32 0), F64:$val)>; 380144518Sdavidxudef : Pat<(store I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 381112918Sjeff (STORE_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 382112918Sjeffdef : Pat<(store I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 383164583Sdavidxu (STORE_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 384112918Sjeffdef : Pat<(store F32:$val, (WebAssemblywrapper tglobaladdr:$off)), 385164583Sdavidxu (STORE_F32 0, tglobaladdr:$off, (CONST_I32 0), F32:$val)>; 386112918Sjeffdef : Pat<(store F64:$val, (WebAssemblywrapper tglobaladdr:$off)), 387112918Sjeff (STORE_F64 0, tglobaladdr:$off, (CONST_I32 0), F64:$val)>; 388112918Sjeffdef : Pat<(store I32:$val, (WebAssemblywrapper texternalsym:$off)), 389112918Sjeff (STORE_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>; 390144518Sdavidxudef : Pat<(store I64:$val, (WebAssemblywrapper texternalsym:$off)), 391112918Sjeff (STORE_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>; 392112918Sjeffdef : Pat<(store F32:$val, (WebAssemblywrapper texternalsym:$off)), 393144518Sdavidxu (STORE_F32 0, texternalsym:$off, (CONST_I32 0), F32:$val)>; 394112918Sjeffdef : Pat<(store F64:$val, (WebAssemblywrapper texternalsym:$off)), 395144518Sdavidxu (STORE_F64 0, texternalsym:$off, (CONST_I32 0), F64:$val)>; 396112918Sjeff 397112918Sjefflet Defs = [ARGUMENTS] in { 398164583Sdavidxu 399112918Sjeff// Truncating store. 400164583Sdavidxudef STORE8_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 401112918Sjeff I32:$val), [], 402112918Sjeff "i32.store8\t${off}(${addr})${p2align}, $val", 0x3a>; 403112918Sjeffdef STORE16_I32 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 404112918Sjeff I32:$val), [], 405144518Sdavidxu "i32.store16\t${off}(${addr})${p2align}, $val", 0x3b>; 406135301Smtmdef STORE8_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 407135301Smtm I64:$val), [], 408144518Sdavidxu "i64.store8\t${off}(${addr})${p2align}, $val", 0x3c>; 409135301Smtmdef STORE16_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 410135301Smtm I64:$val), [], 411144518Sdavidxu "i64.store16\t${off}(${addr})${p2align}, $val", 0x3d>; 412135301Smtmdef STORE32_I64 : I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, 413135301Smtm I64:$val), [], 414164583Sdavidxu "i64.store32\t${off}(${addr})${p2align}, $val", 0x3e>; 415135301Smtm 416164583Sdavidxu} // Defs = [ARGUMENTS] 417135301Smtm 418135301Smtm// Select truncating stores with no constant offset. 419135301Smtmdef : Pat<(truncstorei8 I32:$val, I32:$addr), 420144518Sdavidxu (STORE8_I32 0, 0, I32:$addr, I32:$val)>; 421135301Smtmdef : Pat<(truncstorei16 I32:$val, I32:$addr), 422135301Smtm (STORE16_I32 0, 0, I32:$addr, I32:$val)>; 423144518Sdavidxudef : Pat<(truncstorei8 I64:$val, I32:$addr), 424135301Smtm (STORE8_I64 0, 0, I32:$addr, I64:$val)>; 425144518Sdavidxudef : Pat<(truncstorei16 I64:$val, I32:$addr), 426135301Smtm (STORE16_I64 0, 0, I32:$addr, I64:$val)>; 427135301Smtmdef : Pat<(truncstorei32 I64:$val, I32:$addr), 428164583Sdavidxu (STORE32_I64 0, 0, I32:$addr, I64:$val)>; 429135301Smtm 430164583Sdavidxu// Select truncating stores with a constant offset. 431135301Smtmdef : Pat<(truncstorei8 I32:$val, (regPlusImm I32:$addr, imm:$off)), 432135301Smtm (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>; 433135301Smtmdef : Pat<(truncstorei16 I32:$val, (regPlusImm I32:$addr, imm:$off)), 434144518Sdavidxu (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>; 435112918Sjeffdef : Pat<(truncstorei8 I64:$val, (regPlusImm I32:$addr, imm:$off)), 436112918Sjeff (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>; 437144518Sdavidxudef : Pat<(truncstorei16 I64:$val, (regPlusImm I32:$addr, imm:$off)), 438112918Sjeff (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>; 439112918Sjeffdef : Pat<(truncstorei32 I64:$val, (regPlusImm I32:$addr, imm:$off)), 440144518Sdavidxu (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>; 441112918Sjeffdef : Pat<(truncstorei8 I32:$val, (or_is_add I32:$addr, imm:$off)), 442112918Sjeff (STORE8_I32 0, imm:$off, I32:$addr, I32:$val)>; 443164583Sdavidxudef : Pat<(truncstorei16 I32:$val, (or_is_add I32:$addr, imm:$off)), 444112918Sjeff (STORE16_I32 0, imm:$off, I32:$addr, I32:$val)>; 445164583Sdavidxudef : Pat<(truncstorei8 I64:$val, (or_is_add I32:$addr, imm:$off)), 446112918Sjeff (STORE8_I64 0, imm:$off, I32:$addr, I64:$val)>; 447112918Sjeffdef : Pat<(truncstorei16 I64:$val, (or_is_add I32:$addr, imm:$off)), 448112918Sjeff (STORE16_I64 0, imm:$off, I32:$addr, I64:$val)>; 449144518Sdavidxudef : Pat<(truncstorei32 I64:$val, (or_is_add I32:$addr, imm:$off)), 450135301Smtm (STORE32_I64 0, imm:$off, I32:$addr, I64:$val)>; 451135301Smtmdef : Pat<(truncstorei8 I32:$val, 452144518Sdavidxu (regPlusGA I32:$addr, 453135301Smtm (WebAssemblywrapper tglobaladdr:$off))), 454144518Sdavidxu (STORE8_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>; 455135301Smtmdef : Pat<(truncstorei16 I32:$val, 456135301Smtm (regPlusGA I32:$addr, 457164583Sdavidxu (WebAssemblywrapper tglobaladdr:$off))), 458135301Smtm (STORE16_I32 0, tglobaladdr:$off, I32:$addr, I32:$val)>; 459164583Sdavidxudef : Pat<(truncstorei8 I64:$val, 460135301Smtm (regPlusGA I32:$addr, 461135301Smtm (WebAssemblywrapper tglobaladdr:$off))), 462135301Smtm (STORE8_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>; 463144518Sdavidxudef : Pat<(truncstorei16 I64:$val, 464135301Smtm (regPlusGA I32:$addr, 465135301Smtm (WebAssemblywrapper tglobaladdr:$off))), 466144518Sdavidxu (STORE16_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>; 467135301Smtmdef : Pat<(truncstorei32 I64:$val, 468135301Smtm (regPlusGA I32:$addr, 469144518Sdavidxu (WebAssemblywrapper tglobaladdr:$off))), 470135301Smtm (STORE32_I64 0, tglobaladdr:$off, I32:$addr, I64:$val)>; 471135301Smtmdef : Pat<(truncstorei8 I32:$val, (add I32:$addr, 472164583Sdavidxu (WebAssemblywrapper texternalsym:$off))), 473135301Smtm (STORE8_I32 0, texternalsym:$off, I32:$addr, I32:$val)>; 474164583Sdavidxudef : Pat<(truncstorei16 I32:$val, 475135301Smtm (add I32:$addr, 476135301Smtm (WebAssemblywrapper texternalsym:$off))), 477135301Smtm (STORE16_I32 0, texternalsym:$off, I32:$addr, I32:$val)>; 478160662Sdavidxudef : Pat<(truncstorei8 I64:$val, 479148658Sdeischen (add I32:$addr, 480112918Sjeff (WebAssemblywrapper texternalsym:$off))), 481160662Sdavidxu (STORE8_I64 0, texternalsym:$off, I32:$addr, I64:$val)>; 482112918Sjeffdef : Pat<(truncstorei16 I64:$val, 483144518Sdavidxu (add I32:$addr, 484112918Sjeff (WebAssemblywrapper texternalsym:$off))), 485112918Sjeff (STORE16_I64 0, texternalsym:$off, I32:$addr, I64:$val)>; 486164583Sdavidxudef : Pat<(truncstorei32 I64:$val, 487112918Sjeff (add I32:$addr, 488164583Sdavidxu (WebAssemblywrapper texternalsym:$off))), 489112918Sjeff (STORE32_I64 0, texternalsym:$off, I32:$addr, I64:$val)>; 490144518Sdavidxu 491112918Sjeff// Select truncating stores with just a constant offset. 492112918Sjeffdef : Pat<(truncstorei8 I32:$val, imm:$off), 493160662Sdavidxu (STORE8_I32 0, imm:$off, (CONST_I32 0), I32:$val)>; 494112918Sjeffdef : Pat<(truncstorei16 I32:$val, imm:$off), 495112918Sjeff (STORE16_I32 0, imm:$off, (CONST_I32 0), I32:$val)>; 496160662Sdavidxudef : Pat<(truncstorei8 I64:$val, imm:$off), 497112918Sjeff (STORE8_I64 0, imm:$off, (CONST_I32 0), I64:$val)>; 498144518Sdavidxudef : Pat<(truncstorei16 I64:$val, imm:$off), 499112918Sjeff (STORE16_I64 0, imm:$off, (CONST_I32 0), I64:$val)>; 500112918Sjeffdef : Pat<(truncstorei32 I64:$val, imm:$off), 501164583Sdavidxu (STORE32_I64 0, imm:$off, (CONST_I32 0), I64:$val)>; 502112918Sjeffdef : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 503164583Sdavidxu (STORE8_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 504112918Sjeffdef : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper tglobaladdr:$off)), 505112918Sjeff (STORE16_I32 0, tglobaladdr:$off, (CONST_I32 0), I32:$val)>; 506112918Sjeffdef : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 507112918Sjeff (STORE8_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 508160662Sdavidxudef : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 509112918Sjeff (STORE16_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 510112918Sjeffdef : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper tglobaladdr:$off)), 511160662Sdavidxu (STORE32_I64 0, tglobaladdr:$off, (CONST_I32 0), I64:$val)>; 512112918Sjeffdef : Pat<(truncstorei8 I32:$val, (WebAssemblywrapper texternalsym:$off)), 513144518Sdavidxu (STORE8_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>; 514112918Sjeffdef : Pat<(truncstorei16 I32:$val, (WebAssemblywrapper texternalsym:$off)), 515112918Sjeff (STORE16_I32 0, texternalsym:$off, (CONST_I32 0), I32:$val)>; 516164583Sdavidxudef : Pat<(truncstorei8 I64:$val, (WebAssemblywrapper texternalsym:$off)), 517112918Sjeff (STORE8_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>; 518164583Sdavidxudef : Pat<(truncstorei16 I64:$val, (WebAssemblywrapper texternalsym:$off)), 519112918Sjeff (STORE16_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>; 520144518Sdavidxudef : Pat<(truncstorei32 I64:$val, (WebAssemblywrapper texternalsym:$off)), 521112918Sjeff (STORE32_I64 0, texternalsym:$off, (CONST_I32 0), I64:$val)>; 522112918Sjeff 523160662Sdavidxulet Defs = [ARGUMENTS] in { 524148658Sdeischen 525148658Sdeischen// Current memory size. 526160662Sdavidxudef CURRENT_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags), 527148658Sdeischen [], 528148658Sdeischen "current_memory\t$dst", 0x3f>, 529148658Sdeischen Requires<[HasAddr32]>; 530148658Sdeischen 531164583Sdavidxu// Grow memory. 532148658Sdeischendef GROW_MEMORY_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), 533164583Sdavidxu [], 534148658Sdeischen "grow_memory\t$dst, $delta", 0x40>, 535148658Sdeischen Requires<[HasAddr32]>; 536148658Sdeischen 537148658Sdeischen} // Defs = [ARGUMENTS] 538160662Sdavidxu 539112918Sjeffdef : Pat<(int_wasm_current_memory), 540112918Sjeff (CURRENT_MEMORY_I32 0)>; 541160662Sdavidxudef : Pat<(int_wasm_grow_memory I32:$delta), 542112918Sjeff (GROW_MEMORY_I32 0, $delta)>; 543144518Sdavidxu