Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -32,85 +32,134 @@ //===----------------------------------------------------------------------===// let hasSideEffects = 1 in { -defm ATOMIC_NOTIFY : +defm ATOMIC_NOTIFY_A32 : ATOMIC_I<(outs I32:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$count), (outs), (ins P2Align:$p2align, offset32_op:$off), [], "atomic.notify \t$dst, ${off}(${addr})${p2align}, $count", "atomic.notify \t${off}${p2align}", 0x00>; +defm ATOMIC_NOTIFY_A64 : + ATOMIC_I<(outs I32:$dst), + (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$count), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + "atomic.notify \t$dst, ${off}(${addr})${p2align}, $count", + "atomic.notify \t${off}${p2align}", 0x00>; let mayLoad = 1 in { -defm ATOMIC_WAIT_I32 : +defm ATOMIC_WAIT_I32_A32 : ATOMIC_I<(outs I32:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$exp, I64:$timeout), (outs), (ins P2Align:$p2align, offset32_op:$off), [], "i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", "i32.atomic.wait \t${off}${p2align}", 0x01>; -defm ATOMIC_WAIT_I64 : +defm ATOMIC_WAIT_I32_A64 : + ATOMIC_I<(outs I32:$dst), + (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$exp, + I64:$timeout), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + "i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", + "i32.atomic.wait \t${off}${p2align}", 0x01>; +defm ATOMIC_WAIT_I64_A32 : ATOMIC_I<(outs I32:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, I64:$exp, I64:$timeout), (outs), (ins P2Align:$p2align, offset32_op:$off), [], "i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", "i64.atomic.wait \t${off}${p2align}", 0x02>; +defm ATOMIC_WAIT_I64_A64 : + ATOMIC_I<(outs I32:$dst), + (ins P2Align:$p2align, offset64_op:$off, I64:$addr, I64:$exp, + I64:$timeout), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + "i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout", + "i64.atomic.wait \t${off}${p2align}", 0x02>; } // mayLoad = 1 } // hasSideEffects = 1 let Predicates = [HasAtomics] in { // Select notifys with no constant offset. -def NotifyPatNoOffset : +def NotifyPatNoOffset_A32 : Pat<(i32 (int_wasm_atomic_notify I32:$addr, I32:$count)), - (ATOMIC_NOTIFY 0, 0, I32:$addr, I32:$count)>; + (ATOMIC_NOTIFY_A32 0, 0, I32:$addr, I32:$count)>; +def NotifyPatNoOffset_A64 : + Pat<(i32 (int_wasm_atomic_notify I64:$addr, I32:$count)), + (ATOMIC_NOTIFY_A64 0, 0, I64:$addr, I32:$count)>; // Select notifys with a constant offset. // Pattern with address + immediate offset -class NotifyPatImmOff : - Pat<(i32 (int_wasm_atomic_notify (operand I32:$addr, imm:$off), I32:$count)), - (ATOMIC_NOTIFY 0, imm:$off, I32:$addr, I32:$count)>; -def : NotifyPatImmOff; -def : NotifyPatImmOff; +class NotifyPatImmOff : + Pat<(i32 (int_wasm_atomic_notify (operand rc:$addr, imm:$off), I32:$count)), + (inst 0, imm:$off, I32:$addr, rc:$count)>; +def : NotifyPatImmOff; +def : NotifyPatImmOff; +def : NotifyPatImmOff; +def : NotifyPatImmOff; // Select notifys with just a constant offset. -def NotifyPatOffsetOnly : +def NotifyPatOffsetOnly_A32 : Pat<(i32 (int_wasm_atomic_notify imm:$off, I32:$count)), - (ATOMIC_NOTIFY 0, imm:$off, (CONST_I32 0), I32:$count)>; + (ATOMIC_NOTIFY_A32 0, imm:$off, (CONST_I64 0), I32:$count)>; +def NotifyPatOffsetOnly_A64 : + Pat<(i32 (int_wasm_atomic_notify imm:$off, I32:$count)), + (ATOMIC_NOTIFY_A64 0, imm:$off, (CONST_I64 0), I32:$count)>; -def NotifyPatGlobalAddrOffOnly : +def NotifyPatGlobalAddrOffOnly_A32 : + Pat<(i32 (int_wasm_atomic_notify (WebAssemblywrapper tglobaladdr:$off), + I32:$count)), + (ATOMIC_NOTIFY_A32 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)>; +def NotifyPatGlobalAddrOffOnly_A64 : Pat<(i32 (int_wasm_atomic_notify (WebAssemblywrapper tglobaladdr:$off), I32:$count)), - (ATOMIC_NOTIFY 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)>; + (ATOMIC_NOTIFY_A64 0, tglobaladdr:$off, (CONST_I64 0), I32:$count)>; // Select waits with no constant offset. -class WaitPatNoOffset : - Pat<(i32 (kind I32:$addr, ty:$exp, I64:$timeout)), - (inst 0, 0, I32:$addr, ty:$exp, I64:$timeout)>; -def : WaitPatNoOffset; -def : WaitPatNoOffset; +class WaitPatNoOffset : + Pat<(i32 (kind rc:$addr, ty:$exp, I64:$timeout)), + (inst 0, 0, rc:$addr, ty:$exp, I64:$timeout)>; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; +def : WaitPatNoOffset; // Select waits with a constant offset. // Pattern with address + immediate offset -class WaitPatImmOff : - Pat<(i32 (kind (operand I32:$addr, imm:$off), ty:$exp, I64:$timeout)), - (inst 0, imm:$off, I32:$addr, ty:$exp, I64:$timeout)>; -def : WaitPatImmOff; -def : WaitPatImmOff; -def : WaitPatImmOff; -def : WaitPatImmOff; - -// Select wait_i32, ATOMIC_WAIT_I32s with just a constant offset. -class WaitPatOffsetOnly : +class WaitPatImmOff : + Pat<(i32 (kind (operand rc:$addr, imm:$off), ty:$exp, I64:$timeout)), + (inst 0, imm:$off, rc:$addr, ty:$exp, I64:$timeout)>; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; +def : WaitPatImmOff; + +// Select wait_i32, "ATOMIC_WAIT_I32s with just a constant offset. +class WaitPatOffsetOnly : Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)), - (inst 0, imm:$off, (CONST_I32 0), ty:$exp, I64:$timeout)>; -def : WaitPatOffsetOnly; -def : WaitPatOffsetOnly; - -class WaitPatGlobalAddrOffOnly : + (inst 0, imm:$off, (const_inst 0), ty:$exp, I64:$timeout)>; +def : WaitPatOffsetOnly; +def : WaitPatOffsetOnly; +def : WaitPatOffsetOnly; +def : WaitPatOffsetOnly; + +class WaitPatGlobalAddrOffOnly : Pat<(i32 (kind (WebAssemblywrapper tglobaladdr:$off), ty:$exp, I64:$timeout)), - (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp, I64:$timeout)>; -def : WaitPatGlobalAddrOffOnly; -def : WaitPatGlobalAddrOffOnly; + (inst 0, tglobaladdr:$off, (const_inst 0), ty:$exp, I64:$timeout)>; +def : WaitPatGlobalAddrOffOnly; +def : WaitPatGlobalAddrOffOnly; +def : WaitPatGlobalAddrOffOnly; +def : WaitPatGlobalAddrOffOnly; } // Predicates = [HasAtomics] //===----------------------------------------------------------------------===// @@ -131,8 +180,8 @@ //===----------------------------------------------------------------------===// multiclass AtomicLoad { - defm "" : WebAssemblyLoad, - Requires<[HasAtomics]>; + defm "" : WebAssemblyLoad; } defm ATOMIC_LOAD_I32 : AtomicLoad; @@ -140,23 +189,23 @@ // Select loads with no constant offset. let Predicates = [HasAtomics] in { -def : LoadPatNoOffset; -def : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // Select loads with a constant offset. // Pattern with address + immediate offset -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; // Select loads with just a constant offset. -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; } // Predicates = [HasAtomics] @@ -205,62 +254,62 @@ let Predicates = [HasAtomics] in { // Select zero-extending loads with no constant offset. -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // Select sign-extending loads with no constant offset -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // 32->64 sext load gets selected as i32.atomic.load, i64.extend_i32_s // Zero-extending loads with constant offset -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; // Sign-extending loads with constant offset -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; // No 32->64 patterns, just use i32.atomic.load and i64.extend_s/i64 // Extending loads with just a constant offset -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; - -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; + +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; } // Predicates = [HasAtomics] @@ -284,33 +333,39 @@ let Predicates = [HasAtomics] in { // Select stores with no constant offset. -class AStorePatNoOffset : +class AStorePatNoOffset : Pat<(kind I32:$addr, ty:$val), (inst 0, 0, I32:$addr, ty:$val)>; -def : AStorePatNoOffset; -def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; // Select stores with a constant offset. // Pattern with address + immediate offset -class AStorePatImmOff : +class AStorePatImmOff : Pat<(kind (operand I32:$addr, imm:$off), ty:$val), (inst 0, imm:$off, I32:$addr, ty:$val)>; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; // Select stores with just a constant offset. -class AStorePatOffsetOnly : - Pat<(kind imm:$off, ty:$val), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; -def : AStorePatOffsetOnly; -def : AStorePatOffsetOnly; - -class AStorePatGlobalAddrOffOnly : +class AStorePatOffsetOnly : + Pat<(kind imm:$off, ty:$val), (inst 0, imm:$off, (const_inst 0), ty:$val)>; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; + +class AStorePatGlobalAddrOffOnly : Pat<(kind (WebAssemblywrapper tglobaladdr:$off), ty:$val), (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>; -def : AStorePatGlobalAddrOffOnly; -def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; } // Predicates = [HasAtomics] @@ -336,36 +391,61 @@ let Predicates = [HasAtomics] in { // Truncating stores with no constant offset -def : AStorePatNoOffset; -def : AStorePatNoOffset; -def : AStorePatNoOffset; -def : AStorePatNoOffset; -def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; // Truncating stores with a constant offset -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; -def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; +def : AStorePatImmOff; // Truncating stores with just a constant offset -def : AStorePatOffsetOnly; -def : AStorePatOffsetOnly; -def : AStorePatOffsetOnly; -def : AStorePatOffsetOnly; -def : AStorePatOffsetOnly; - -def : AStorePatGlobalAddrOffOnly; -def : AStorePatGlobalAddrOffOnly; -def : AStorePatGlobalAddrOffOnly; -def : AStorePatGlobalAddrOffOnly; -def : AStorePatGlobalAddrOffOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; +def : AStorePatOffsetOnly; + +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; } // Predicates = [HasAtomics] @@ -502,18 +582,18 @@ } let Predicates = [HasAtomics] in { -defm : BinRMWPattern; -defm : BinRMWPattern; -defm : BinRMWPattern; -defm : BinRMWPattern; -defm : BinRMWPattern; -defm : BinRMWPattern; +defm : BinRMWPattern; +defm : BinRMWPattern; +defm : BinRMWPattern; +defm : BinRMWPattern; +defm : BinRMWPattern; +defm : BinRMWPattern; } // Predicates = [HasAtomics] // Truncating & zero-extending binary RMW patterns. @@ -615,28 +695,28 @@ let Predicates = [HasAtomics] in { defm : BinRMWTruncExtPattern< atomic_load_add_8, atomic_load_add_16, atomic_load_add_32, atomic_load_add_64, - ATOMIC_RMW8_U_ADD_I32, ATOMIC_RMW16_U_ADD_I32, - ATOMIC_RMW8_U_ADD_I64, ATOMIC_RMW16_U_ADD_I64, ATOMIC_RMW32_U_ADD_I64>; + ATOMIC_RMW8_U_ADD_I32, "ATOMIC_RMW16_U_ADD_I32", + ATOMIC_RMW8_U_ADD_I64, "ATOMIC_RMW16_U_ADD_I64", "ATOMIC_RMW32_U_ADD_I64">; defm : BinRMWTruncExtPattern< atomic_load_sub_8, atomic_load_sub_16, atomic_load_sub_32, atomic_load_sub_64, - ATOMIC_RMW8_U_SUB_I32, ATOMIC_RMW16_U_SUB_I32, - ATOMIC_RMW8_U_SUB_I64, ATOMIC_RMW16_U_SUB_I64, ATOMIC_RMW32_U_SUB_I64>; + ATOMIC_RMW8_U_SUB_I32, "ATOMIC_RMW16_U_SUB_I32", + ATOMIC_RMW8_U_SUB_I64, "ATOMIC_RMW16_U_SUB_I64", "ATOMIC_RMW32_U_SUB_I64">; defm : BinRMWTruncExtPattern< atomic_load_and_8, atomic_load_and_16, atomic_load_and_32, atomic_load_and_64, - ATOMIC_RMW8_U_AND_I32, ATOMIC_RMW16_U_AND_I32, - ATOMIC_RMW8_U_AND_I64, ATOMIC_RMW16_U_AND_I64, ATOMIC_RMW32_U_AND_I64>; + ATOMIC_RMW8_U_AND_I32, "ATOMIC_RMW16_U_AND_I32", + ATOMIC_RMW8_U_AND_I64, "ATOMIC_RMW16_U_AND_I64", "ATOMIC_RMW32_U_AND_I64">; defm : BinRMWTruncExtPattern< atomic_load_or_8, atomic_load_or_16, atomic_load_or_32, atomic_load_or_64, - ATOMIC_RMW8_U_OR_I32, ATOMIC_RMW16_U_OR_I32, - ATOMIC_RMW8_U_OR_I64, ATOMIC_RMW16_U_OR_I64, ATOMIC_RMW32_U_OR_I64>; + ATOMIC_RMW8_U_OR_I32, "ATOMIC_RMW16_U_OR_I32", + ATOMIC_RMW8_U_OR_I64, "ATOMIC_RMW16_U_OR_I64", "ATOMIC_RMW32_U_OR_I64">; defm : BinRMWTruncExtPattern< atomic_load_xor_8, atomic_load_xor_16, atomic_load_xor_32, atomic_load_xor_64, - ATOMIC_RMW8_U_XOR_I32, ATOMIC_RMW16_U_XOR_I32, - ATOMIC_RMW8_U_XOR_I64, ATOMIC_RMW16_U_XOR_I64, ATOMIC_RMW32_U_XOR_I64>; + ATOMIC_RMW8_U_XOR_I32, "ATOMIC_RMW16_U_XOR_I32", + ATOMIC_RMW8_U_XOR_I64, "ATOMIC_RMW16_U_XOR_I64", "ATOMIC_RMW32_U_XOR_I64">; defm : BinRMWTruncExtPattern< atomic_swap_8, atomic_swap_16, atomic_swap_32, atomic_swap_64, - ATOMIC_RMW8_U_XCHG_I32, ATOMIC_RMW16_U_XCHG_I32, - ATOMIC_RMW8_U_XCHG_I64, ATOMIC_RMW16_U_XCHG_I64, ATOMIC_RMW32_U_XCHG_I64>; + ATOMIC_RMW8_U_XCHG_I32, "ATOMIC_RMW16_U_XCHG_I32", + ATOMIC_RMW8_U_XCHG_I64, "ATOMIC_RMW16_U_XCHG_I64", "ATOMIC_RMW32_U_XCHG_I64">; } // Predicates = [HasAtomics] //===----------------------------------------------------------------------===// @@ -716,7 +796,7 @@ let Predicates = [HasAtomics] in defm : TerRMWPattern; + ATOMIC_RMW_CMPXCHG_I32, "ATOMIC_RMW_CMPXCHG_I64">; // Truncating & zero-extending ternary RMW patterns. // DAG legalization & optimization before instruction selection may introduce Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td @@ -166,6 +166,9 @@ let OperandType = "OPERAND_OFFSET32" in def offset32_op : Operand; +let OperandType = "OPERAND_OFFSET64" in +def offset64_op : Operand; + let OperandType = "OPERAND_P2ALIGN" in { def P2Align : Operand { let PrintMethod = "printWebAssemblyP2AlignOperand"; Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td @@ -12,7 +12,6 @@ //===----------------------------------------------------------------------===// // TODO: -// - HasAddr64 // - WebAssemblyTargetLowering having to do with atomics // - Each has optional alignment. @@ -41,181 +40,213 @@ // offsets folded into them, so we can just use add. // Defines atomic and non-atomic loads, regular and extending. -multiclass WebAssemblyLoad { +multiclass WebAssemblyLoad reqs> { let mayLoad = 1, UseNamedOperandTable = 1 in - defm "": I<(outs rc:$dst), - (ins P2Align:$p2align, offset32_op:$off, I32:$addr), - (outs), (ins P2Align:$p2align, offset32_op:$off), - [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), - !strconcat(Name, "\t${off}${p2align}"), Opcode>; + defm "_A32": I<(outs rc:$dst), + (ins P2Align:$p2align, offset32_op:$off, I32:$addr), + (outs), (ins P2Align:$p2align, offset32_op:$off), + [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), + !strconcat(Name, "\t${off}${p2align}"), Opcode>, + Requires; + let mayLoad = 1, UseNamedOperandTable = 1 in + defm "_A64": I<(outs rc:$dst), + (ins P2Align:$p2align, offset64_op:$off, I64:$addr), + (outs), (ins P2Align:$p2align, offset64_op:$off), + [], !strconcat(Name, "\t$dst, ${off}(${addr})${p2align}"), + !strconcat(Name, "\t${off}${p2align}"), Opcode>, + Requires; } // Basic load. // FIXME: When we can break syntax compatibility, reorder the fields in the // asmstrings to match the binary encoding. -defm LOAD_I32 : WebAssemblyLoad; -defm LOAD_I64 : WebAssemblyLoad; -defm LOAD_F32 : WebAssemblyLoad; -defm LOAD_F64 : WebAssemblyLoad; +defm LOAD_I32 : WebAssemblyLoad; +defm LOAD_I64 : WebAssemblyLoad; +defm LOAD_F32 : WebAssemblyLoad; +defm LOAD_F64 : WebAssemblyLoad; // Select loads with no constant offset. -class LoadPatNoOffset : - Pat<(ty (kind I32:$addr)), (inst 0, 0, I32:$addr)>; - -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; +multiclass LoadPatNoOffset { + def : Pat<(ty (kind I32:$addr)), (!cast(inst # "_A32") 0, 0, I32:$addr)>; + def : Pat<(ty (kind I64:$addr)), (!cast(inst # "_A64") 0, 0, I64:$addr)>; +} +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // Select loads with a constant offset. // Pattern with address + immediate offset -class LoadPatImmOff : - Pat<(ty (kind (operand I32:$addr, imm:$off))), (inst 0, imm:$off, I32:$addr)>; - -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +multiclass LoadPatImmOff { + def : Pat<(ty (kind (operand I32:$addr, imm:$off))), + (!cast(inst # "_A32") 0, imm:$off, I32:$addr)>; + def : Pat<(ty (kind (operand I64:$addr, imm:$off))), + (!cast(inst # "_A64") 0, imm:$off, I64:$addr)>; +} -// Select loads with just a constant offset. -class LoadPatOffsetOnly : - Pat<(ty (kind imm:$off)), (inst 0, imm:$off, (CONST_I32 0))>; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; +// Select loads with just a constant offset. +multiclass LoadPatOffsetOnly { + def : Pat<(ty (kind imm:$off)), + (!cast(inst # "_A32") 0, imm:$off, (CONST_I32 0))>; + def : Pat<(ty (kind imm:$off)), + (!cast(inst # "_A64") 0, imm:$off, (CONST_I64 0))>; +} -class LoadPatGlobalAddrOffOnly : - Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))), - (inst 0, tglobaladdr:$off, (CONST_I32 0))>, Requires<[IsNotPIC]>; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; + +multiclass LoadPatGlobalAddrOffOnly { + def : Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))), + (!cast(inst # "_A32") 0, tglobaladdr:$off, (CONST_I32 0))>, + Requires<[IsNotPIC]>; + def : Pat<(ty (kind (WebAssemblywrapper tglobaladdr:$off))), + (!cast(inst # "_A64") 0, tglobaladdr:$off, (CONST_I64 0))>, + Requires<[IsNotPIC]>; +} -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; // Extending load. -defm LOAD8_S_I32 : WebAssemblyLoad; -defm LOAD8_U_I32 : WebAssemblyLoad; -defm LOAD16_S_I32 : WebAssemblyLoad; -defm LOAD16_U_I32 : WebAssemblyLoad; -defm LOAD8_S_I64 : WebAssemblyLoad; -defm LOAD8_U_I64 : WebAssemblyLoad; -defm LOAD16_S_I64 : WebAssemblyLoad; -defm LOAD16_U_I64 : WebAssemblyLoad; -defm LOAD32_S_I64 : WebAssemblyLoad; -defm LOAD32_U_I64 : WebAssemblyLoad; +defm LOAD8_S_I32 : WebAssemblyLoad; +defm LOAD8_U_I32 : WebAssemblyLoad; +defm LOAD16_S_I32 : WebAssemblyLoad; +defm LOAD16_U_I32 : WebAssemblyLoad; +defm LOAD8_S_I64 : WebAssemblyLoad; +defm LOAD8_U_I64 : WebAssemblyLoad; +defm LOAD16_S_I64 : WebAssemblyLoad; +defm LOAD16_U_I64 : WebAssemblyLoad; +defm LOAD32_S_I64 : WebAssemblyLoad; +defm LOAD32_U_I64 : WebAssemblyLoad; // Select extending loads with no constant offset. -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // Select extending loads with a constant offset. -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; - -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; + +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; // Select extending loads with just a constant offset. -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; - -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; - -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; + +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; + +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; // Resolve "don't care" extending loads to zero-extending loads. This is // somewhat arbitrary, but zero-extending is conceptually simpler. // Select "don't care" extending loads with no constant offset. -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; -def : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; +defm : LoadPatNoOffset; // Select "don't care" extending loads with a constant offset. -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatImmOff; // Select "don't care" extending loads with just a constant offset. -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatOffsetOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; +defm : LoadPatGlobalAddrOffOnly; // Defines atomic and non-atomic stores, regular and truncating multiclass WebAssemblyStore { let mayStore = 1, UseNamedOperandTable = 1 in - defm "" : I<(outs), - (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), - (outs), - (ins P2Align:$p2align, offset32_op:$off), [], - !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), - !strconcat(Name, "\t${off}${p2align}"), Opcode>; + defm "_A32" : I<(outs), + (ins P2Align:$p2align, offset32_op:$off, I32:$addr, rc:$val), + (outs), + (ins P2Align:$p2align, offset32_op:$off), [], + !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), + !strconcat(Name, "\t${off}${p2align}"), Opcode>; + let mayStore = 1, UseNamedOperandTable = 1 in + defm "_A64" : I<(outs), + (ins P2Align:$p2align, offset64_op:$off, I64:$addr, rc:$val), + (outs), + (ins P2Align:$p2align, offset64_op:$off), [], + !strconcat(Name, "\t${off}(${addr})${p2align}, $val"), + !strconcat(Name, "\t${off}${p2align}"), Opcode>; } + // Basic store. // Note: WebAssembly inverts SelectionDAG's usual operand order. defm STORE_I32 : WebAssemblyStore; @@ -224,43 +255,62 @@ defm STORE_F64 : WebAssemblyStore; // Select stores with no constant offset. -class StorePatNoOffset : - Pat<(node ty:$val, I32:$addr), (inst 0, 0, I32:$addr, ty:$val)>; +multiclass StorePatNoOffset { + def : Pat<(node ty:$val, I32:$addr), + (!cast(inst # "_A32") 0, 0, I32:$addr, ty:$val)>; + def : Pat<(node ty:$val, I64:$addr), + (!cast(inst # "_A64") 0, 0, I64:$addr, ty:$val)>; +} -def : StorePatNoOffset; -def : StorePatNoOffset; -def : StorePatNoOffset; -def : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; // Select stores with a constant offset. -class StorePatImmOff : - Pat<(kind ty:$val, (operand I32:$addr, imm:$off)), - (inst 0, imm:$off, I32:$addr, ty:$val)>; - -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; +multiclass StorePatImmOff { + def : Pat<(kind ty:$val, (operand I32:$addr, imm:$off)), + (!cast(inst # "_A32") 0, imm:$off, I32:$addr, ty:$val)>; + def : Pat<(kind ty:$val, (operand I64:$addr, imm:$off)), + (!cast(inst # "_A64") 0, imm:$off, I64:$addr, ty:$val)>; +} + +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; // Select stores with just a constant offset. -class StorePatOffsetOnly : - Pat<(kind ty:$val, imm:$off), (inst 0, imm:$off, (CONST_I32 0), ty:$val)>; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; - -class StorePatGlobalAddrOffOnly : - Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)), - (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>, Requires<[IsNotPIC]>; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; +multiclass StorePatOffsetOnly { + def : Pat<(kind ty:$val, imm:$off), + (!cast(inst # "_A32") 0, imm:$off, (CONST_I32 0), ty:$val)>; + def : Pat<(kind ty:$val, imm:$off), + (!cast(inst # "_A64") 0, imm:$off, (CONST_I64 0), ty:$val)>; +} +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; + +multiclass StorePatGlobalAddrOffOnly { + def : Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)), + (!cast(inst # "_A32") 0, tglobaladdr:$off, (CONST_I32 0), + ty:$val)>, + Requires<[IsNotPIC]>; + def : Pat<(kind ty:$val, (WebAssemblywrapper tglobaladdr:$off)), + (!cast(inst # "_A64") 0, tglobaladdr:$off, (CONST_I64 0), + ty:$val)>, + Requires<[IsNotPIC]>; +} +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; // Truncating store. defm STORE8_I32 : WebAssemblyStore; @@ -270,35 +320,35 @@ defm STORE32_I64 : WebAssemblyStore; // Select truncating stores with no constant offset. -def : StorePatNoOffset; -def : StorePatNoOffset; -def : StorePatNoOffset; -def : StorePatNoOffset; -def : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; +defm : StorePatNoOffset; // Select truncating stores with a constant offset. -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatImmOff; // Select truncating stores with just a constant offset. -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatOffsetOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; -def : StorePatGlobalAddrOffOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatOffsetOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; +defm : StorePatGlobalAddrOffOnly; // Current memory size. defm MEMORY_SIZE_I32 : I<(outs I32:$dst), (ins i32imm:$flags), Index: llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -40,30 +40,42 @@ //===----------------------------------------------------------------------===// // Load: v128.load -let mayLoad = 1, UseNamedOperandTable = 1 in -defm LOAD_V128 : +let mayLoad = 1, UseNamedOperandTable = 1 in { +defm LOAD_V128_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], "v128.load\t$dst, ${off}(${addr})$p2align", "v128.load\t$off$p2align", 0>; +defm LOAD_V128_A64 : + SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, I64:$addr), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + "v128.load\t$dst, ${off}(${addr})$p2align", + "v128.load\t$off$p2align", 0>; +} // Def load and store patterns from WebAssemblyInstrMemory.td for vector types foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { -def : LoadPatNoOffset; -def : LoadPatImmOff; -def : LoadPatImmOff; -def : LoadPatOffsetOnly; -def : LoadPatGlobalAddrOffOnly; +defm : LoadPatNoOffset; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; } // vNxM.load_splat multiclass SIMDLoadSplat simdop> { - let mayLoad = 1, UseNamedOperandTable = 1 in - defm LOAD_SPLAT_#vec : + let mayLoad = 1, UseNamedOperandTable = 1 in { + defm LOAD_SPLAT_#vec#_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], vec#".load_splat\t$dst, ${off}(${addr})$p2align", vec#".load_splat\t$off$p2align", simdop>; + defm LOAD_SPLAT_#vec#_A64 : + SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, I64:$addr), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + vec#".load_splat\t$dst, ${off}(${addr})$p2align", + vec#".load_splat\t$off$p2align", simdop>; + } } defm "" : SIMDLoadSplat<"v8x16", 7>; @@ -78,38 +90,48 @@ foreach args = [["v16i8", "v8x16"], ["v8i16", "v16x8"], ["v4i32", "v32x4"], ["v2i64", "v64x2"], ["v4f32", "v32x4"], ["v2f64", "v64x2"]] in { -def : LoadPatNoOffset(args[0]), - load_splat, - !cast("LOAD_SPLAT_"#args[1])>; -def : LoadPatImmOff(args[0]), - load_splat, - regPlusImm, - !cast("LOAD_SPLAT_"#args[1])>; -def : LoadPatImmOff(args[0]), - load_splat, - or_is_add, - !cast("LOAD_SPLAT_"#args[1])>; -def : LoadPatOffsetOnly(args[0]), - load_splat, - !cast("LOAD_SPLAT_"#args[1])>; -def : LoadPatGlobalAddrOffOnly(args[0]), - load_splat, - !cast("LOAD_SPLAT_"#args[1])>; +defm : LoadPatNoOffset(args[0]), + load_splat, + "LOAD_SPLAT_"#args[1]>; +defm : LoadPatImmOff(args[0]), + load_splat, + regPlusImm, + "LOAD_SPLAT_"#args[1]>; +defm : LoadPatImmOff(args[0]), + load_splat, + or_is_add, + "LOAD_SPLAT_"#args[1]>; +defm : LoadPatOffsetOnly(args[0]), + load_splat, + "LOAD_SPLAT_"#args[1]>; +defm : LoadPatGlobalAddrOffOnly(args[0]), + load_splat, + "LOAD_SPLAT_"#args[1]>; } // Load and extend multiclass SIMDLoadExtend simdop> { let mayLoad = 1, UseNamedOperandTable = 1 in { - defm LOAD_EXTEND_S_#vec_t : + defm LOAD_EXTEND_S_#vec_t#_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], name#"_s\t$dst, ${off}(${addr})$p2align", name#"_s\t$off$p2align", simdop>; - defm LOAD_EXTEND_U_#vec_t : + defm LOAD_EXTEND_U_#vec_t#_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], name#"_u\t$dst, ${off}(${addr})$p2align", name#"_u\t$off$p2align", !add(simdop, 1)>; + defm LOAD_EXTEND_S_#vec_t#_A64 : + SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, I64:$addr), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + name#"_s\t$dst, ${off}(${addr})$p2align", + name#"_s\t$off$p2align", simdop>; + defm LOAD_EXTEND_U_#vec_t#_A64 : + SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, I64:$addr), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + name#"_u\t$dst, ${off}(${addr})$p2align", + name#"_u\t$off$p2align", !add(simdop, 1)>; } } @@ -121,34 +143,39 @@ foreach exts = [["sextloadv", "_S"], ["zextloadv", "_U"], ["extloadv", "_U"]] in { -def : LoadPatNoOffset(exts[0]#types[1]), - !cast("LOAD_EXTEND"#exts[1]#"_"#types[0])>; -def : LoadPatImmOff(exts[0]#types[1]), regPlusImm, - !cast("LOAD_EXTEND"#exts[1]#"_"#types[0])>; -def : LoadPatImmOff(exts[0]#types[1]), or_is_add, - !cast("LOAD_EXTEND"#exts[1]#"_"#types[0])>; -def : LoadPatOffsetOnly(exts[0]#types[1]), - !cast("LOAD_EXTEND"#exts[1]#"_"#types[0])>; -def : LoadPatGlobalAddrOffOnly(exts[0]#types[1]), - !cast("LOAD_EXTEND"#exts[1]#"_"#types[0])>; +defm : LoadPatNoOffset(exts[0]#types[1]), + "LOAD_EXTEND"#exts[1]#"_"#types[0]>; +defm : LoadPatImmOff(exts[0]#types[1]), regPlusImm, + "LOAD_EXTEND"#exts[1]#"_"#types[0]>; +defm : LoadPatImmOff(exts[0]#types[1]), or_is_add, + "LOAD_EXTEND"#exts[1]#"_"#types[0]>; +defm : LoadPatOffsetOnly(exts[0]#types[1]), + "LOAD_EXTEND"#exts[1]#"_"#types[0]>; +defm : LoadPatGlobalAddrOffOnly(exts[0]#types[1]), + "LOAD_EXTEND"#exts[1]#"_"#types[0]>; } // Store: v128.store -let mayStore = 1, UseNamedOperandTable = 1 in -defm STORE_V128 : +let mayStore = 1, UseNamedOperandTable = 1 in { +defm STORE_V128_A32 : SIMD_I<(outs), (ins P2Align:$p2align, offset32_op:$off, I32:$addr, V128:$vec), (outs), (ins P2Align:$p2align, offset32_op:$off), [], "v128.store\t${off}(${addr})$p2align, $vec", "v128.store\t$off$p2align", 11>; - +defm STORE_V128_A64 : + SIMD_I<(outs), (ins P2Align:$p2align, offset64_op:$off, I64:$addr, V128:$vec), + (outs), (ins P2Align:$p2align, offset64_op:$off), [], + "v128.store\t${off}(${addr})$p2align, $vec", + "v128.store\t$off$p2align", 11>; +} foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { // Def load and store patterns from WebAssemblyInstrMemory.td for vector types -def : StorePatNoOffset; -def : StorePatImmOff; -def : StorePatImmOff; -def : StorePatOffsetOnly; -def : StorePatGlobalAddrOffOnly; +defm : StorePatNoOffset; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatOffsetOnly; +defm : StorePatGlobalAddrOffOnly; } //===----------------------------------------------------------------------===//