Index: lib/Target/WebAssembly/WebAssemblyInstrSIMD.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrSIMD.td +++ lib/Target/WebAssembly/WebAssemblyInstrSIMD.td @@ -127,6 +127,23 @@ defm "" : SIMDBinary; defm "" : SIMDBinary; } +multiclass SIMDShift simdop> { + defm _#vec_t : SIMD_I<(outs V128:$dst), (ins V128:$vec, I32:$x), + (outs), (ins), + [(set (vec_t V128:$dst), + (node V128:$vec, (vec_t pat)))], + vec#"."#name#"\t$dst, $vec, $x", vec#"."#name, simdop>; +} +multiclass SIMDShiftInt baseInst, int skip> { + defm "" : SIMDShift; + defm "" : SIMDShift; + defm "" : SIMDShift; + defm "" : SIMDShift; +} multiclass SIMDBitwise simdop> { defm "" : SIMDBinary; defm "" : SIMDBinary; @@ -259,6 +276,10 @@ defm SUB : SIMDBinaryFP; defm DIV : SIMDBinaryFP; +defm SHL : SIMDShiftInt; +defm SHR_S : SIMDShiftInt; +defm SHR_U : SIMDShiftInt; + let isCommutable = 1 in { defm AND : SIMDBitwise; defm OR : SIMDBitwise; @@ -312,6 +333,11 @@ ) in def : Pat<(t1 (bitconvert (t2 V128:$v))), (t1 V128:$v)>; +// Truncate i64 shift operands to 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:$x)))), + (v2i64 (shifts[1] (v2i64 V128:$vec), (I32_WRAP_I64 I64:$x)))>; + // Shuffles after custom lowering def wasm_shuffle_t : SDTypeProfile<1, 18, []>; def wasm_shuffle : SDNode<"WebAssemblyISD::SHUFFLE", wasm_shuffle_t>; Index: test/CodeGen/WebAssembly/simd-arith.ll =================================================================== --- test/CodeGen/WebAssembly/simd-arith.ll +++ test/CodeGen/WebAssembly/simd-arith.ll @@ -55,6 +55,60 @@ ret <16 x i8> %a } +; CHECK-LABEL: shl_v16i8 +; NO-SIMD128-NOT: i8x16 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i8x16.shl $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x2f]{{$}} +; SIMD128: return $pop0 # +define <16 x i8> @shl_v16i8(<16 x i8> %v, i8 %x) { + %t = insertelement <16 x i8> undef, i8 %x, i32 0 + %s = shufflevector <16 x i8> %t, <16 x i8> undef, + <16 x i32> + %a = shl <16 x i8> %v, %s + ret <16 x i8> %a +} + +; CHECK-LABEL: shr_s_v16i8 +; NO-SIMD128-NOT: i8x16 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i8x16.shr_s $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x33]{{$}} +; SIMD128: return $pop0 # +define <16 x i8> @shr_s_v16i8(<16 x i8> %v, i8 %x) { + %t = insertelement <16 x i8> undef, i8 %x, i32 0 + %s = shufflevector <16 x i8> %t, <16 x i8> undef, + <16 x i32> + %a = ashr <16 x i8> %v, %s + ret <16 x i8> %a +} + +; CHECK-LABEL: shr_u_v16i8 +; NO-SIMD128-NOT: i8x16 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i8x16.shr_u $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x34]{{$}} +; SIMD128: return $pop0 # +define <16 x i8> @shr_u_v16i8(<16 x i8> %v, i8 %x) { + %t = insertelement <16 x i8> undef, i8 %x, i32 0 + %s = shufflevector <16 x i8> %t, <16 x i8> undef, + <16 x i32> + %a = lshr <16 x i8> %v, %s + ret <16 x i8> %a +} + ; CHECK-LABEL: and_v16i8 ; NO-SIMD128-NOT: v128 ; SIMD128: .param v128, v128{{$}} @@ -157,6 +211,57 @@ ret <8 x i16> %a } +; CHECK-LABEL: shl_v8i16 +; NO-SIMD128-NOT: i16x8 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i16x8.shl $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x30]{{$}} +; SIMD128: return $pop0 # +define <8 x i16> @shl_v8i16(<8 x i16> %v, i16 %x) { + %t = insertelement <8 x i16> undef, i16 %x, i32 0 + %s = shufflevector <8 x i16> %t, <8 x i16> undef, + <8 x i32> + %a = shl <8 x i16> %v, %s + ret <8 x i16> %a +} + +; CHECK-LABEL: shr_s_v8i16 +; NO-SIMD128-NOT: i16x8 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i16x8.shr_s $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x35]{{$}} +; SIMD128: return $pop0 # +define <8 x i16> @shr_s_v8i16(<8 x i16> %v, i16 %x) { + %t = insertelement <8 x i16> undef, i16 %x, i32 0 + %s = shufflevector <8 x i16> %t, <8 x i16> undef, + <8 x i32> + %a = ashr <8 x i16> %v, %s + ret <8 x i16> %a +} + +; CHECK-LABEL: shr_u_v8i16 +; NO-SIMD128-NOT: i16x8 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i16x8.shr_u $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x36]{{$}} +; SIMD128: return $pop0 # +define <8 x i16> @shr_u_v8i16(<8 x i16> %v, i16 %x) { + %t = insertelement <8 x i16> undef, i16 %x, i32 0 + %s = shufflevector <8 x i16> %t, <8 x i16> undef, + <8 x i32> + %a = lshr <8 x i16> %v, %s + ret <8 x i16> %a +} + ; CHECK-LABEL: and_v8i16 ; NO-SIMD128-NOT: v128 ; SIMD128: .param v128, v128{{$}} @@ -257,6 +362,57 @@ ret <4 x i32> %a } +; CHECK-LABEL: shl_v4i32 +; NO-SIMD128-NOT: i32x4 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32x4.shl $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x31]{{$}} +; SIMD128: return $pop0 # +define <4 x i32> @shl_v4i32(<4 x i32> %v, i32 %x) { + %t = insertelement <4 x i32> undef, i32 %x, i32 0 + %s = shufflevector <4 x i32> %t, <4 x i32> undef, + <4 x i32> + %a = shl <4 x i32> %v, %s + ret <4 x i32> %a +} + +; CHECK-LABEL: shr_s_v4i32 +; NO-SIMD128-NOT: i32x4 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32x4.shr_s $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x37]{{$}} +; SIMD128: return $pop0 # +define <4 x i32> @shr_s_v4i32(<4 x i32> %v, i32 %x) { + %t = insertelement <4 x i32> undef, i32 %x, i32 0 + %s = shufflevector <4 x i32> %t, <4 x i32> undef, + <4 x i32> + %a = ashr <4 x i32> %v, %s + ret <4 x i32> %a +} + +; CHECK-LABEL: shr_u_v4i32 +; NO-SIMD128-NOT: i32x4 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32x4.shr_u $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x38]{{$}} +; SIMD128: return $pop0 # +define <4 x i32> @shr_u_v4i32(<4 x i32> %v, i32 %x) { + %t = insertelement <4 x i32> undef, i32 %x, i32 0 + %s = shufflevector <4 x i32> %t, <4 x i32> undef, + <4 x i32> + %a = lshr <4 x i32> %v, %s + ret <4 x i32> %a +} + ; CHECK-LABEL: and_v4i32 ; NO-SIMD128-NOT: v128 ; SIMD128: .param v128, v128{{$}} @@ -358,6 +514,108 @@ ret <2 x i64> %a } +; CHECK-LABEL: shl_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i64x2.shl $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x32]{{$}} +; SIMD128: return $pop0 # +define <2 x i64> @shl_v2i64(<2 x i64> %v, i32 %x) { + %x2 = zext 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_nozext_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i64{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32.wrap/i64 $push[[L2:[0-9]+]]=, $pop[[L1]] # +; SIMD128: i64x2.shl $push[[R:[0-9]+]]=, $pop[[L0]], $pop[[L2]] # +; SIMD128-SAME: encoding: [0xfd,0x32]{{$}} +; SIMD128: return $pop[[R]] # +define <2 x i64> @shl_nozext_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 + ret <2 x i64> %a +} + +; CHECK-LABEL: shr_s_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i64x2.shr_s $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x39]{{$}} +; SIMD128: return $pop0 # +define <2 x i64> @shr_s_v2i64(<2 x i64> %v, i32 %x) { + %x2 = zext 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_nozext_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i64{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32.wrap/i64 $push[[L2:[0-9]+]]=, $pop[[L1]] # +; SIMD128: i64x2.shr_s $push[[R:[0-9]+]]=, $pop[[L0]], $pop[[L2]] # +; SIMD128-SAME: encoding: [0xfd,0x39]{{$}} +; SIMD128: return $pop[[R]] # +define <2 x i64> @shr_s_nozext_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 + ret <2 x i64> %a +} + +; CHECK-LABEL: shr_u_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i32{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i64x2.shr_u $push0=, $pop[[L0]], $pop[[L1]] # +; SIMD128-SAME: encoding: [0xfd,0x3a]{{$}} +; SIMD128: return $pop0 # +define <2 x i64> @shr_u_v2i64(<2 x i64> %v, i32 %x) { + %x2 = zext 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_nozext_v2i64 +; NO-SIMD128-NOT: i64x2 +; SIMD128: .param v128, i64{{$}} +; SIMD128: .result v128{{$}} +; SIMD128: get_local $push[[L0:[0-9]+]]=, 0 # +; SIMD128: get_local $push[[L1:[0-9]+]]=, 1 # +; SIMD128: i32.wrap/i64 $push[[L2:[0-9]+]]=, $pop[[L1]] # +; SIMD128: i64x2.shr_u $push[[R:[0-9]+]]=, $pop[[L0]], $pop[[L2]] # +; SIMD128-SAME: encoding: [0xfd,0x3a]{{$}} +; SIMD128: return $pop[[R]] # +define <2 x i64> @shr_u_nozext_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 + ret <2 x i64> %a +} + ; CHECK-LABEL: and_v2i64 ; NO-SIMD128-NOT: v128 ; SIMD128-VM-NOT: v128