WebAssemblyInstrMemory.td revision 344779
1286425Sdim// WebAssemblyInstrMemory.td-WebAssembly Memory codegen support -*- tablegen -*- 2286425Sdim// 3286425Sdim// The LLVM Compiler Infrastructure 4286425Sdim// 5286425Sdim// This file is distributed under the University of Illinois Open Source 6286425Sdim// License. See LICENSE.TXT for details. 7286425Sdim// 8286425Sdim//===----------------------------------------------------------------------===// 9286425Sdim/// 10286425Sdim/// \file 11341825Sdim/// WebAssembly Memory operand code-gen constructs. 12286425Sdim/// 13286425Sdim//===----------------------------------------------------------------------===// 14286425Sdim 15296417Sdim// TODO: 16296417Sdim// - HasAddr64 17296417Sdim// - WebAssemblyTargetLowering having to do with atomics 18296417Sdim// - Each has optional alignment. 19296417Sdim 20296417Sdim// WebAssembly has i8/i16/i32/i64/f32/f64 memory types, but doesn't have i8/i16 21296417Sdim// local types. These memory-only types instead zero- or sign-extend into local 22296417Sdim// types when loading, and truncate when storing. 23296417Sdim 24296417Sdim// WebAssembly constant offsets are performed as unsigned with infinite 25296417Sdim// precision, so we need to check for NoUnsignedWrap so that we don't fold an 26296417Sdim// offset for an add that needs wrapping. 27296417Sdimdef regPlusImm : PatFrag<(ops node:$addr, node:$off), 28296417Sdim (add node:$addr, node:$off), 29321369Sdim [{ return N->getFlags().hasNoUnsignedWrap(); }]>; 30296417Sdim 31309124Sdim// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero. 32309124Sdimdef or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ 33309124Sdim if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1))) 34309124Sdim return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); 35309124Sdim 36344779Sdim KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0); 37344779Sdim KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0); 38321369Sdim return (~Known0.Zero & ~Known1.Zero) == 0; 39309124Sdim}]>; 40309124Sdim 41296417Sdim// GlobalAddresses are conceptually unsigned values, so we can also fold them 42314564Sdim// into immediate values as long as the add is 'nuw'. 43314564Sdim// TODO: We'd like to also match GA offsets but there are cases where the 44314564Sdim// register can have a negative value. Find out what more we can do. 45296417Sdimdef regPlusGA : PatFrag<(ops node:$addr, node:$off), 46296417Sdim (add node:$addr, node:$off), 47296417Sdim [{ 48321369Sdim return N->getFlags().hasNoUnsignedWrap(); 49296417Sdim}]>; 50296417Sdim 51296417Sdim// We don't need a regPlusES because external symbols never have constant 52296417Sdim// offsets folded into them, so we can just use add. 53296417Sdim 54327952Sdim// Defines atomic and non-atomic loads, regular and extending. 55341825Sdimmulticlass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode> { 56344779Sdim let mayLoad = 1 in 57341825Sdim defm "": I<(outs rc:$dst), 58341825Sdim (ins P2Align:$p2align, offset32_op:$off, I32:$addr), 59341825Sdim (outs), (ins P2Align:$p2align, offset32_op:$off), 60341825Sdim [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), 61344779Sdim !strconcat(Name, "\t${off}${p2align}"), Opcode>; 62341825Sdim} 63327952Sdim 64296417Sdim// Basic load. 65314564Sdim// FIXME: When we can break syntax compatibility, reorder the fields in the 66314564Sdim// asmstrings to match the binary encoding. 67341825Sdimdefm LOAD_I32 : WebAssemblyLoad<I32, "i32.load", 0x28>; 68341825Sdimdefm LOAD_I64 : WebAssemblyLoad<I64, "i64.load", 0x29>; 69341825Sdimdefm LOAD_F32 : WebAssemblyLoad<F32, "f32.load", 0x2a>; 70341825Sdimdefm LOAD_F64 : WebAssemblyLoad<F64, "f64.load", 0x2b>; 71296417Sdim 72296417Sdim// Select loads with no constant offset. 73341825Sdimclass LoadPatNoOffset<ValueType ty, PatFrag kind, NI inst> : 74341825Sdim Pat<(ty (kind I32:$addr)), (inst 0, 0, I32:$addr)>; 75296417Sdim 76327952Sdimdef : LoadPatNoOffset<i32, load, LOAD_I32>; 77327952Sdimdef : LoadPatNoOffset<i64, load, LOAD_I64>; 78327952Sdimdef : LoadPatNoOffset<f32, load, LOAD_F32>; 79327952Sdimdef : LoadPatNoOffset<f64, load, LOAD_F64>; 80327952Sdim 81327952Sdim 82296417Sdim// Select loads with a constant offset. 83296417Sdim 84327952Sdim// Pattern with address + immediate offset 85341825Sdimclass LoadPatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> : 86341825Sdim Pat<(ty (kind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, I32:$addr)>; 87327952Sdim 88327952Sdimdef : LoadPatImmOff<i32, load, regPlusImm, LOAD_I32>; 89327952Sdimdef : LoadPatImmOff<i64, load, regPlusImm, LOAD_I64>; 90327952Sdimdef : LoadPatImmOff<f32, load, regPlusImm, LOAD_F32>; 91327952Sdimdef : LoadPatImmOff<f64, load, regPlusImm, LOAD_F64>; 92327952Sdimdef : LoadPatImmOff<i32, load, or_is_add, LOAD_I32>; 93327952Sdimdef : LoadPatImmOff<i64, load, or_is_add, LOAD_I64>; 94327952Sdimdef : LoadPatImmOff<f32, load, or_is_add, LOAD_F32>; 95327952Sdimdef : LoadPatImmOff<f64, load, or_is_add, LOAD_F64>; 96327952Sdim 97341825Sdimclass LoadPatGlobalAddr<ValueType ty, PatFrag kind, NI inst> : 98341825Sdim Pat<(ty (kind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)))), 99341825Sdim (inst 0, tglobaladdr:$off, I32:$addr)>; 100327952Sdim 101327952Sdimdef : LoadPatGlobalAddr<i32, load, LOAD_I32>; 102327952Sdimdef : LoadPatGlobalAddr<i64, load, LOAD_I64>; 103327952Sdimdef : LoadPatGlobalAddr<f32, load, LOAD_F32>; 104327952Sdimdef : LoadPatGlobalAddr<f64, load, LOAD_F64>; 105327952Sdim 106341825Sdimclass LoadPatExternalSym<ValueType ty, PatFrag kind, NI inst> : 107341825Sdim Pat<(ty (kind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)))), 108341825Sdim (inst 0, texternalsym:$off, I32:$addr)>; 109327952Sdimdef : LoadPatExternalSym<i32, load, LOAD_I32>; 110327952Sdimdef : LoadPatExternalSym<i64, load, LOAD_I64>; 111327952Sdimdef : LoadPatExternalSym<f32, load, LOAD_F32>; 112327952Sdimdef : LoadPatExternalSym<f64, load, LOAD_F64>; 113327952Sdim 114327952Sdim 115296417Sdim// Select loads with just a constant offset. 116341825Sdimclass LoadPatOffsetOnly<ValueType ty, PatFrag kind, NI inst> : 117341825Sdim Pat<(ty (kind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>; 118296417Sdim 119327952Sdimdef : LoadPatOffsetOnly<i32, load, LOAD_I32>; 120327952Sdimdef : LoadPatOffsetOnly<i64, load, LOAD_I64>; 121327952Sdimdef : LoadPatOffsetOnly<f32, load, LOAD_F32>; 122327952Sdimdef : LoadPatOffsetOnly<f64, load, LOAD_F64>; 123327952Sdim 124341825Sdimclass LoadPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> : 125341825Sdim Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))), 126327952Sdim (inst 0, tglobaladdr:$off, (CONST_I32 0))>; 127327952Sdim 128327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, load, LOAD_I32>; 129327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, load, LOAD_I64>; 130327952Sdimdef : LoadPatGlobalAddrOffOnly<f32, load, LOAD_F32>; 131327952Sdimdef : LoadPatGlobalAddrOffOnly<f64, load, LOAD_F64>; 132327952Sdim 133341825Sdimclass LoadPatExternSymOffOnly<ValueType ty, PatFrag kind, NI inst> : 134341825Sdim Pat<(ty (kind (WebAssemblywrapper texternalsym:$off))), 135327952Sdim (inst 0, texternalsym:$off, (CONST_I32 0))>; 136327952Sdimdef : LoadPatExternSymOffOnly<i32, load, LOAD_I32>; 137327952Sdimdef : LoadPatExternSymOffOnly<i64, load, LOAD_I64>; 138327952Sdimdef : LoadPatExternSymOffOnly<f32, load, LOAD_F32>; 139327952Sdimdef : LoadPatExternSymOffOnly<f64, load, LOAD_F64>; 140327952Sdim 141296417Sdim// Extending load. 142341825Sdimdefm LOAD8_S_I32 : WebAssemblyLoad<I32, "i32.load8_s", 0x2c>; 143341825Sdimdefm LOAD8_U_I32 : WebAssemblyLoad<I32, "i32.load8_u", 0x2d>; 144341825Sdimdefm LOAD16_S_I32 : WebAssemblyLoad<I32, "i32.load16_s", 0x2e>; 145341825Sdimdefm LOAD16_U_I32 : WebAssemblyLoad<I32, "i32.load16_u", 0x2f>; 146341825Sdimdefm LOAD8_S_I64 : WebAssemblyLoad<I64, "i64.load8_s", 0x30>; 147341825Sdimdefm LOAD8_U_I64 : WebAssemblyLoad<I64, "i64.load8_u", 0x31>; 148341825Sdimdefm LOAD16_S_I64 : WebAssemblyLoad<I64, "i64.load16_s", 0x32>; 149341825Sdimdefm LOAD16_U_I64 : WebAssemblyLoad<I64, "i64.load16_u", 0x33>; 150341825Sdimdefm LOAD32_S_I64 : WebAssemblyLoad<I64, "i64.load32_s", 0x34>; 151341825Sdimdefm LOAD32_U_I64 : WebAssemblyLoad<I64, "i64.load32_u", 0x35>; 152296417Sdim 153296417Sdim// Select extending loads with no constant offset. 154327952Sdimdef : LoadPatNoOffset<i32, sextloadi8, LOAD8_S_I32>; 155327952Sdimdef : LoadPatNoOffset<i32, zextloadi8, LOAD8_U_I32>; 156327952Sdimdef : LoadPatNoOffset<i32, sextloadi16, LOAD16_S_I32>; 157327952Sdimdef : LoadPatNoOffset<i32, zextloadi16, LOAD16_U_I32>; 158327952Sdimdef : LoadPatNoOffset<i64, sextloadi8, LOAD8_S_I64>; 159327952Sdimdef : LoadPatNoOffset<i64, zextloadi8, LOAD8_U_I64>; 160327952Sdimdef : LoadPatNoOffset<i64, sextloadi16, LOAD16_S_I64>; 161327952Sdimdef : LoadPatNoOffset<i64, zextloadi16, LOAD16_U_I64>; 162327952Sdimdef : LoadPatNoOffset<i64, sextloadi32, LOAD32_S_I64>; 163327952Sdimdef : LoadPatNoOffset<i64, zextloadi32, LOAD32_U_I64>; 164296417Sdim 165296417Sdim// Select extending loads with a constant offset. 166327952Sdimdef : LoadPatImmOff<i32, sextloadi8, regPlusImm, LOAD8_S_I32>; 167327952Sdimdef : LoadPatImmOff<i32, zextloadi8, regPlusImm, LOAD8_U_I32>; 168327952Sdimdef : LoadPatImmOff<i32, sextloadi16, regPlusImm, LOAD16_S_I32>; 169327952Sdimdef : LoadPatImmOff<i32, zextloadi16, regPlusImm, LOAD16_U_I32>; 170327952Sdimdef : LoadPatImmOff<i64, sextloadi8, regPlusImm, LOAD8_S_I64>; 171327952Sdimdef : LoadPatImmOff<i64, zextloadi8, regPlusImm, LOAD8_U_I64>; 172327952Sdimdef : LoadPatImmOff<i64, sextloadi16, regPlusImm, LOAD16_S_I64>; 173327952Sdimdef : LoadPatImmOff<i64, zextloadi16, regPlusImm, LOAD16_U_I64>; 174327952Sdimdef : LoadPatImmOff<i64, sextloadi32, regPlusImm, LOAD32_S_I64>; 175327952Sdimdef : LoadPatImmOff<i64, zextloadi32, regPlusImm, LOAD32_U_I64>; 176296417Sdim 177327952Sdimdef : LoadPatImmOff<i32, sextloadi8, or_is_add, LOAD8_S_I32>; 178327952Sdimdef : LoadPatImmOff<i32, zextloadi8, or_is_add, LOAD8_U_I32>; 179327952Sdimdef : LoadPatImmOff<i32, sextloadi16, or_is_add, LOAD16_S_I32>; 180327952Sdimdef : LoadPatImmOff<i32, zextloadi16, or_is_add, LOAD16_U_I32>; 181327952Sdimdef : LoadPatImmOff<i64, sextloadi8, or_is_add, LOAD8_S_I64>; 182327952Sdimdef : LoadPatImmOff<i64, zextloadi8, or_is_add, LOAD8_U_I64>; 183327952Sdimdef : LoadPatImmOff<i64, sextloadi16, or_is_add, LOAD16_S_I64>; 184327952Sdimdef : LoadPatImmOff<i64, zextloadi16, or_is_add, LOAD16_U_I64>; 185327952Sdimdef : LoadPatImmOff<i64, sextloadi32, or_is_add, LOAD32_S_I64>; 186327952Sdimdef : LoadPatImmOff<i64, zextloadi32, or_is_add, LOAD32_U_I64>; 187327952Sdim 188327952Sdimdef : LoadPatGlobalAddr<i32, sextloadi8, LOAD8_S_I32>; 189327952Sdimdef : LoadPatGlobalAddr<i32, zextloadi8, LOAD8_U_I32>; 190327952Sdimdef : LoadPatGlobalAddr<i32, sextloadi16, LOAD16_S_I32>; 191327952Sdimdef : LoadPatGlobalAddr<i32, zextloadi8, LOAD16_U_I32>; 192327952Sdim 193327952Sdimdef : LoadPatGlobalAddr<i64, sextloadi8, LOAD8_S_I64>; 194327952Sdimdef : LoadPatGlobalAddr<i64, zextloadi8, LOAD8_U_I64>; 195327952Sdimdef : LoadPatGlobalAddr<i64, sextloadi16, LOAD16_S_I64>; 196327952Sdimdef : LoadPatGlobalAddr<i64, zextloadi16, LOAD16_U_I64>; 197327952Sdimdef : LoadPatGlobalAddr<i64, sextloadi32, LOAD32_S_I64>; 198327952Sdimdef : LoadPatGlobalAddr<i64, zextloadi32, LOAD32_U_I64>; 199327952Sdim 200327952Sdimdef : LoadPatExternalSym<i32, sextloadi8, LOAD8_S_I32>; 201327952Sdimdef : LoadPatExternalSym<i32, zextloadi8, LOAD8_U_I32>; 202327952Sdimdef : LoadPatExternalSym<i32, sextloadi16, LOAD16_S_I32>; 203327952Sdimdef : LoadPatExternalSym<i32, zextloadi16, LOAD16_U_I32>; 204327952Sdimdef : LoadPatExternalSym<i64, sextloadi8, LOAD8_S_I64>; 205327952Sdimdef : LoadPatExternalSym<i64, zextloadi8, LOAD8_U_I64>; 206327952Sdimdef : LoadPatExternalSym<i64, sextloadi16, LOAD16_S_I64>; 207327952Sdimdef : LoadPatExternalSym<i64, zextloadi16, LOAD16_U_I64>; 208327952Sdimdef : LoadPatExternalSym<i64, sextloadi32, LOAD32_S_I64>; 209327952Sdimdef : LoadPatExternalSym<i64, zextloadi32, LOAD32_U_I64>; 210327952Sdim 211327952Sdim 212296417Sdim// Select extending loads with just a constant offset. 213327952Sdimdef : LoadPatOffsetOnly<i32, sextloadi8, LOAD8_S_I32>; 214327952Sdimdef : LoadPatOffsetOnly<i32, zextloadi8, LOAD8_U_I32>; 215327952Sdimdef : LoadPatOffsetOnly<i32, sextloadi16, LOAD16_S_I32>; 216327952Sdimdef : LoadPatOffsetOnly<i32, zextloadi16, LOAD16_U_I32>; 217296417Sdim 218327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi8, LOAD8_S_I64>; 219327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi8, LOAD8_U_I64>; 220327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi16, LOAD16_S_I64>; 221327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi16, LOAD16_U_I64>; 222327952Sdimdef : LoadPatOffsetOnly<i64, sextloadi32, LOAD32_S_I64>; 223327952Sdimdef : LoadPatOffsetOnly<i64, zextloadi32, LOAD32_U_I64>; 224327952Sdim 225327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, sextloadi8, LOAD8_S_I32>; 226327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, zextloadi8, LOAD8_U_I32>; 227327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, sextloadi16, LOAD16_S_I32>; 228327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, zextloadi16, LOAD16_U_I32>; 229327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi8, LOAD8_S_I64>; 230327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi8, LOAD8_U_I64>; 231327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi16, LOAD16_S_I64>; 232327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi16, LOAD16_U_I64>; 233327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, sextloadi32, LOAD32_S_I64>; 234327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, zextloadi32, LOAD32_U_I64>; 235327952Sdim 236327952Sdimdef : LoadPatExternSymOffOnly<i32, sextloadi8, LOAD8_S_I32>; 237327952Sdimdef : LoadPatExternSymOffOnly<i32, zextloadi8, LOAD8_U_I32>; 238327952Sdimdef : LoadPatExternSymOffOnly<i32, sextloadi16, LOAD16_S_I32>; 239327952Sdimdef : LoadPatExternSymOffOnly<i32, zextloadi16, LOAD16_U_I32>; 240327952Sdimdef : LoadPatExternSymOffOnly<i64, sextloadi8, LOAD8_S_I64>; 241327952Sdimdef : LoadPatExternSymOffOnly<i64, zextloadi8, LOAD8_U_I64>; 242327952Sdimdef : LoadPatExternSymOffOnly<i64, sextloadi16, LOAD16_S_I64>; 243327952Sdimdef : LoadPatExternSymOffOnly<i64, zextloadi16, LOAD16_U_I64>; 244327952Sdimdef : LoadPatExternSymOffOnly<i64, sextloadi32, LOAD32_S_I64>; 245327952Sdimdef : LoadPatExternSymOffOnly<i64, zextloadi32, LOAD32_U_I64>; 246327952Sdim 247296417Sdim// Resolve "don't care" extending loads to zero-extending loads. This is 248296417Sdim// somewhat arbitrary, but zero-extending is conceptually simpler. 249296417Sdim 250296417Sdim// Select "don't care" extending loads with no constant offset. 251327952Sdimdef : LoadPatNoOffset<i32, extloadi8, LOAD8_U_I32>; 252327952Sdimdef : LoadPatNoOffset<i32, extloadi16, LOAD16_U_I32>; 253327952Sdimdef : LoadPatNoOffset<i64, extloadi8, LOAD8_U_I64>; 254327952Sdimdef : LoadPatNoOffset<i64, extloadi16, LOAD16_U_I64>; 255327952Sdimdef : LoadPatNoOffset<i64, extloadi32, LOAD32_U_I64>; 256296417Sdim 257296417Sdim// Select "don't care" extending loads with a constant offset. 258327952Sdimdef : LoadPatImmOff<i32, extloadi8, regPlusImm, LOAD8_U_I32>; 259327952Sdimdef : LoadPatImmOff<i32, extloadi16, regPlusImm, LOAD16_U_I32>; 260327952Sdimdef : LoadPatImmOff<i64, extloadi8, regPlusImm, LOAD8_U_I64>; 261327952Sdimdef : LoadPatImmOff<i64, extloadi16, regPlusImm, LOAD16_U_I64>; 262327952Sdimdef : LoadPatImmOff<i64, extloadi32, regPlusImm, LOAD32_U_I64>; 263327952Sdimdef : LoadPatImmOff<i32, extloadi8, or_is_add, LOAD8_U_I32>; 264327952Sdimdef : LoadPatImmOff<i32, extloadi16, or_is_add, LOAD16_U_I32>; 265327952Sdimdef : LoadPatImmOff<i64, extloadi8, or_is_add, LOAD8_U_I64>; 266327952Sdimdef : LoadPatImmOff<i64, extloadi16, or_is_add, LOAD16_U_I64>; 267327952Sdimdef : LoadPatImmOff<i64, extloadi32, or_is_add, LOAD32_U_I64>; 268327952Sdimdef : LoadPatGlobalAddr<i32, extloadi8, LOAD8_U_I32>; 269327952Sdimdef : LoadPatGlobalAddr<i32, extloadi16, LOAD16_U_I32>; 270327952Sdimdef : LoadPatGlobalAddr<i64, extloadi8, LOAD8_U_I64>; 271327952Sdimdef : LoadPatGlobalAddr<i64, extloadi16, LOAD16_U_I64>; 272327952Sdimdef : LoadPatGlobalAddr<i64, extloadi32, LOAD32_U_I64>; 273327952Sdimdef : LoadPatExternalSym<i32, extloadi8, LOAD8_U_I32>; 274327952Sdimdef : LoadPatExternalSym<i32, extloadi16, LOAD16_U_I32>; 275327952Sdimdef : LoadPatExternalSym<i64, extloadi8, LOAD8_U_I64>; 276327952Sdimdef : LoadPatExternalSym<i64, extloadi16, LOAD16_U_I64>; 277327952Sdimdef : LoadPatExternalSym<i64, extloadi32, LOAD32_U_I64>; 278296417Sdim 279296417Sdim// Select "don't care" extending loads with just a constant offset. 280327952Sdimdef : LoadPatOffsetOnly<i32, extloadi8, LOAD8_U_I32>; 281327952Sdimdef : LoadPatOffsetOnly<i32, extloadi16, LOAD16_U_I32>; 282327952Sdimdef : LoadPatOffsetOnly<i64, extloadi8, LOAD8_U_I64>; 283327952Sdimdef : LoadPatOffsetOnly<i64, extloadi16, LOAD16_U_I64>; 284327952Sdimdef : LoadPatOffsetOnly<i64, extloadi32, LOAD32_U_I64>; 285327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, extloadi8, LOAD8_U_I32>; 286327952Sdimdef : LoadPatGlobalAddrOffOnly<i32, extloadi16, LOAD16_U_I32>; 287327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi8, LOAD8_U_I64>; 288327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi16, LOAD16_U_I64>; 289327952Sdimdef : LoadPatGlobalAddrOffOnly<i64, extloadi32, LOAD32_U_I64>; 290327952Sdimdef : LoadPatExternSymOffOnly<i32, extloadi8, LOAD8_U_I32>; 291327952Sdimdef : LoadPatExternSymOffOnly<i32, extloadi16, LOAD16_U_I32>; 292327952Sdimdef : LoadPatExternSymOffOnly<i64, extloadi8, LOAD8_U_I64>; 293327952Sdimdef : LoadPatExternSymOffOnly<i64, extloadi16, LOAD16_U_I64>; 294327952Sdimdef : LoadPatExternSymOffOnly<i64, extloadi32, LOAD32_U_I64>; 295296417Sdim 296341825Sdim// Defines atomic and non-atomic stores, regular and truncating 297341825Sdimmulticlass WebAssemblyStore<WebAssemblyRegClass rc, string Name, int Opcode> { 298344779Sdim let mayStore = 1 in 299341825Sdim defm "" : I<(outs), 300341825Sdim (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), 301341825Sdim (outs), 302341825Sdim (ins P2Align:$p2align, offset32_op:$off), [], 303341825Sdim !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), 304344779Sdim !strconcat(Name, "\t${off}${p2align}"), Opcode>; 305341825Sdim} 306296417Sdim// Basic store. 307296417Sdim// Note: WebAssembly inverts SelectionDAG's usual operand order. 308341825Sdimdefm STORE_I32 : WebAssemblyStore<I32, "i32.store", 0x36>; 309341825Sdimdefm STORE_I64 : WebAssemblyStore<I64, "i64.store", 0x37>; 310341825Sdimdefm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>; 311341825Sdimdefm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>; 312296417Sdim 313296417Sdim// Select stores with no constant offset. 314341825Sdimclass StorePatNoOffset<ValueType ty, PatFrag node, NI inst> : 315341825Sdim Pat<(node ty:$val, I32:$addr), (inst 0, 0, I32:$addr, ty:$val)>; 316296417Sdim 317341825Sdimdef : StorePatNoOffset<i32, store, STORE_I32>; 318341825Sdimdef : StorePatNoOffset<i64, store, STORE_I64>; 319341825Sdimdef : StorePatNoOffset<f32, store, STORE_F32>; 320341825Sdimdef : StorePatNoOffset<f64, store, STORE_F64>; 321341825Sdim 322296417Sdim// Select stores with a constant offset. 323341825Sdimclass StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand, NI inst> : 324341825Sdim Pat<(kind ty:$val, (operand I32:$addr, imm:$off)), 325341825Sdim (inst 0, imm:$off, I32:$addr, ty:$val)>; 326296417Sdim 327341825Sdimdef : StorePatImmOff<i32, store, regPlusImm, STORE_I32>; 328341825Sdimdef : StorePatImmOff<i64, store, regPlusImm, STORE_I64>; 329341825Sdimdef : StorePatImmOff<f32, store, regPlusImm, STORE_F32>; 330341825Sdimdef : StorePatImmOff<f64, store, regPlusImm, STORE_F64>; 331341825Sdimdef : StorePatImmOff<i32, store, or_is_add, STORE_I32>; 332341825Sdimdef : StorePatImmOff<i64, store, or_is_add, STORE_I64>; 333341825Sdimdef : StorePatImmOff<f32, store, or_is_add, STORE_F32>; 334341825Sdimdef : StorePatImmOff<f64, store, or_is_add, STORE_F64>; 335341825Sdim 336341825Sdimclass StorePatGlobalAddr<ValueType ty, PatFrag kind, NI inst> : 337341825Sdim Pat<(kind ty:$val, 338341825Sdim (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off))), 339341825Sdim (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>; 340341825Sdimdef : StorePatGlobalAddr<i32, store, STORE_I32>; 341341825Sdimdef : StorePatGlobalAddr<i64, store, STORE_I64>; 342341825Sdimdef : StorePatGlobalAddr<f32, store, STORE_F32>; 343341825Sdimdef : StorePatGlobalAddr<f64, store, STORE_F64>; 344341825Sdim 345341825Sdimclass StorePatExternalSym<ValueType ty, PatFrag kind, NI inst> : 346341825Sdim Pat<(kind ty:$val, (add I32:$addr, (WebAssemblywrapper texternalsym:$off))), 347341825Sdim (inst 0, texternalsym:$off, I32:$addr, ty:$val)>; 348341825Sdimdef : StorePatExternalSym<i32, store, STORE_I32>; 349341825Sdimdef : StorePatExternalSym<i64, store, STORE_I64>; 350341825Sdimdef : StorePatExternalSym<f32, store, STORE_F32>; 351341825Sdimdef : StorePatExternalSym<f64, store, STORE_F64>; 352341825Sdim 353296417Sdim// Select stores with just a constant offset. 354341825Sdimclass StorePatOffsetOnly<ValueType ty, PatFrag kind, NI inst> : 355341825Sdim Pat<(kind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; 356341825Sdimdef : StorePatOffsetOnly<i32, store, STORE_I32>; 357341825Sdimdef : StorePatOffsetOnly<i64, store, STORE_I64>; 358341825Sdimdef : StorePatOffsetOnly<f32, store, STORE_F32>; 359341825Sdimdef : StorePatOffsetOnly<f64, store, STORE_F64>; 360296417Sdim 361341825Sdimclass StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, NI inst> : 362341825Sdim Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)), 363341825Sdim (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>; 364341825Sdimdef : StorePatGlobalAddrOffOnly<i32, store, STORE_I32>; 365341825Sdimdef : StorePatGlobalAddrOffOnly<i64, store, STORE_I64>; 366341825Sdimdef : StorePatGlobalAddrOffOnly<f32, store, STORE_F32>; 367341825Sdimdef : StorePatGlobalAddrOffOnly<f64, store, STORE_F64>; 368341825Sdim 369341825Sdimclass StorePatExternSymOffOnly<ValueType ty, PatFrag kind, NI inst> : 370341825Sdim Pat<(kind ty:$val, (WebAssemblywrapper texternalsym:$off)), 371341825Sdim (inst 0, texternalsym:$off, (CONST_I32 0), ty:$val)>; 372341825Sdimdef : StorePatExternSymOffOnly<i32, store, STORE_I32>; 373341825Sdimdef : StorePatExternSymOffOnly<i64, store, STORE_I64>; 374341825Sdimdef : StorePatExternSymOffOnly<f32, store, STORE_F32>; 375341825Sdimdef : StorePatExternSymOffOnly<f64, store, STORE_F64>; 376341825Sdim 377296417Sdim// Truncating store. 378341825Sdimdefm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>; 379341825Sdimdefm STORE16_I32 : WebAssemblyStore<I32, "i32.store16", 0x3b>; 380341825Sdimdefm STORE8_I64 : WebAssemblyStore<I64, "i64.store8", 0x3c>; 381341825Sdimdefm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>; 382341825Sdimdefm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>; 383296417Sdim 384296417Sdim// Select truncating stores with no constant offset. 385341825Sdimdef : StorePatNoOffset<i32, truncstorei8, STORE8_I32>; 386341825Sdimdef : StorePatNoOffset<i32, truncstorei16, STORE16_I32>; 387341825Sdimdef : StorePatNoOffset<i64, truncstorei8, STORE8_I64>; 388341825Sdimdef : StorePatNoOffset<i64, truncstorei16, STORE16_I64>; 389341825Sdimdef : StorePatNoOffset<i64, truncstorei32, STORE32_I64>; 390296417Sdim 391296417Sdim// Select truncating stores with a constant offset. 392341825Sdimdef : StorePatImmOff<i32, truncstorei8, regPlusImm, STORE8_I32>; 393341825Sdimdef : StorePatImmOff<i32, truncstorei16, regPlusImm, STORE16_I32>; 394341825Sdimdef : StorePatImmOff<i64, truncstorei8, regPlusImm, STORE8_I64>; 395341825Sdimdef : StorePatImmOff<i64, truncstorei16, regPlusImm, STORE16_I64>; 396341825Sdimdef : StorePatImmOff<i64, truncstorei32, regPlusImm, STORE32_I64>; 397341825Sdimdef : StorePatImmOff<i32, truncstorei8, or_is_add, STORE8_I32>; 398341825Sdimdef : StorePatImmOff<i32, truncstorei16, or_is_add, STORE16_I32>; 399341825Sdimdef : StorePatImmOff<i64, truncstorei8, or_is_add, STORE8_I64>; 400341825Sdimdef : StorePatImmOff<i64, truncstorei16, or_is_add, STORE16_I64>; 401341825Sdimdef : StorePatImmOff<i64, truncstorei32, or_is_add, STORE32_I64>; 402296417Sdim 403341825Sdimdef : StorePatGlobalAddr<i32, truncstorei8, STORE8_I32>; 404341825Sdimdef : StorePatGlobalAddr<i32, truncstorei16, STORE16_I32>; 405341825Sdimdef : StorePatGlobalAddr<i64, truncstorei8, STORE8_I64>; 406341825Sdimdef : StorePatGlobalAddr<i64, truncstorei16, STORE16_I64>; 407341825Sdimdef : StorePatGlobalAddr<i64, truncstorei32, STORE32_I64>; 408341825Sdimdef : StorePatExternalSym<i32, truncstorei8, STORE8_I32>; 409341825Sdimdef : StorePatExternalSym<i32, truncstorei16, STORE16_I32>; 410341825Sdimdef : StorePatExternalSym<i64, truncstorei8, STORE8_I64>; 411341825Sdimdef : StorePatExternalSym<i64, truncstorei16, STORE16_I64>; 412341825Sdimdef : StorePatExternalSym<i64, truncstorei32, STORE32_I64>; 413341825Sdim 414296417Sdim// Select truncating stores with just a constant offset. 415341825Sdimdef : StorePatOffsetOnly<i32, truncstorei8, STORE8_I32>; 416341825Sdimdef : StorePatOffsetOnly<i32, truncstorei16, STORE16_I32>; 417341825Sdimdef : StorePatOffsetOnly<i64, truncstorei8, STORE8_I64>; 418341825Sdimdef : StorePatOffsetOnly<i64, truncstorei16, STORE16_I64>; 419341825Sdimdef : StorePatOffsetOnly<i64, truncstorei32, STORE32_I64>; 420341825Sdimdef : StorePatGlobalAddrOffOnly<i32, truncstorei8, STORE8_I32>; 421341825Sdimdef : StorePatGlobalAddrOffOnly<i32, truncstorei16, STORE16_I32>; 422341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei8, STORE8_I64>; 423341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei16, STORE16_I64>; 424341825Sdimdef : StorePatGlobalAddrOffOnly<i64, truncstorei32, STORE32_I64>; 425341825Sdimdef : StorePatExternSymOffOnly<i32, truncstorei8, STORE8_I32>; 426341825Sdimdef : StorePatExternSymOffOnly<i32, truncstorei16, STORE16_I32>; 427341825Sdimdef : StorePatExternSymOffOnly<i64, truncstorei8, STORE8_I64>; 428341825Sdimdef : StorePatExternSymOffOnly<i64, truncstorei16, STORE16_I64>; 429341825Sdimdef : StorePatExternSymOffOnly<i64, truncstorei32, STORE32_I64>; 430296417Sdim 431309124Sdim// Current memory size. 432341825Sdimdefm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), 433341825Sdim (outs), (ins i32imm:$flags), 434341825Sdim [(set I32:$dst, 435341825Sdim (int_wasm_memory_size (i32 imm:$flags)))], 436341825Sdim "memory.size\t$dst, $flags", "memory.size\t$flags", 437341825Sdim 0x3f>, 438341825Sdim Requires<[HasAddr32]>; 439296417Sdim 440296417Sdim// Grow memory. 441341825Sdimdefm MEMORY_GROW_I32 : I<(outs I32:$dst), (ins i32imm:$flags, I32:$delta), 442344779Sdim (outs), (ins i32imm:$flags), 443341825Sdim [(set I32:$dst, 444341825Sdim (int_wasm_memory_grow (i32 imm:$flags), 445341825Sdim I32:$delta))], 446341825Sdim "memory.grow\t$dst, $flags, $delta", 447344779Sdim "memory.grow\t$flags", 0x40>, 448341825Sdim Requires<[HasAddr32]>; 449