]> granicus.if.org Git - llvm/commitdiff
[WebAssembly] Omit wrap on i64x2.{shl,shr*} ISel when possible
authorThomas Lively <tlively@google.com>
Wed, 26 Jun 2019 16:19:59 +0000 (16:19 +0000)
committerThomas Lively <tlively@google.com>
Wed, 26 Jun 2019 16:19:59 +0000 (16:19 +0000)
Summary:
Since the WebAssembly SIMD shift instructions take i32 operands, we
truncate the i64 operand to <2 x i64> shifts during ISel. When the i64
operand is sign extended from i32, this CL makes it so the sign
extension is dropped instead of a wrap instruction added.

Reviewers: dschuff, aheejin

Subscribers: sbc100, jgravelle-google, hiraditya, sunfish, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D63615

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364446 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/WebAssembly/WebAssemblyInstrSIMD.td
test/CodeGen/WebAssembly/simd-arith.ll

index cae02d20bd3ab84fb3dbd7e77e986ed81637a74f..dd8930f079b08b9940cf2df42a2780ce3438f6cf 100644 (file)
@@ -579,10 +579,16 @@ defm SHL : SIMDShiftInt<shl, "shl", 84>;
 defm SHR_S : SIMDShiftInt<sra, "shr_s", 85>;
 defm SHR_U : SIMDShiftInt<srl, "shr_u", 86>;
 
-// 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 8d7f0205415b466c28d7cec0656bf4d8fcca4c67..bd5479a0f35b569329398994e9a685dfb74b3220 100644 (file)
@@ -730,13 +730,26 @@ define <2 x i64> @shl_v2i64(<2 x i64> %v, i32 %x) {
   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> <i32 0, i32 0>
+  %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> <i32 0, i32 0>
   %a = shl <2 x i64> %v, %s
@@ -784,13 +797,26 @@ define <2 x i64> @shr_s_v2i64(<2 x i64> %v, i32 %x) {
   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> <i32 0, i32 0>
+  %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> <i32 0, i32 0>
   %a = ashr <2 x i64> %v, %s
@@ -838,13 +864,26 @@ define <2 x i64> @shr_u_v2i64(<2 x i64> %v, i32 %x) {
   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> <i32 0, i32 0>
+  %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> <i32 0, i32 0>
   %a = lshr <2 x i64> %v, %s