diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h index 4bc77aa68668bc..6c819f396ddc1a 100644 --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -195,8 +195,8 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) { WASM_LOAD_STORE(ATOMIC_RMW8_U_CMPXCHG_I32) WASM_LOAD_STORE(ATOMIC_RMW8_U_CMPXCHG_I64) WASM_LOAD_STORE(LOAD8_SPLAT) - WASM_LOAD_STORE(LOAD_LANE_v16i8) - WASM_LOAD_STORE(STORE_LANE_v16i8) + WASM_LOAD_STORE(LOAD_LANE_I8x16) + WASM_LOAD_STORE(STORE_LANE_I8x16) return 0; WASM_LOAD_STORE(LOAD16_S_I32) WASM_LOAD_STORE(LOAD16_U_I32) @@ -223,8 +223,8 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) { WASM_LOAD_STORE(ATOMIC_RMW16_U_CMPXCHG_I32) WASM_LOAD_STORE(ATOMIC_RMW16_U_CMPXCHG_I64) WASM_LOAD_STORE(LOAD16_SPLAT) - WASM_LOAD_STORE(LOAD_LANE_v8i16) - WASM_LOAD_STORE(STORE_LANE_v8i16) + WASM_LOAD_STORE(LOAD_LANE_I16x8) + WASM_LOAD_STORE(STORE_LANE_I16x8) return 1; WASM_LOAD_STORE(LOAD_I32) WASM_LOAD_STORE(LOAD_F32) @@ -254,9 +254,9 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) { WASM_LOAD_STORE(MEMORY_ATOMIC_NOTIFY) WASM_LOAD_STORE(MEMORY_ATOMIC_WAIT32) WASM_LOAD_STORE(LOAD32_SPLAT) - WASM_LOAD_STORE(LOAD_ZERO_v4i32) - WASM_LOAD_STORE(LOAD_LANE_v4i32) - WASM_LOAD_STORE(STORE_LANE_v4i32) + WASM_LOAD_STORE(LOAD_ZERO_I32x4) + WASM_LOAD_STORE(LOAD_LANE_I32x4) + WASM_LOAD_STORE(STORE_LANE_I32x4) return 2; WASM_LOAD_STORE(LOAD_I64) WASM_LOAD_STORE(LOAD_F64) @@ -273,15 +273,15 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) { WASM_LOAD_STORE(ATOMIC_RMW_CMPXCHG_I64) WASM_LOAD_STORE(MEMORY_ATOMIC_WAIT64) WASM_LOAD_STORE(LOAD64_SPLAT) - WASM_LOAD_STORE(LOAD_EXTEND_S_v8i16) - WASM_LOAD_STORE(LOAD_EXTEND_U_v8i16) - WASM_LOAD_STORE(LOAD_EXTEND_S_v4i32) - WASM_LOAD_STORE(LOAD_EXTEND_U_v4i32) - WASM_LOAD_STORE(LOAD_EXTEND_S_v2i64) - WASM_LOAD_STORE(LOAD_EXTEND_U_v2i64) - WASM_LOAD_STORE(LOAD_ZERO_v2i64) - WASM_LOAD_STORE(LOAD_LANE_v2i64) - WASM_LOAD_STORE(STORE_LANE_v2i64) + WASM_LOAD_STORE(LOAD_EXTEND_S_I16x8) + WASM_LOAD_STORE(LOAD_EXTEND_U_I16x8) + WASM_LOAD_STORE(LOAD_EXTEND_S_I32x4) + WASM_LOAD_STORE(LOAD_EXTEND_U_I32x4) + WASM_LOAD_STORE(LOAD_EXTEND_S_I64x2) + WASM_LOAD_STORE(LOAD_EXTEND_U_I64x2) + WASM_LOAD_STORE(LOAD_ZERO_I64x2) + WASM_LOAD_STORE(LOAD_LANE_I64x2) + WASM_LOAD_STORE(STORE_LANE_I64x2) return 3; WASM_LOAD_STORE(LOAD_V128) WASM_LOAD_STORE(STORE_V128) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td index e48bbaebd47e92..df4de49ee4c8fb 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -37,6 +37,75 @@ def ImmI#SIZE : ImmLeaf; +class Vec { + ValueType vt; + ValueType lane_vt; + WebAssemblyRegClass lane_rc; + int lane_bits; + ImmLeaf lane_idx; + string prefix; + Vec split; +} + +def I8x16 : Vec { + let vt = v16i8; + let lane_vt = i32; + let lane_rc = I32; + let lane_bits = 8; + let lane_idx = LaneIdx16; + let prefix = "i8x16"; +} + +def I16x8 : Vec { + let vt = v8i16; + let lane_vt = i32; + let lane_rc = I32; + let lane_bits = 16; + let lane_idx = LaneIdx8; + let prefix = "i16x8"; + let split = I8x16; +} + +def I32x4 : Vec { + let vt = v4i32; + let lane_vt = i32; + let lane_rc = I32; + let lane_bits = 32; + let lane_idx = LaneIdx4; + let prefix = "i32x4"; + let split = I16x8; +} + +def I64x2 : Vec { + let vt = v2i64; + let lane_vt = i64; + let lane_rc = I64; + let lane_bits = 64; + let lane_idx = LaneIdx2; + let prefix = "i64x2"; + let split = I32x4; +} + +def F32x4 : Vec { + let vt = v4f32; + let lane_vt = f32; + let lane_rc = F32; + let lane_bits = 32; + let lane_idx = LaneIdx4; + let prefix = "f32x4"; +} + +def F64x2 : Vec { + let vt = v2f64; + let lane_vt = f64; + let lane_rc = F64; + let lane_bits = 64; + let lane_idx = LaneIdx2; + let prefix = "f64x2"; +} + +defvar AllVecs = [I8x16, I16x8, I32x4, I64x2, F32x4, F64x2]; + //===----------------------------------------------------------------------===// // Load and store //===----------------------------------------------------------------------===// @@ -56,12 +125,12 @@ defm LOAD_V128_A64 : } // Def load patterns from WebAssemblyInstrMemory.td for vector types -foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { -defm : LoadPatNoOffset; -defm : LoadPatImmOff; -defm : LoadPatImmOff; -defm : LoadPatOffsetOnly; -defm : LoadPatGlobalAddrOffOnly; +foreach vec = AllVecs in { +defm : LoadPatNoOffset; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; } // v128.loadX_splat @@ -94,87 +163,75 @@ def wasm_load_splat : SDNode<"WebAssemblyISD::LOAD_SPLAT", wasm_load_splat_t, [SDNPHasChain, SDNPMayLoad, SDNPMemOperand]>; def load_splat : PatFrag<(ops node:$addr), (wasm_load_splat node:$addr)>; -foreach args = [["v16i8", "8"], ["v8i16", "16"], ["v4i32", "32"], - ["v2i64", "64"], ["v4f32", "32"], ["v2f64", "64"]] in { -defm : LoadPatNoOffset(args[0]), - load_splat, - "LOAD"#args[1]#"_SPLAT">; -defm : LoadPatImmOff(args[0]), - load_splat, - regPlusImm, - "LOAD"#args[1]#"_SPLAT">; -defm : LoadPatImmOff(args[0]), - load_splat, - or_is_add, - "LOAD"#args[1]#"_SPLAT">; -defm : LoadPatOffsetOnly(args[0]), - load_splat, - "LOAD"#args[1]#"_SPLAT">; -defm : LoadPatGlobalAddrOffOnly(args[0]), - load_splat, - "LOAD"#args[1]#"_SPLAT">; +foreach vec = AllVecs in { +defvar inst = "LOAD"#vec.lane_bits#"_SPLAT"; +defm : LoadPatNoOffset; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; } // Load and extend -multiclass SIMDLoadExtend simdop> { +multiclass SIMDLoadExtend simdop> { + defvar signed = vec.prefix#".load"#loadPat#"_s"; + defvar unsigned = vec.prefix#".load"#loadPat#"_u"; let mayLoad = 1, UseNamedOperandTable = 1 in { - defm LOAD_EXTEND_S_#vec_t#_A32 : + defm LOAD_EXTEND_S_#vec#_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#_A32 : + signed#"\t$dst, ${off}(${addr})$p2align", + signed#"\t$off$p2align", simdop>; + defm LOAD_EXTEND_U_#vec#_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 : + unsigned#"\t$dst, ${off}(${addr})$p2align", + unsigned#"\t$off$p2align", !add(simdop, 1)>; + defm LOAD_EXTEND_S_#vec#_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 : + signed#"\t$dst, ${off}(${addr})$p2align", + signed#"\t$off$p2align", simdop>; + defm LOAD_EXTEND_U_#vec#_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)>; + unsigned#"\t$dst, ${off}(${addr})$p2align", + unsigned#"\t$off$p2align", !add(simdop, 1)>; } } -defm "" : SIMDLoadExtend; -defm "" : SIMDLoadExtend; -defm "" : SIMDLoadExtend; - -foreach types = [[v8i16, i8], [v4i32, i16], [v2i64, i32]] in -foreach exts = [["sextloadv", "_S"], - ["zextloadv", "_U"], - ["extloadv", "_U"]] in { -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]>; +defm "" : SIMDLoadExtend; +defm "" : SIMDLoadExtend; +defm "" : SIMDLoadExtend; + +foreach vec = [I16x8, I32x4, I64x2] in +foreach exts = [["sextloadvi", "_S"], + ["zextloadvi", "_U"], + ["extloadvi", "_U"]] in { +defvar loadpat = !cast(exts[0]#vec.split.lane_bits); +defvar inst = "LOAD_EXTEND"#exts[1]#"_"#vec; +defm : LoadPatNoOffset; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; } // Load lane into zero vector -multiclass SIMDLoadZero simdop> { +multiclass SIMDLoadZero simdop> { + defvar name = "v128.load"#vec.lane_bits#"_zero"; let mayLoad = 1, UseNamedOperandTable = 1 in { - defm LOAD_ZERO_#vec_t#_A32 : + defm LOAD_ZERO_#vec#_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, I32:$addr), (outs), (ins P2Align:$p2align, offset32_op:$off), [], name#"\t$dst, ${off}(${addr})$p2align", name#"\t$off$p2align", simdop>; - defm LOAD_ZERO_#vec_t#_A64 : + defm LOAD_ZERO_#vec#_A64 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, I64:$addr), (outs), (ins P2Align:$p2align, offset64_op:$off), [], @@ -185,35 +242,31 @@ multiclass SIMDLoadZero simdop> { // TODO: Also support v4f32 and v2f64 once the instructions are merged // to the proposal -defm "" : SIMDLoadZero; -defm "" : SIMDLoadZero; - -defm : LoadPatNoOffset; -defm : LoadPatNoOffset; - -defm : LoadPatImmOff; -defm : LoadPatImmOff; - -defm : LoadPatImmOff; -defm : LoadPatImmOff; - -defm : LoadPatOffsetOnly; -defm : LoadPatOffsetOnly; - -defm : LoadPatGlobalAddrOffOnly; -defm : LoadPatGlobalAddrOffOnly; +defm "" : SIMDLoadZero; +defm "" : SIMDLoadZero; + +foreach vec = [I32x4, I64x2] in { +defvar loadpat = !cast("int_wasm_load"#vec.lane_bits#"_zero"); +defvar inst = "LOAD_ZERO_"#vec; +defm : LoadPatNoOffset; +defm : LoadPatImmOff; +defm : LoadPatImmOff; +defm : LoadPatOffsetOnly; +defm : LoadPatGlobalAddrOffOnly; +} // Load lane -multiclass SIMDLoadLane simdop> { +multiclass SIMDLoadLane simdop> { + defvar name = "v128.load"#vec.lane_bits#"_lane"; let mayLoad = 1, UseNamedOperandTable = 1 in { - defm LOAD_LANE_#vec_t#_A32 : + defm LOAD_LANE_#vec#_A32 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset32_op:$off, vec_i8imm_op:$idx, I32:$addr, V128:$vec), (outs), (ins P2Align:$p2align, offset32_op:$off, vec_i8imm_op:$idx), [], name#"\t$dst, ${off}(${addr})$p2align, $vec, $idx", name#"\t$off$p2align, $idx", simdop>; - defm LOAD_LANE_#vec_t#_A64 : + defm LOAD_LANE_#vec#_A64 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, vec_i8imm_op:$idx, I64:$addr, V128:$vec), @@ -225,25 +278,29 @@ multiclass SIMDLoadLane simdop> { // TODO: Also support v4f32 and v2f64 once the instructions are merged // to the proposal -defm "" : SIMDLoadLane; -defm "" : SIMDLoadLane; -defm "" : SIMDLoadLane; -defm "" : SIMDLoadLane; +defm "" : SIMDLoadLane; +defm "" : SIMDLoadLane; +defm "" : SIMDLoadLane; +defm "" : SIMDLoadLane; // Select loads with no constant offset. -multiclass LoadLanePatNoOffset { - def : Pat<(ty (kind (i32 I32:$addr), (ty V128:$vec), (i32 lane_imm_t:$idx))), - (!cast("LOAD_LANE_"#ty#"_A32") 0, 0, imm:$idx, I32:$addr, V128:$vec)>, +multiclass LoadLanePatNoOffset { + defvar load_lane_a32 = !cast("LOAD_LANE_"#vec#"_A32"); + defvar load_lane_a64 = !cast("LOAD_LANE_"#vec#"_A64"); + def : Pat<(vec.vt (kind (i32 I32:$addr), + (vec.vt V128:$vec), (i32 vec.lane_idx:$idx))), + (load_lane_a32 0, 0, imm:$idx, I32:$addr, V128:$vec)>, Requires<[HasAddr32]>; - def : Pat<(ty (kind (i64 I64:$addr), (ty V128:$vec), (i32 lane_imm_t:$idx))), - (!cast("LOAD_LANE_"#ty#"_A64") 0, 0, imm:$idx, I64:$addr, V128:$vec)>, + def : Pat<(vec.vt (kind (i64 I64:$addr), + (vec.vt V128:$vec), (i32 vec.lane_idx:$idx))), + (load_lane_a64 0, 0, imm:$idx, I64:$addr, V128:$vec)>, Requires<[HasAddr64]>; } -defm : LoadLanePatNoOffset; -defm : LoadLanePatNoOffset; -defm : LoadLanePatNoOffset; -defm : LoadLanePatNoOffset; +defm : LoadLanePatNoOffset; +defm : LoadLanePatNoOffset; +defm : LoadLanePatNoOffset; +defm : LoadLanePatNoOffset; // TODO: Also support the other load patterns for load_lane once the instructions // are merged to the proposal. @@ -263,25 +320,26 @@ defm STORE_V128_A64 : } // Def store patterns from WebAssemblyInstrMemory.td for vector types -foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { -defm : StorePatNoOffset; -defm : StorePatImmOff; -defm : StorePatImmOff; -defm : StorePatOffsetOnly; -defm : StorePatGlobalAddrOffOnly; +foreach vec = AllVecs in { +defm : StorePatNoOffset; +defm : StorePatImmOff; +defm : StorePatImmOff; +defm : StorePatOffsetOnly; +defm : StorePatGlobalAddrOffOnly; } // Store lane -multiclass SIMDStoreLane simdop> { +multiclass SIMDStoreLane simdop> { + defvar name = "v128.store"#vec.lane_bits#"_lane"; let mayStore = 1, UseNamedOperandTable = 1 in { - defm STORE_LANE_#vec_t#_A32 : + defm STORE_LANE_#vec#_A32 : SIMD_I<(outs), (ins P2Align:$p2align, offset32_op:$off, vec_i8imm_op:$idx, I32:$addr, V128:$vec), (outs), (ins P2Align:$p2align, offset32_op:$off, vec_i8imm_op:$idx), [], name#"\t${off}(${addr})$p2align, $vec, $idx", name#"\t$off$p2align, $idx", simdop>; - defm STORE_LANE_#vec_t#_A64 : + defm STORE_LANE_#vec#_A64 : SIMD_I<(outs V128:$dst), (ins P2Align:$p2align, offset64_op:$off, vec_i8imm_op:$idx, I64:$addr, V128:$vec), @@ -293,27 +351,27 @@ multiclass SIMDStoreLane simdop> { // TODO: Also support v4f32 and v2f64 once the instructions are merged // to the proposal -defm "" : SIMDStoreLane; -defm "" : SIMDStoreLane; -defm "" : SIMDStoreLane; -defm "" : SIMDStoreLane; +defm "" : SIMDStoreLane; +defm "" : SIMDStoreLane; +defm "" : SIMDStoreLane; +defm "" : SIMDStoreLane; // Select stores with no constant offset. -multiclass StoreLanePatNoOffset { - def : Pat<(kind (i32 I32:$addr), (ty V128:$vec), (i32 lane_imm_t:$idx)), - (!cast("STORE_LANE_"#ty#"_A32") - 0, 0, imm:$idx, I32:$addr, ty:$vec)>, +multiclass StoreLanePatNoOffset { + def : Pat<(kind (i32 I32:$addr), (vec.vt V128:$vec), (i32 vec.lane_idx:$idx)), + (!cast("STORE_LANE_"#vec#"_A32") + 0, 0, imm:$idx, I32:$addr, vec.vt:$vec)>, Requires<[HasAddr32]>; - def : Pat<(kind (i64 I64:$addr), (ty V128:$vec), (i32 lane_imm_t:$idx)), - (!cast("STORE_LANE_"#ty#"_A64") - 0, 0, imm:$idx, I64:$addr, ty:$vec)>, + def : Pat<(kind (i64 I64:$addr), (vec.vt V128:$vec), (i32 vec.lane_idx:$idx)), + (!cast("STORE_LANE_"#vec#"_A64") + 0, 0, imm:$idx, I64:$addr, vec.vt:$vec)>, Requires<[HasAddr64]>; } -defm : StoreLanePatNoOffset; -defm : StoreLanePatNoOffset; -defm : StoreLanePatNoOffset; -defm : StoreLanePatNoOffset; +defm : StoreLanePatNoOffset; +defm : StoreLanePatNoOffset; +defm : StoreLanePatNoOffset; +defm : StoreLanePatNoOffset; // TODO: Also support the other store patterns for store_lane once the // instructions are merged to the proposal.