diff --git a/llvm/lib/Target/AArch64/AArch64InstrFormats.td b/llvm/lib/Target/AArch64/AArch64InstrFormats.td index e1ecc5a57dd269..ab8251dc830147 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrFormats.td +++ b/llvm/lib/Target/AArch64/AArch64InstrFormats.td @@ -1108,6 +1108,13 @@ def timm32_1_7 : Operand, TImmLeaf, ImmLeaf { + let ParserMatchClass = Imm0_7Operand; +} + // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15] def imm32_0_15 : Operand, ImmLeaf; +def : Pat<(shl (v8i16 (zext (v8i8 V64:$Rm))), (v8i16 (AArch64dup (i32 imm32_0_7:$size)))), + (USHLLv8i8_shift V64:$Rm, (i32 imm32_0_7:$size))>; +def : Pat<(shl (v4i32 (zext (v4i16 V64:$Rm))), (v4i32 (AArch64dup (i32 imm32_0_15:$size)))), + (USHLLv4i16_shift V64:$Rm, (i32 imm32_0_15:$size))>; +def : Pat<(shl (v2i64 (zext (v2i32 V64:$Rm))), (v2i64 (AArch64dup (i64 imm0_31:$size)))), + (USHLLv2i32_shift V64:$Rm, (trunc_imm imm0_31:$size))>; + +def : Pat<(shl (v8i16 (sext (v8i8 V64:$Rm))), (v8i16 (AArch64dup (i32 imm32_0_7:$size)))), + (SSHLLv8i8_shift V64:$Rm, (i32 imm32_0_7:$size))>; +def : Pat<(shl (v4i32 (sext (v4i16 V64:$Rm))), (v4i32 (AArch64dup (i32 imm32_0_15:$size)))), + (SSHLLv4i16_shift V64:$Rm, (i32 imm32_0_15:$size))>; +def : Pat<(shl (v2i64 (sext (v2i32 V64:$Rm))), (v2i64 (AArch64dup (i64 imm0_31:$size)))), + (SSHLLv2i32_shift V64:$Rm, (trunc_imm imm0_31:$size))>; + // Vector sign and zero extensions are implemented with SSHLL and USSHLL. // Anyexts are implemented as zexts. def : Pat<(v8i16 (sext (v8i8 V64:$Rn))), (SSHLLv8i8_shift V64:$Rn, (i32 0))>; diff --git a/llvm/test/CodeGen/AArch64/neon-shift-left-long.ll b/llvm/test/CodeGen/AArch64/neon-shift-left-long.ll index fab3776fed086d..282f43763f3625 100644 --- a/llvm/test/CodeGen/AArch64/neon-shift-left-long.ll +++ b/llvm/test/CodeGen/AArch64/neon-shift-left-long.ll @@ -3,16 +3,10 @@ ; RUN: llc < %s -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -mattr=+neon -global-isel | FileCheck %s --check-prefixes=CHECK,CHECK-GI define <8 x i16> @test_sshll_v8i8(<8 x i8> %a) { -; CHECK-SD-LABEL: test_sshll_v8i8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: sshll v0.8h, v0.8b, #3 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_sshll_v8i8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #0 -; CHECK-GI-NEXT: shl v0.8h, v0.8h, #3 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_sshll_v8i8: +; CHECK: // %bb.0: +; CHECK-NEXT: sshll v0.8h, v0.8b, #3 +; CHECK-NEXT: ret %1 = sext <8 x i8> %a to <8 x i16> %tmp = shl <8 x i16> %1, ret <8 x i16> %tmp @@ -36,16 +30,10 @@ define <8 x i16> @test_sshll_v8i8_big(<8 x i8> %a) { } define <4 x i32> @test_sshll_v4i16(<4 x i16> %a) { -; CHECK-SD-LABEL: test_sshll_v4i16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: sshll v0.4s, v0.4h, #9 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_sshll_v4i16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #0 -; CHECK-GI-NEXT: shl v0.4s, v0.4s, #9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_sshll_v4i16: +; CHECK: // %bb.0: +; CHECK-NEXT: sshll v0.4s, v0.4h, #9 +; CHECK-NEXT: ret %1 = sext <4 x i16> %a to <4 x i32> %tmp = shl <4 x i32> %1, ret <4 x i32> %tmp @@ -69,16 +57,10 @@ define <4 x i32> @test_sshll_v4i16_big(<4 x i16> %a) { } define <2 x i64> @test_sshll_v2i32(<2 x i32> %a) { -; CHECK-SD-LABEL: test_sshll_v2i32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: sshll v0.2d, v0.2s, #19 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_sshll_v2i32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll v0.2d, v0.2s, #0 -; CHECK-GI-NEXT: shl v0.2d, v0.2d, #19 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_sshll_v2i32: +; CHECK: // %bb.0: +; CHECK-NEXT: sshll v0.2d, v0.2s, #19 +; CHECK-NEXT: ret %1 = sext <2 x i32> %a to <2 x i64> %tmp = shl <2 x i64> %1, ret <2 x i64> %tmp @@ -102,16 +84,10 @@ define <2 x i64> @test_sshll_v2i32_big(<2 x i32> %a) { } define <8 x i16> @test_ushll_v8i8(<8 x i8> %a) { -; CHECK-SD-LABEL: test_ushll_v8i8: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: ushll v0.8h, v0.8b, #3 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_ushll_v8i8: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #0 -; CHECK-GI-NEXT: shl v0.8h, v0.8h, #3 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_ushll_v8i8: +; CHECK: // %bb.0: +; CHECK-NEXT: ushll v0.8h, v0.8b, #3 +; CHECK-NEXT: ret %1 = zext <8 x i8> %a to <8 x i16> %tmp = shl <8 x i16> %1, ret <8 x i16> %tmp @@ -129,16 +105,10 @@ define <8 x i16> @test_ushll_v8i8_big(<8 x i8> %a) { } define <4 x i32> @test_ushll_v4i16(<4 x i16> %a) { -; CHECK-SD-LABEL: test_ushll_v4i16: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: ushll v0.4s, v0.4h, #9 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_ushll_v4i16: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #0 -; CHECK-GI-NEXT: shl v0.4s, v0.4s, #9 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_ushll_v4i16: +; CHECK: // %bb.0: +; CHECK-NEXT: ushll v0.4s, v0.4h, #9 +; CHECK-NEXT: ret %1 = zext <4 x i16> %a to <4 x i32> %tmp = shl <4 x i32> %1, ret <4 x i32> %tmp @@ -156,16 +126,10 @@ define <4 x i32> @test_ushll_v4i16_big(<4 x i16> %a) { } define <2 x i64> @test_ushll_v2i32(<2 x i32> %a) { -; CHECK-SD-LABEL: test_ushll_v2i32: -; CHECK-SD: // %bb.0: -; CHECK-SD-NEXT: ushll v0.2d, v0.2s, #19 -; CHECK-SD-NEXT: ret -; -; CHECK-GI-LABEL: test_ushll_v2i32: -; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #0 -; CHECK-GI-NEXT: shl v0.2d, v0.2d, #19 -; CHECK-GI-NEXT: ret +; CHECK-LABEL: test_ushll_v2i32: +; CHECK: // %bb.0: +; CHECK-NEXT: ushll v0.2d, v0.2s, #19 +; CHECK-NEXT: ret %1 = zext <2 x i32> %a to <2 x i64> %tmp = shl <2 x i64> %1, ret <2 x i64> %tmp @@ -190,8 +154,8 @@ define <8 x i16> @test_sshll2_v16i8(<16 x i8> %a) { ; ; CHECK-GI-LABEL: test_sshll2_v16i8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll2 v0.8h, v0.16b, #0 -; CHECK-GI-NEXT: shl v0.8h, v0.8h, #3 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: sshll v0.8h, v0.8b, #3 ; CHECK-GI-NEXT: ret %1 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> %2 = sext <8 x i8> %1 to <8 x i16> @@ -225,8 +189,8 @@ define <4 x i32> @test_sshll2_v8i16(<8 x i16> %a) { ; ; CHECK-GI-LABEL: test_sshll2_v8i16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll2 v0.4s, v0.8h, #0 -; CHECK-GI-NEXT: shl v0.4s, v0.4s, #9 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: sshll v0.4s, v0.4h, #9 ; CHECK-GI-NEXT: ret %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> %2 = sext <4 x i16> %1 to <4 x i32> @@ -260,8 +224,8 @@ define <2 x i64> @test_sshll2_v4i32(<4 x i32> %a) { ; ; CHECK-GI-LABEL: test_sshll2_v4i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: sshll2 v0.2d, v0.4s, #0 -; CHECK-GI-NEXT: shl v0.2d, v0.2d, #19 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: sshll v0.2d, v0.2s, #19 ; CHECK-GI-NEXT: ret %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> %2 = sext <2 x i32> %1 to <2 x i64> @@ -295,8 +259,8 @@ define <8 x i16> @test_ushll2_v16i8(<16 x i8> %a) { ; ; CHECK-GI-LABEL: test_ushll2_v16i8: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll2 v0.8h, v0.16b, #0 -; CHECK-GI-NEXT: shl v0.8h, v0.8h, #3 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: ushll v0.8h, v0.8b, #3 ; CHECK-GI-NEXT: ret %1 = shufflevector <16 x i8> %a, <16 x i8> undef, <8 x i32> %2 = zext <8 x i8> %1 to <8 x i16> @@ -324,8 +288,8 @@ define <4 x i32> @test_ushll2_v8i16(<8 x i16> %a) { ; ; CHECK-GI-LABEL: test_ushll2_v8i16: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll2 v0.4s, v0.8h, #0 -; CHECK-GI-NEXT: shl v0.4s, v0.4s, #9 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: ushll v0.4s, v0.4h, #9 ; CHECK-GI-NEXT: ret %1 = shufflevector <8 x i16> %a, <8 x i16> undef, <4 x i32> %2 = zext <4 x i16> %1 to <4 x i32> @@ -353,8 +317,8 @@ define <2 x i64> @test_ushll2_v4i32(<4 x i32> %a) { ; ; CHECK-GI-LABEL: test_ushll2_v4i32: ; CHECK-GI: // %bb.0: -; CHECK-GI-NEXT: ushll2 v0.2d, v0.4s, #0 -; CHECK-GI-NEXT: shl v0.2d, v0.2d, #19 +; CHECK-GI-NEXT: mov d0, v0.d[1] +; CHECK-GI-NEXT: ushll v0.2d, v0.2s, #19 ; CHECK-GI-NEXT: ret %1 = shufflevector <4 x i32> %a, <4 x i32> undef, <2 x i32> %2 = zext <2 x i32> %1 to <2 x i64>