diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h --- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h +++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCTargetDesc.h @@ -191,6 +191,8 @@ case WebAssembly::ATOMIC_RMW8_U_CMPXCHG_I32_S: case WebAssembly::ATOMIC_RMW8_U_CMPXCHG_I64: case WebAssembly::ATOMIC_RMW8_U_CMPXCHG_I64_S: + case WebAssembly::LOAD_SPLAT_v8x16: + case WebAssembly::LOAD_SPLAT_v8x16_S: return 0; case WebAssembly::LOAD16_S_I32: case WebAssembly::LOAD16_S_I32_S: @@ -240,6 +242,8 @@ case WebAssembly::ATOMIC_RMW16_U_CMPXCHG_I32_S: case WebAssembly::ATOMIC_RMW16_U_CMPXCHG_I64: case WebAssembly::ATOMIC_RMW16_U_CMPXCHG_I64_S: + case WebAssembly::LOAD_SPLAT_v16x8: + case WebAssembly::LOAD_SPLAT_v16x8_S: return 1; case WebAssembly::LOAD_I32: case WebAssembly::LOAD_I32_S: @@ -295,6 +299,8 @@ case WebAssembly::ATOMIC_NOTIFY_S: case WebAssembly::ATOMIC_WAIT_I32: case WebAssembly::ATOMIC_WAIT_I32_S: + case WebAssembly::LOAD_SPLAT_v32x4: + case WebAssembly::LOAD_SPLAT_v32x4_S: return 2; case WebAssembly::LOAD_I64: case WebAssembly::LOAD_I64_S: @@ -324,6 +330,8 @@ case WebAssembly::ATOMIC_RMW_CMPXCHG_I64_S: case WebAssembly::ATOMIC_WAIT_I64: case WebAssembly::ATOMIC_WAIT_I64_S: + case WebAssembly::LOAD_SPLAT_v64x2: + case WebAssembly::LOAD_SPLAT_v64x2_S: return 3; case WebAssembly::LOAD_V128: case WebAssembly::LOAD_V128_S: diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def --- a/llvm/lib/Target/WebAssembly/WebAssemblyISD.def +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISD.def @@ -29,6 +29,7 @@ HANDLE_NODETYPE(VEC_SHL) HANDLE_NODETYPE(VEC_SHR_S) HANDLE_NODETYPE(VEC_SHR_U) +HANDLE_NODETYPE(LOAD_SPLAT) HANDLE_NODETYPE(THROW) HANDLE_NODETYPE(MEMORY_COPY) HANDLE_NODETYPE(MEMORY_FILL) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyISelLowering.cpp @@ -1358,7 +1358,16 @@ } } // Use a splat for the initial vector - SDValue Result = DAG.getSplatBuildVector(VecT, DL, SplatValue); + SDValue Result; + // Possibly a load_splat + LoadSDNode *SplattedLoad; + if (Subtarget->hasUnimplementedSIMD128() && + (SplattedLoad = dyn_cast(SplatValue)) && + SplattedLoad->getMemoryVT() == VecT.getVectorElementType()) { + Result = DAG.getNode(WebAssemblyISD::LOAD_SPLAT, DL, VecT, SplatValue); + } else { + Result = DAG.getSplatBuildVector(VecT, DL, SplatValue); + } // Add replace_lane instructions for other values for (size_t I = 0; I < Lanes; ++I) { const SDValue &Lane = Op->getOperand(I); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td --- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -56,6 +56,54 @@ def : LoadPatGlobalAddrOffOnly; } +// vNxM.load_splat +multiclass SIMDLoadSplat simdop> { + let mayLoad = 1, UseNamedOperandTable = 1, + Predicates = [HasUnimplementedSIMD128] in + defm LOAD_SPLAT_#vec : + 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 "" : SIMDLoadSplat<"v8x16", 194>; +defm "" : SIMDLoadSplat<"v16x8", 195>; +defm "" : SIMDLoadSplat<"v32x4", 196>; +defm "" : SIMDLoadSplat<"v64x2", 197>; + +def wasm_load_splat_t : SDTypeProfile<1, 1, []>; +def wasm_load_splat : SDNode<"WebAssemblyISD::LOAD_SPLAT", wasm_load_splat_t>; + +foreach args = [["v16i8", "i32", "extloadi8"], ["v8i16", "i32", "extloadi16"], + ["v4i32", "i32", "load"], ["v2i64", "i64", "load"], + ["v4f32", "f32", "load"], ["v2f64", "f64", "load"]] in +def load_splat_#args[0] : + PatFrag<(ops node:$addr), (wasm_load_splat + (!cast(args[1]) (!cast(args[2]) node:$addr)))>; + +let Predicates = [HasUnimplementedSIMD128] in +foreach args = [["v16i8", "v8x16"], ["v8i16", "v16x8"], ["v4i32", "v32x4"], + ["v2i64", "v64x2"], ["v4f32", "v32x4"], ["v2f64", "v64x2"]] in { +def : LoadPatNoOffset(args[0]), + !cast("load_splat_"#args[0]), + !cast("LOAD_SPLAT_"#args[1])>; +def : LoadPatImmOff(args[0]), + !cast("load_splat_"#args[0]), + regPlusImm, + !cast("LOAD_SPLAT_"#args[1])>; +def : LoadPatImmOff(args[0]), + !cast("load_splat_"#args[0]), + or_is_add, + !cast("LOAD_SPLAT_"#args[1])>; +def : LoadPatOffsetOnly(args[0]), + !cast("load_splat_"#args[0]), + !cast("LOAD_SPLAT_"#args[1])>; +def : LoadPatGlobalAddrOffOnly(args[0]), + !cast("load_splat_"#args[0]), + !cast("LOAD_SPLAT_"#args[1])>; +} + // Store: v128.store let mayStore = 1, UseNamedOperandTable = 1 in defm STORE_V128 : @@ -64,8 +112,8 @@ "v128.store\t${off}(${addr})$p2align, $vec", "v128.store\t$off$p2align", 1>; -foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { // Def load and store patterns from WebAssemblyInstrMemory.td for vector types +foreach vec_t = [v16i8, v8i16, v4i32, v2i64, v4f32, v2f64] in { def : StorePatNoOffset; def : StorePatImmOff; def : StorePatImmOff; diff --git a/llvm/test/CodeGen/WebAssembly/simd-offset.ll b/llvm/test/CodeGen/WebAssembly/simd-offset.ll --- a/llvm/test/CodeGen/WebAssembly/simd-offset.ll +++ b/llvm/test/CodeGen/WebAssembly/simd-offset.ll @@ -20,6 +20,19 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8: +; SIMD128-VM-NOT: v8x16.load_splat +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8 (i32) -> (v128){{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8(i8* %p) { + %e = load i8, i8* %p + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_with_folded_offset (i32) -> (v128){{$}} @@ -33,6 +46,21 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_with_folded_offset(i8* %p) { + %q = ptrtoint i8* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to i8* + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_with_folded_gep_offset (i32) -> (v128){{$}} @@ -44,6 +72,19 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 1($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_with_folded_gep_offset(i8* %p) { + %s = getelementptr inbounds i8, i8* %p, i32 1 + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} @@ -57,6 +98,21 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -1{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_with_unfolded_gep_negative_offset(i8* %p) { + %s = getelementptr inbounds i8, i8* %p, i32 -1 + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_with_unfolded_offset (i32) -> (v128){{$}} @@ -72,6 +128,23 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_with_unfolded_offset(i8* %p) { + %q = ptrtoint i8* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to i8* + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_with_unfolded_gep_offset (i32) -> (v128){{$}} @@ -85,6 +158,21 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 1{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_with_unfolded_gep_offset(i8* %p) { + %s = getelementptr i8, i8* %p, i32 1 + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_from_numeric_address () -> (v128){{$}} @@ -97,6 +185,20 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <16 x i8> @load_splat_v16i8_from_numeric_address() { + %s = inttoptr i32 32 to i8* + %e = load i8, i8* %s + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: load_v16i8_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v16i8_from_global_address () -> (v128){{$}} @@ -109,6 +211,20 @@ ret <16 x i8> %v } +; CHECK-LABEL: load_splat_v16i8_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v16i8_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v8x16.load_splat $push[[R:[0-9]+]]=, gv_i8($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_i8 = global i8 42 +define <16 x i8> @load_splat_v16i8_from_global_address() { + %e = load i8, i8* @gv_i8 + %v1 = insertelement <16 x i8> undef, i8 %e, i32 0 + %v2 = shufflevector <16 x i8> %v1, <16 x i8> undef, <16 x i32> zeroinitializer + ret <16 x i8> %v2 +} + ; CHECK-LABEL: store_v16i8: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype store_v16i8 (v128, i32) -> (){{$}} @@ -210,6 +326,18 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16 (i32) -> (v128){{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16(i16* %p) { + %e = load i16, i16* %p + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_with_folded_offset (i32) -> (v128){{$}} @@ -223,6 +351,21 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16_with_folded_offset(i16* %p) { + %q = ptrtoint i16* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to i16* + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_with_folded_gep_offset (i32) -> (v128){{$}} @@ -234,6 +377,19 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 2($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16_with_folded_gep_offset(i16* %p) { + %s = getelementptr inbounds i16, i16* %p, i32 1 + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} @@ -247,6 +403,21 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -2{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16_with_unfolded_gep_negative_offset(i16* %p) { + %s = getelementptr inbounds i16, i16* %p, i32 -1 + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_with_unfolded_offset (i32) -> (v128){{$}} @@ -262,6 +433,23 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[L0:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[L0]]{{$}} +define <8 x i16> @load_splat_v8i16_with_unfolded_offset(i16* %p) { + %q = ptrtoint i16* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to i16* + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_with_unfolded_gep_offset (i32) -> (v128){{$}} @@ -275,6 +463,21 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 2{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16_with_unfolded_gep_offset(i16* %p) { + %s = getelementptr i16, i16* %p, i32 1 + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_from_numeric_address () -> (v128){{$}} @@ -287,6 +490,20 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <8 x i16> @load_splat_v8i16_from_numeric_address() { + %s = inttoptr i32 32 to i16* + %e = load i16, i16* %s + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: load_v8i16_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v8i16_from_global_address () -> (v128){{$}} @@ -299,6 +516,20 @@ ret <8 x i16> %v } +; CHECK-LABEL: load_splat_v8i16_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v8i16_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v16x8.load_splat $push[[R:[0-9]+]]=, gv_i16($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_i16 = global i16 42 +define <8 x i16> @load_splat_v8i16_from_global_address() { + %e = load i16, i16* @gv_i16 + %v1 = insertelement <8 x i16> undef, i16 %e, i32 0 + %v2 = shufflevector <8 x i16> %v1, <8 x i16> undef, <8 x i32> zeroinitializer + ret <8 x i16> %v2 +} + ; CHECK-LABEL: store_v8i16: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype store_v8i16 (v128, i32) -> (){{$}} @@ -400,6 +631,17 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32 (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat +define <4 x i32> @load_splat_v4i32(i32* %addr) { + %e = load i32, i32* %addr, align 4 + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_with_folded_offset (i32) -> (v128){{$}} @@ -413,6 +655,21 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_with_folded_offset(i32* %p) { + %q = ptrtoint i32* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to i32* + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_with_folded_gep_offset (i32) -> (v128){{$}} @@ -424,6 +681,19 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 4($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_with_folded_gep_offset(i32* %p) { + %s = getelementptr inbounds i32, i32* %p, i32 1 + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} @@ -437,6 +707,21 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -4{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_with_unfolded_gep_negative_offset(i32* %p) { + %s = getelementptr inbounds i32, i32* %p, i32 -1 + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_with_unfolded_offset (i32) -> (v128){{$}} @@ -452,6 +737,23 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_with_unfolded_offset(i32* %p) { + %q = ptrtoint i32* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to i32* + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_with_unfolded_gep_offset (i32) -> (v128){{$}} @@ -465,6 +767,21 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 4{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_with_unfolded_gep_offset(i32* %p) { + %s = getelementptr i32, i32* %p, i32 1 + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_from_numeric_address () -> (v128){{$}} @@ -477,6 +794,20 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x i32> @load_splat_v4i32_from_numeric_address() { + %s = inttoptr i32 32 to i32* + %e = load i32, i32* %s + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: load_v4i32_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4i32_from_global_address () -> (v128){{$}} @@ -489,6 +820,20 @@ ret <4 x i32> %v } +; CHECK-LABEL: load_splat_v4i32_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4i32_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, gv_i32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_i32 = global i32 42 +define <4 x i32> @load_splat_v4i32_from_global_address() { + %e = load i32, i32* @gv_i32 + %v1 = insertelement <4 x i32> undef, i32 %e, i32 0 + %v2 = shufflevector <4 x i32> %v1, <4 x i32> undef, <4 x i32> zeroinitializer + ret <4 x i32> %v2 +} + ; CHECK-LABEL: store_v4i32: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype store_v4i32 (v128, i32) -> (){{$}} @@ -591,6 +936,19 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64 (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64(i64* %p) { + %e = load i64, i64* %p + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -605,6 +963,22 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_with_folded_offset(i64* %p) { + %q = ptrtoint i64* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to i64* + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -617,6 +991,20 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 8($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_with_folded_gep_offset(i64* %p) { + %s = getelementptr inbounds i64, i64* %p, i32 1 + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -631,6 +1019,22 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -8{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_with_unfolded_gep_negative_offset(i64* %p) { + %s = getelementptr inbounds i64, i64* %p, i32 -1 + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -647,6 +1051,24 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_with_unfolded_offset(i64* %p) { + %q = ptrtoint i64* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to i64* + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -661,6 +1083,22 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 8{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_with_unfolded_gep_offset(i64* %p) { + %s = getelementptr i64, i64* %p, i32 1 + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -674,6 +1112,21 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @load_splat_v2i64_from_numeric_address() { + %s = inttoptr i32 32 to i64* + %e = load i64, i64* %s + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: load_v2i64_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -687,6 +1140,21 @@ ret <2 x i64> %v } +; CHECK-LABEL: load_splat_v2i64_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2i64_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, gv_i64($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_i64 = global i64 42 +define <2 x i64> @load_splat_v2i64_from_global_address() { + %e = load i64, i64* @gv_i64 + %v1 = insertelement <2 x i64> undef, i64 %e, i32 0 + %v2 = shufflevector <2 x i64> %v1, <2 x i64> undef, <2 x i32> zeroinitializer + ret <2 x i64> %v2 +} + ; CHECK-LABEL: store_v2i64: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -796,6 +1264,18 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32 (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32(float* %p) { + %e = load float, float* %p + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_with_folded_offset (i32) -> (v128){{$}} @@ -809,6 +1289,21 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_with_folded_offset(float* %p) { + %q = ptrtoint float* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to float* + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_with_folded_gep_offset (i32) -> (v128){{$}} @@ -820,6 +1315,19 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 4($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_with_folded_gep_offset(float* %p) { + %s = getelementptr inbounds float, float* %p, i32 1 + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} @@ -833,6 +1341,21 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -4{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_with_unfolded_gep_negative_offset(float* %p) { + %s = getelementptr inbounds float, float* %p, i32 -1 + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_with_unfolded_offset (i32) -> (v128){{$}} @@ -848,6 +1371,23 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_with_unfolded_offset(float* %p) { + %q = ptrtoint float* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to float* + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_with_unfolded_gep_offset (i32) -> (v128){{$}} @@ -861,6 +1401,21 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 4{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_with_unfolded_gep_offset(float* %p) { + %s = getelementptr float, float* %p, i32 1 + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_from_numeric_address () -> (v128){{$}} @@ -873,6 +1428,20 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <4 x float> @load_splat_v4f32_from_numeric_address() { + %s = inttoptr i32 32 to float* + %e = load float, float* %s + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: load_v4f32_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype load_v4f32_from_global_address () -> (v128){{$}} @@ -885,6 +1454,20 @@ ret <4 x float> %v } +; CHECK-LABEL: load_splat_v4f32_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v4f32_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v32x4.load_splat $push[[R:[0-9]+]]=, gv_f32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_f32 = global float 42. +define <4 x float> @load_splat_v4f32_from_global_address() { + %e = load float, float* @gv_f32 + %v1 = insertelement <4 x float> undef, float %e, i32 0 + %v2 = shufflevector <4 x float> %v1, <4 x float> undef, <4 x i32> zeroinitializer + ret <4 x float> %v2 +} + ; CHECK-LABEL: store_v4f32: ; NO-SIMD128-NOT: v128 ; SIMD128-NEXT: .functype store_v4f32 (v128, i32) -> (){{$}} @@ -987,6 +1570,19 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64 (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64(double* %p) { + %e = load double, double* %p + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_with_folded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1001,6 +1597,22 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_with_folded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_with_folded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 16($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_with_folded_offset(double* %p) { + %q = ptrtoint double* %p to i32 + %r = add nuw i32 %q, 16 + %s = inttoptr i32 %r to double* + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_with_folded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1013,6 +1625,20 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_with_folded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_with_folded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 8($0){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_with_folded_gep_offset(double* %p) { + %s = getelementptr inbounds double, double* %p, i32 1 + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_with_unfolded_gep_negative_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1027,6 +1653,22 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_with_unfolded_gep_negative_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_with_unfolded_gep_negative_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, -8{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_with_unfolded_gep_negative_offset(double* %p) { + %s = getelementptr inbounds double, double* %p, i32 -1 + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_with_unfolded_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1043,6 +1685,24 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_with_unfolded_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_with_unfolded_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 16{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_with_unfolded_offset(double* %p) { + %q = ptrtoint double* %p to i32 + %r = add nsw i32 %q, 16 + %s = inttoptr i32 %r to double* + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_with_unfolded_gep_offset: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1057,6 +1717,22 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_with_unfolded_gep_offset: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_with_unfolded_gep_offset (i32) -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 8{{$}} +; SIMD128-NEXT: i32.add $push[[L1:[0-9]+]]=, $0, $pop[[L0]]{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 0($pop[[L1]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_with_unfolded_gep_offset(double* %p) { + %s = getelementptr double, double* %p, i32 1 + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_from_numeric_address: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1070,6 +1746,21 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_from_numeric_address: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_from_numeric_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, 32($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x double> @load_splat_v2f64_from_numeric_address() { + %s = inttoptr i32 32 to double* + %e = load double, double* %s + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: load_v2f64_from_global_address: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128 @@ -1083,6 +1774,21 @@ ret <2 x double> %v } +; CHECK-LABEL: load_splat_v2f64_from_global_address: +; NO-SIMD128-NOT: v128 +; SIMD128-VM-NOT: v128 +; SIMD128-NEXT: .functype load_splat_v2f64_from_global_address () -> (v128){{$}} +; SIMD128-NEXT: i32.const $push[[L0:[0-9]+]]=, 0{{$}} +; SIMD128-NEXT: v64x2.load_splat $push[[R:[0-9]+]]=, gv_f64($pop[[L0]]){{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +@gv_f64 = global double 42. +define <2 x double> @load_splat_v2f64_from_global_address() { + %e = load double, double* @gv_f64 + %v1 = insertelement <2 x double> undef, double %e, i32 0 + %v2 = shufflevector <2 x double> %v1, <2 x double> undef, <2 x i32> zeroinitializer + ret <2 x double> %v2 +} + ; CHECK-LABEL: store_v2f64: ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128