diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -32,85 +32,135 @@ //===----------------------------------------------------------------------===// 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 { + def : 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 +181,8 @@ //===----------------------------------------------------------------------===// multiclass AtomicLoad { - defm "" : WebAssemblyLoad, - Requires<[HasAtomics]>; + defm "" : WebAssemblyLoad; } defm ATOMIC_LOAD_I32 : AtomicLoad; @@ -140,23 +190,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 +255,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] @@ -286,8 +336,8 @@ // Select stores with no constant offset. class AStorePatNoOffset : Pat<(kind I32:$addr, ty:$val), (inst 0, 0, I32:$addr, ty:$val)>; -def : AStorePatNoOffset; -def : AStorePatNoOffset; +def : AStorePatNoOffset; +def : AStorePatNoOffset; // Select stores with a constant offset. @@ -295,22 +345,22 @@ 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; +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; } // Predicates = [HasAtomics] @@ -336,36 +386,36 @@ 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; // 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; // 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 : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; +def : AStorePatGlobalAddrOffOnly; } // Predicates = [HasAtomics] @@ -502,18 +552,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 +665,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 +766,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 @@ -820,6 +870,6 @@ let Predicates = [HasAtomics] in defm : TerRMWTruncExtPattern< atomic_cmp_swap_8, atomic_cmp_swap_16, atomic_cmp_swap_32, atomic_cmp_swap_64, - ATOMIC_RMW8_U_CMPXCHG_I32, ATOMIC_RMW16_U_CMPXCHG_I32, - ATOMIC_RMW8_U_CMPXCHG_I64, ATOMIC_RMW16_U_CMPXCHG_I64, - ATOMIC_RMW32_U_CMPXCHG_I64>; + ATOMIC_RMW8_U_CMPXCHG_I32, "ATOMIC_RMW16_U_CMPXCHG_I32, + ATOMIC_RMW8_U_CMPXCHG_I64, "ATOMIC_RMW16_U_CMPXCHG_I64, + ATOMIC_RMW32_U_CMPXCHG_I64">; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td +++ b/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"; diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrMemory.td +++ b/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),