Index: llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -579,10 +579,16 @@ defm SHR_S : SIMDShiftInt; defm SHR_U : SIMDShiftInt; -// Truncate i64 shift operands to i32s -foreach shifts = [[shl, SHL_v2i64], [sra, SHR_S_v2i64], [srl, SHR_U_v2i64]] in +// Truncate i64 shift operands to i32s, except if they are already i32s +foreach shifts = [[shl, SHL_v2i64], [sra, SHR_S_v2i64], [srl, SHR_U_v2i64]] in { +def : Pat<(v2i64 (shifts[0] + (v2i64 V128:$vec), + (v2i64 (splat2 (i64 (sext I32:$x)))) + )), + (v2i64 (shifts[1] (v2i64 V128:$vec), (i32 I32:$x)))>; def : Pat<(v2i64 (shifts[0] (v2i64 V128:$vec), (v2i64 (splat2 I64:$x)))), (v2i64 (shifts[1] (v2i64 V128:$vec), (I32_WRAP_I64 I64:$x)))>; +} // 2xi64 shifts with constant shift amounts are custom lowered to avoid wrapping def wasm_shift_t : SDTypeProfile<1, 2, Index: llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll +++ llvm/trunk/test/CodeGen/WebAssembly/simd-arith.ll @@ -730,13 +730,26 @@ ret <2 x i64> %a } -; CHECK-LABEL: shl_nozext_v2i64: +; CHECK-LABEL: shl_sext_v2i64: ; NO-SIMD128-NOT: i64x2 -; SIMD128-NEXT: .functype shl_nozext_v2i64 (v128, i64) -> (v128){{$}} +; SIMD128-NEXT: .functype shl_sext_v2i64 (v128, i32) -> (v128){{$}} +; SIMD128-NEXT: i64x2.shl $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @shl_sext_v2i64(<2 x i64> %v, i32 %x) { + %x2 = sext i32 %x to i64 + %t = insertelement <2 x i64> undef, i64 %x2, i32 0 + %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> + %a = shl <2 x i64> %v, %s + ret <2 x i64> %a +} + +; CHECK-LABEL: shl_noext_v2i64: +; NO-SIMD128-NOT: i64x2 +; SIMD128-NEXT: .functype shl_noext_v2i64 (v128, i64) -> (v128){{$}} ; SIMD128-NEXT: i32.wrap_i64 $push[[L0:[0-9]+]]=, $1{{$}} ; SIMD128-NEXT: i64x2.shl $push[[R:[0-9]+]]=, $0, $pop[[L0]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} -define <2 x i64> @shl_nozext_v2i64(<2 x i64> %v, i64 %x) { +define <2 x i64> @shl_noext_v2i64(<2 x i64> %v, i64 %x) { %t = insertelement <2 x i64> undef, i64 %x, i32 0 %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> %a = shl <2 x i64> %v, %s @@ -784,13 +797,26 @@ ret <2 x i64> %a } -; CHECK-LABEL: shr_s_nozext_v2i64: +; CHECK-LABEL: shr_s_sext_v2i64: ; NO-SIMD128-NOT: i64x2 -; SIMD128-NEXT: .functype shr_s_nozext_v2i64 (v128, i64) -> (v128){{$}} +; SIMD128-NEXT: .functype shr_s_sext_v2i64 (v128, i32) -> (v128){{$}} +; SIMD128-NEXT: i64x2.shr_s $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @shr_s_sext_v2i64(<2 x i64> %v, i32 %x) { + %x2 = sext i32 %x to i64 + %t = insertelement <2 x i64> undef, i64 %x2, i32 0 + %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> + %a = ashr <2 x i64> %v, %s + ret <2 x i64> %a +} + +; CHECK-LABEL: shr_s_noext_v2i64: +; NO-SIMD128-NOT: i64x2 +; SIMD128-NEXT: .functype shr_s_noext_v2i64 (v128, i64) -> (v128){{$}} ; SIMD128-NEXT: i32.wrap_i64 $push[[L0:[0-9]+]]=, $1{{$}} ; SIMD128-NEXT: i64x2.shr_s $push[[R:[0-9]+]]=, $0, $pop[[L0]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} -define <2 x i64> @shr_s_nozext_v2i64(<2 x i64> %v, i64 %x) { +define <2 x i64> @shr_s_noext_v2i64(<2 x i64> %v, i64 %x) { %t = insertelement <2 x i64> undef, i64 %x, i32 0 %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> %a = ashr <2 x i64> %v, %s @@ -838,13 +864,26 @@ ret <2 x i64> %a } -; CHECK-LABEL: shr_u_nozext_v2i64: +; CHECK-LABEL: shr_u_sext_v2i64: +; NO-SIMD128-NOT: i64x2 +; SIMD128-NEXT: .functype shr_u_sext_v2i64 (v128, i32) -> (v128){{$}} +; SIMD128-NEXT: i64x2.shr_u $push[[R:[0-9]+]]=, $0, $1{{$}} +; SIMD128-NEXT: return $pop[[R]]{{$}} +define <2 x i64> @shr_u_sext_v2i64(<2 x i64> %v, i32 %x) { + %x2 = sext i32 %x to i64 + %t = insertelement <2 x i64> undef, i64 %x2, i32 0 + %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> + %a = lshr <2 x i64> %v, %s + ret <2 x i64> %a +} + +; CHECK-LABEL: shr_u_noext_v2i64: ; NO-SIMD128-NOT: i64x2 -; SIMD128-NEXT: .functype shr_u_nozext_v2i64 (v128, i64) -> (v128){{$}} +; SIMD128-NEXT: .functype shr_u_noext_v2i64 (v128, i64) -> (v128){{$}} ; SIMD128-NEXT: i32.wrap_i64 $push[[L0:[0-9]+]]=, $1{{$}} ; SIMD128-NEXT: i64x2.shr_u $push[[R:[0-9]+]]=, $0, $pop[[L0]]{{$}} ; SIMD128-NEXT: return $pop[[R]]{{$}} -define <2 x i64> @shr_u_nozext_v2i64(<2 x i64> %v, i64 %x) { +define <2 x i64> @shr_u_noext_v2i64(<2 x i64> %v, i64 %x) { %t = insertelement <2 x i64> undef, i64 %x, i32 0 %s = shufflevector <2 x i64> %t, <2 x i64> undef, <2 x i32> %a = lshr <2 x i64> %v, %s