https://github.com/kieroxide created 
https://github.com/llvm/llvm-project/pull/212459

- Add ImmCheckShiftLeftLong to allow checking of [0..((elt/2) -1)] range checks
- Add immediate range checks in vector-shift-left.c
- Update stale intrinsic tests for vcvt_f32_bf16 and vshll_n
- Add GIsel patterns so VCVT_F32_BF16 lowers to the correct ACLE specified 
instruction

The fixed immediate range caused a problem with the VCVT_F32_BF16 instrinic as 
it used vshll_n with an illegal range immediate of 16. I split this instruction 
into a widen (vmovl) then a shift (vshl_n) producing the same result.

Both A64/A32 lower to the vshll/shll 16 widen-shift instruction in asm as 
defined in ACLE. Tests for the vshll_n fold can be found in vshll.ll (A32) and 
arm64-vshift.ll (A64)

>From b61f7758eaceecd6e7b5f5474d39af3c6a84aada Mon Sep 17 00:00:00 2001
From: Kieran Bailey <[email protected]>
Date: Tue, 28 Jul 2026 09:31:59 +0000
Subject: [PATCH] [Clang][ARM] Fix immediate range for NEON widening
 left-shifts

- Add ImmCheckShiftLeftLong to allow checking of [0..((elt/2) -1)] range checks
- Add immediate range checks in vector-shift-left.c
- Update stale intrinsic tests for vcvt_f32_bf16 and vshll_n
- Add GIsel patterns so VCVT_F32_BF16 lowers to the correct ACLE specified 
instruction

The fixed immediate range caused a problem with the VCVT_F32_BF16 instrinic as 
it used vshll_n with an illegal range immediate of 16. I split this instruction 
into a widen (vmovl) then a shift (vshl_n) producing the same result.

Both A64/A32 lower to the vshll/shll 16 widen-shift instruction in asm as 
defined in ACLE.
Tests for the vshll_n fold can be found in vshll.ll (A32) and arm64-vshift.ll 
(A64)
---
 .../include/clang/Basic/arm_immcheck_incl.td  | 43 ++++-----
 clang/include/clang/Basic/arm_neon.td         | 19 ++--
 clang/lib/Sema/SemaARM.cpp                    |  5 ++
 clang/test/CodeGen/AArch64/neon-misc.c        | 48 +++++-----
 .../CodeGen/arm-bf16-convert-intrinsics.c     | 90 +++++++++++--------
 .../vector-shift-left.c                       | 45 +++-------
 llvm/lib/Target/AArch64/AArch64InstrInfo.td   |  5 ++
 llvm/test/CodeGen/AArch64/arm64-vcvt_f.ll     | 54 +++++++++++
 llvm/test/CodeGen/AArch64/arm64-vshift.ll     | 14 +--
 9 files changed, 190 insertions(+), 133 deletions(-)

diff --git a/clang/include/clang/Basic/arm_immcheck_incl.td 
b/clang/include/clang/Basic/arm_immcheck_incl.td
index 6892b8299771b..87bc83e89aa10 100644
--- a/clang/include/clang/Basic/arm_immcheck_incl.td
+++ b/clang/include/clang/Basic/arm_immcheck_incl.td
@@ -11,27 +11,28 @@ def ImmCheckExtract             : ImmCheckType<2>;  // 
0..(2048/sizeinbits(elt)
 def ImmCheckShiftRight          : ImmCheckType<3>;  // 1..sizeinbits(elt)
 def ImmCheckShiftRightNarrow    : ImmCheckType<4>;  // 1..sizeinbits(elt)/2
 def ImmCheckShiftLeft           : ImmCheckType<5>;  // 0..(sizeinbits(elt) - 1)
-def ImmCheck0_7                 : ImmCheckType<6>;  // 0..7
-def ImmCheckLaneIndex           : ImmCheckType<7>;  // 
0..(container_size/(sizeinbits(elt)) - 1)
-def ImmCheckCvt                 : ImmCheckType<8>;  // 1..sizeinbits(elt) 
(same as ShiftRight)
-def ImmCheckLaneIndexCompRotate : ImmCheckType<9>;  // 
0..(container_size/(2*sizeinbits(elt)) - 1)
-def ImmCheckLaneIndexDot        : ImmCheckType<10>; // 
0..(container_size/(4*sizeinbits(elt)) - 1)
-def ImmCheckComplexRot90_270    : ImmCheckType<11>; // [90,270]
-def ImmCheckComplexRotAll90     : ImmCheckType<12>; // [0, 90, 180,270]
-def ImmCheck0_13                : ImmCheckType<13>; // 0..13
-def ImmCheck0_1                 : ImmCheckType<14>; // 0..1
-def ImmCheck0_2                 : ImmCheckType<15>; // 0..2
-def ImmCheck0_3                 : ImmCheckType<16>; // 0..3
-def ImmCheck0_0                 : ImmCheckType<17>; // 0..0
-def ImmCheck0_15                : ImmCheckType<18>; // 0..15
-def ImmCheck0_255               : ImmCheckType<19>; // 0..255
-def ImmCheck2_4_Mul2            : ImmCheckType<20>; // 2, 4
-def ImmCheck1_1                 : ImmCheckType<21>; // 1..1
-def ImmCheck1_3                 : ImmCheckType<22>; // 1..3
-def ImmCheck1_7                 : ImmCheckType<23>; // 1..7
-def ImmCheck1_32                : ImmCheckType<24>; // 1..32
-def ImmCheck1_64                : ImmCheckType<25>; // 1..64
-def ImmCheck0_63                : ImmCheckType<26>; // 0..63
+def ImmCheckShiftLeftLong       : ImmCheckType<6>;  // 0..(sizeinbits(elt)/2) 
- 1)
+def ImmCheck0_7                 : ImmCheckType<7>;  // 0..7
+def ImmCheckLaneIndex           : ImmCheckType<8>;  // 
0..(container_size/(sizeinbits(elt)) - 1)
+def ImmCheckCvt                 : ImmCheckType<9>;  // 1..sizeinbits(elt) 
(same as ShiftRight)
+def ImmCheckLaneIndexCompRotate : ImmCheckType<10>; // 
0..(container_size/(2*sizeinbits(elt)) - 1)
+def ImmCheckLaneIndexDot        : ImmCheckType<11>; // 
0..(container_size/(4*sizeinbits(elt)) - 1)
+def ImmCheckComplexRot90_270    : ImmCheckType<12>; // [90,270]
+def ImmCheckComplexRotAll90     : ImmCheckType<13>; // [0, 90, 180,270]
+def ImmCheck0_13                : ImmCheckType<14>; // 0..13
+def ImmCheck0_1                 : ImmCheckType<15>; // 0..1
+def ImmCheck0_2                 : ImmCheckType<16>; // 0..2
+def ImmCheck0_3                 : ImmCheckType<17>; // 0..3
+def ImmCheck0_0                 : ImmCheckType<18>; // 0..0
+def ImmCheck0_15                : ImmCheckType<19>; // 0..15
+def ImmCheck0_255               : ImmCheckType<20>; // 0..255
+def ImmCheck2_4_Mul2            : ImmCheckType<21>; // 2, 4
+def ImmCheck1_1                 : ImmCheckType<22>; // 1..1
+def ImmCheck1_3                 : ImmCheckType<23>; // 1..3
+def ImmCheck1_7                 : ImmCheckType<24>; // 1..7
+def ImmCheck1_32                : ImmCheckType<25>; // 1..32
+def ImmCheck1_64                : ImmCheckType<26>; // 1..64
+def ImmCheck0_63                : ImmCheckType<27>; // 0..63
 
 class ImmCheck<int immArgIdx, ImmCheckType kind, int typeArgIdx = -1> {
   // Parameter index of immediate argument to be verified
diff --git a/clang/include/clang/Basic/arm_neon.td 
b/clang/include/clang/Basic/arm_neon.td
index 041a420875290..e7008b39f202d 100644
--- a/clang/include/clang/Basic/arm_neon.td
+++ b/clang/include/clang/Basic/arm_neon.td
@@ -251,9 +251,10 @@ def OP_BFMLALT_LN
           (dup_typed $p1, (call "vget_lane", $p2, $p3)))>;
 
 def OP_VCVT_F32_BF16
-    : Op<(bitcast "R",
-          (call "vshll_n", (bitcast "uint16x4_t", $p0),
-                           (literal "int32_t", "16")))>;
+     : Op<(bitcast "R",
+          (call "vshl_n",
+            (call "vmovl", (bitcast "uint16x4_t", $p0)),
+            (literal "int32_t", "16")))>;
 def OP_VCVT_F32_BF16_LO
     : Op<(call "vcvt_f32_bf16", (call "vget_low", $p0))>;
 def OP_VCVT_F32_BF16_HI
@@ -432,13 +433,13 @@ def VRSHRN_N   : IInst<"vrshrn_n", "<QI", "silUsUiUl",
 def VQRSHRN_N  : SInst<"vqrshrn_n", "<QI", "silUsUiUl",
                       [ImmCheck<1, ImmCheckShiftRight>]>;
 
-// Widening left-shifts should have a range of 0..(sizeinbits(arg)-1).
-// This polymorphic builtin is supplied the wider return type as it's 
overloaded
-// base type, so the range here is actually 0..(sizeinbits(arg)*2).
-// This cannot be rectified currently due to a use of vshll_n_s16 with an
-// out-of-bounds immediate in the defintiion of vcvt_f32_bf16.
+// Widening left-shifts should have an immediate range of 
0..(sizeinbits(arg)-1).
+// However, as the overloaded type code that is supplied to a polymorphic 
builtin
+// is that of the return type (twice as wide as the argument in this case), 
using
+// ImmCheckShiftLeft would return in an upper bound of ((sizeinbits(arg)*2)-1).
+// ImmCheckShiftLeftLong produces the correct behavior here.
 def VSHLL_N    : SInst<"vshll_n", "(>Q).I", "csiUcUsUi",
-                      [ImmCheck<1, ImmCheckShiftLeft>]>;
+                      [ImmCheck<1, ImmCheckShiftLeftLong>]>;
 
 
////////////////////////////////////////////////////////////////////////////////
 // E.3.13 Shifts with insert
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp
index 5e7504fab416d..d801ff17ce2f4 100644
--- a/clang/lib/Sema/SemaARM.cpp
+++ b/clang/lib/Sema/SemaARM.cpp
@@ -452,6 +452,11 @@ bool SemaARM::CheckImmediateArg(CallExpr *TheCall, 
unsigned CheckTy,
     if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0, EltBitWidth - 1))
       return true;
     break;
+  case ImmCheckType::ImmCheckShiftLeftLong:
+    if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
+                                        (EltBitWidth / 2) - 1))
+      return true;
+    break;
   case ImmCheckType::ImmCheckLaneIndex:
     if (SemaRef.BuiltinConstantArgRange(TheCall, ArgIdx, 0,
                                         (ContainerBitWidth / EltBitWidth) - 1))
diff --git a/clang/test/CodeGen/AArch64/neon-misc.c 
b/clang/test/CodeGen/AArch64/neon-misc.c
index 308718fd1bedf..e9e17b2fe407a 100644
--- a/clang/test/CodeGen/AArch64/neon-misc.c
+++ b/clang/test/CodeGen/AArch64/neon-misc.c
@@ -2451,11 +2451,11 @@ uint32x4_t test_vqmovn_high_u64(uint32x2_t a, 
uint64x2_t b) {
 // CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = sext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 8)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 7)
 // CHECK-NEXT:    ret <8 x i16> [[VSHLL_N]]
 //
 int16x8_t test_vshll_n_s8(int8x8_t a) {
-  return vshll_n_s8(a, 8);
+  return vshll_n_s8(a, 7);
 }
 
 // CHECK-LABEL: define dso_local <4 x i32> @test_vshll_n_s16(
@@ -2464,11 +2464,11 @@ int16x8_t test_vshll_n_s8(int8x8_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
 // CHECK-NEXT:    [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 15)
 // CHECK-NEXT:    ret <4 x i32> [[VSHLL_N]]
 //
 int32x4_t test_vshll_n_s16(int16x4_t a) {
-  return vshll_n_s16(a, 16);
+  return vshll_n_s16(a, 15);
 }
 
 // CHECK-LABEL: define dso_local <2 x i64> @test_vshll_n_s32(
@@ -2477,22 +2477,22 @@ int32x4_t test_vshll_n_s16(int16x4_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
 // CHECK-NEXT:    [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 32)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 31)
 // CHECK-NEXT:    ret <2 x i64> [[VSHLL_N]]
 //
 int64x2_t test_vshll_n_s32(int32x2_t a) {
-  return vshll_n_s32(a, 32);
+  return vshll_n_s32(a, 31);
 }
 
 // CHECK-LABEL: define dso_local <8 x i16> @test_vshll_n_u8(
 // CHECK-SAME: <8 x i8> noundef [[A:%.*]]) #[[ATTR0]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[TMP0:%.*]] = zext <8 x i8> [[A]] to <8 x i16>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 8)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 7)
 // CHECK-NEXT:    ret <8 x i16> [[VSHLL_N]]
 //
 uint16x8_t test_vshll_n_u8(uint8x8_t a) {
-  return vshll_n_u8(a, 8);
+  return vshll_n_u8(a, 7);
 }
 
 // CHECK-LABEL: define dso_local <4 x i32> @test_vshll_n_u16(
@@ -2501,11 +2501,11 @@ uint16x8_t test_vshll_n_u8(uint8x8_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i16> [[A]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
 // CHECK-NEXT:    [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 15)
 // CHECK-NEXT:    ret <4 x i32> [[VSHLL_N]]
 //
 uint32x4_t test_vshll_n_u16(uint16x4_t a) {
-  return vshll_n_u16(a, 16);
+  return vshll_n_u16(a, 15);
 }
 
 // CHECK-LABEL: define dso_local <2 x i64> @test_vshll_n_u32(
@@ -2514,11 +2514,11 @@ uint32x4_t test_vshll_n_u16(uint16x4_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i32> [[A]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
 // CHECK-NEXT:    [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 32)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 31)
 // CHECK-NEXT:    ret <2 x i64> [[VSHLL_N]]
 //
 uint64x2_t test_vshll_n_u32(uint32x2_t a) {
-  return vshll_n_u32(a, 32);
+  return vshll_n_u32(a, 31);
 }
 
 // CHECK-LABEL: define dso_local <8 x i16> @test_vshll_high_n_s8(
@@ -2526,11 +2526,11 @@ uint64x2_t test_vshll_n_u32(uint32x2_t a) {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> 
[[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
 // CHECK-NEXT:    [[TMP0:%.*]] = sext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 8)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 7)
 // CHECK-NEXT:    ret <8 x i16> [[VSHLL_N]]
 //
 int16x8_t test_vshll_high_n_s8(int8x16_t a) {
-  return vshll_high_n_s8(a, 8);
+  return vshll_high_n_s8(a, 7);
 }
 
 // CHECK-LABEL: define dso_local <4 x i32> @test_vshll_high_n_s16(
@@ -2540,11 +2540,11 @@ int16x8_t test_vshll_high_n_s8(int8x16_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
 // CHECK-NEXT:    [[TMP2:%.*]] = sext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 15)
 // CHECK-NEXT:    ret <4 x i32> [[VSHLL_N]]
 //
 int32x4_t test_vshll_high_n_s16(int16x8_t a) {
-  return vshll_high_n_s16(a, 16);
+  return vshll_high_n_s16(a, 15);
 }
 
 // CHECK-LABEL: define dso_local <2 x i64> @test_vshll_high_n_s32(
@@ -2554,11 +2554,11 @@ int32x4_t test_vshll_high_n_s16(int16x8_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
 // CHECK-NEXT:    [[TMP2:%.*]] = sext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 32)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 31)
 // CHECK-NEXT:    ret <2 x i64> [[VSHLL_N]]
 //
 int64x2_t test_vshll_high_n_s32(int32x4_t a) {
-  return vshll_high_n_s32(a, 32);
+  return vshll_high_n_s32(a, 31);
 }
 
 // CHECK-LABEL: define dso_local <8 x i16> @test_vshll_high_n_u8(
@@ -2566,11 +2566,11 @@ int64x2_t test_vshll_high_n_s32(int32x4_t a) {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[SHUFFLE_I:%.*]] = shufflevector <16 x i8> [[A]], <16 x i8> 
[[A]], <8 x i32> <i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15>
 // CHECK-NEXT:    [[TMP0:%.*]] = zext <8 x i8> [[SHUFFLE_I]] to <8 x i16>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 8)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <8 x i16> [[TMP0]], splat (i16 7)
 // CHECK-NEXT:    ret <8 x i16> [[VSHLL_N]]
 //
 uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
-  return vshll_high_n_u8(a, 8);
+  return vshll_high_n_u8(a, 7);
 }
 
 // CHECK-LABEL: define dso_local <4 x i32> @test_vshll_high_n_u16(
@@ -2580,11 +2580,11 @@ uint16x8_t test_vshll_high_n_u8(uint8x16_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <4 x i16> [[SHUFFLE_I]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <4 x i16>
 // CHECK-NEXT:    [[TMP2:%.*]] = zext <4 x i16> [[TMP1]] to <4 x i32>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 16)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <4 x i32> [[TMP2]], splat (i32 15)
 // CHECK-NEXT:    ret <4 x i32> [[VSHLL_N]]
 //
 uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
-  return vshll_high_n_u16(a, 16);
+  return vshll_high_n_u16(a, 15);
 }
 
 // CHECK-LABEL: define dso_local <2 x i64> @test_vshll_high_n_u32(
@@ -2594,11 +2594,11 @@ uint32x4_t test_vshll_high_n_u16(uint16x8_t a) {
 // CHECK-NEXT:    [[TMP0:%.*]] = bitcast <2 x i32> [[SHUFFLE_I]] to <8 x i8>
 // CHECK-NEXT:    [[TMP1:%.*]] = bitcast <8 x i8> [[TMP0]] to <2 x i32>
 // CHECK-NEXT:    [[TMP2:%.*]] = zext <2 x i32> [[TMP1]] to <2 x i64>
-// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 32)
+// CHECK-NEXT:    [[VSHLL_N:%.*]] = shl <2 x i64> [[TMP2]], splat (i64 31)
 // CHECK-NEXT:    ret <2 x i64> [[VSHLL_N]]
 //
 uint64x2_t test_vshll_high_n_u32(uint32x4_t a) {
-  return vshll_high_n_u32(a, 32);
+  return vshll_high_n_u32(a, 31);
 }
 
 // CHECK-LABEL: define dso_local <4 x half> @test_vcvt_f16_f32(
diff --git a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c 
b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c
index 8a1ef2441b39d..256c681db3b3f 100644
--- a/clang/test/CodeGen/arm-bf16-convert-intrinsics.c
+++ b/clang/test/CodeGen/arm-bf16-convert-intrinsics.c
@@ -27,20 +27,24 @@
 // CHECK-A64-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[A:%.*]] to <4 x 
i16>
 // CHECK-A64-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
 // CHECK-A64-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK-A64-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
-// CHECK-A64-NEXT:    [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], splat (i32 
16)
-// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I]] to <4 x 
float>
-// CHECK-A64-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A64-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
+// CHECK-A64-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to <16 x i8>
+// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x i32>
+// CHECK-A64-NEXT:    [[VSHL_N_I:%.*]] = shl <4 x i32> [[TMP4]], splat (i32 16)
+// CHECK-A64-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I]] to <4 x 
float>
+// CHECK-A64-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-HARDFP-LABEL: @test_vcvt_f32_bf16(
 // CHECK-A32-HARDFP-NEXT:  entry:
 // CHECK-A32-HARDFP-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[A:%.*]] to 
<4 x i16>
 // CHECK-A32-HARDFP-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x 
i8>
 // CHECK-A32-HARDFP-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x 
i16>
-// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
-// CHECK-A32-HARDFP-NEXT:    [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP3]], splat 
(i32 16)
-// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I]] to 
<4 x float>
-// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A32-HARDFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[VSHL_N_I:%.*]] = shl <4 x i32> [[TMP4]], splat 
(i32 16)
+// CHECK-A32-HARDFP-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I]] to 
<4 x float>
+// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-SOFTFP-LABEL: @test_vcvt_f32_bf16(
 // CHECK-A32-SOFTFP-NEXT:  entry:
@@ -50,10 +54,12 @@
 // CHECK-A32-SOFTFP-NEXT:    [[TMP3:%.*]] = bitcast <4 x bfloat> [[TMP2]] to 
<4 x i16>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP4:%.*]] = bitcast <4 x i16> [[TMP3]] to <8 x 
i8>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP5:%.*]] = bitcast <8 x i8> [[TMP4]] to <4 x 
i16>
-// CHECK-A32-SOFTFP-NEXT:    [[TMP6:%.*]] = zext <4 x i16> [[TMP5]] to <4 x 
i32>
-// CHECK-A32-SOFTFP-NEXT:    [[VSHLL_N_I:%.*]] = shl <4 x i32> [[TMP6]], splat 
(i32 16)
-// CHECK-A32-SOFTFP-NEXT:    [[TMP7:%.*]] = bitcast <4 x i32> [[VSHLL_N_I]] to 
<4 x float>
-// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP7]]
+// CHECK-A32-SOFTFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP5]] to <4 x 
i32>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP6:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP7:%.*]] = bitcast <16 x i8> [[TMP6]] to <4 x 
i32>
+// CHECK-A32-SOFTFP-NEXT:    [[VSHL_N_I:%.*]] = shl <4 x i32> [[TMP7]], splat 
(i32 16)
+// CHECK-A32-SOFTFP-NEXT:    [[TMP8:%.*]] = bitcast <4 x i32> [[VSHL_N_I]] to 
<4 x float>
+// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP8]]
 //
 float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) {
   return vcvt_f32_bf16(a);
@@ -65,10 +71,12 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) {
 // CHECK-A64-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[SHUFFLE_I]] to <4 
x i16>
 // CHECK-A64-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
 // CHECK-A64-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK-A64-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
-// CHECK-A64-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], splat (i32 
16)
-// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] to <4 x 
float>
-// CHECK-A64-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A64-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
+// CHECK-A64-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to <16 x i8>
+// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x i32>
+// CHECK-A64-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP4]], splat (i32 
16)
+// CHECK-A64-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] to <4 x 
float>
+// CHECK-A64-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-HARDFP-LABEL: @test_vcvtq_low_f32_bf16(
 // CHECK-A32-HARDFP-NEXT:  entry:
@@ -76,10 +84,12 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) {
 // CHECK-A32-HARDFP-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[SHUFFLE_I]] 
to <4 x i16>
 // CHECK-A32-HARDFP-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x 
i8>
 // CHECK-A32-HARDFP-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x 
i16>
-// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
-// CHECK-A32-HARDFP-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], 
splat (i32 16)
-// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] 
to <4 x float>
-// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A32-HARDFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP4]], 
splat (i32 16)
+// CHECK-A32-HARDFP-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] 
to <4 x float>
+// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_low_f32_bf16(
 // CHECK-A32-SOFTFP-NEXT:  entry:
@@ -96,10 +106,12 @@ float32x4_t test_vcvt_f32_bf16(bfloat16x4_t a) {
 // CHECK-A32-SOFTFP-NEXT:    [[TMP9:%.*]] = bitcast <4 x bfloat> [[TMP8]] to 
<4 x i16>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 
x i8>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP11:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 
x i16>
-// CHECK-A32-SOFTFP-NEXT:    [[TMP12:%.*]] = zext <4 x i16> [[TMP11]] to <4 x 
i32>
-// CHECK-A32-SOFTFP-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP12]], 
splat (i32 16)
-// CHECK-A32-SOFTFP-NEXT:    [[TMP13:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] 
to <4 x float>
-// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP13]]
+// CHECK-A32-SOFTFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP11]] to <4 
x i32>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP12:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP13:%.*]] = bitcast <16 x i8> [[TMP12]] to <4 
x i32>
+// CHECK-A32-SOFTFP-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP13]], 
splat (i32 16)
+// CHECK-A32-SOFTFP-NEXT:    [[TMP14:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] 
to <4 x float>
+// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP14]]
 //
 float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) {
   return vcvtq_low_f32_bf16(a);
@@ -111,10 +123,12 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) {
 // CHECK-A64-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[SHUFFLE_I]] to <4 
x i16>
 // CHECK-A64-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x i8>
 // CHECK-A64-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x i16>
-// CHECK-A64-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
-// CHECK-A64-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], splat (i32 
16)
-// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] to <4 x 
float>
-// CHECK-A64-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A64-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x i32>
+// CHECK-A64-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to <16 x i8>
+// CHECK-A64-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x i32>
+// CHECK-A64-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP4]], splat (i32 
16)
+// CHECK-A64-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] to <4 x 
float>
+// CHECK-A64-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-HARDFP-LABEL: @test_vcvtq_high_f32_bf16(
 // CHECK-A32-HARDFP-NEXT:  entry:
@@ -122,10 +136,12 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) {
 // CHECK-A32-HARDFP-NEXT:    [[TMP0:%.*]] = bitcast <4 x bfloat> [[SHUFFLE_I]] 
to <4 x i16>
 // CHECK-A32-HARDFP-NEXT:    [[TMP1:%.*]] = bitcast <4 x i16> [[TMP0]] to <8 x 
i8>
 // CHECK-A32-HARDFP-NEXT:    [[TMP2:%.*]] = bitcast <8 x i8> [[TMP1]] to <4 x 
i16>
-// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
-// CHECK-A32-HARDFP-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP3]], 
splat (i32 16)
-// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] 
to <4 x float>
-// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP4]]
+// CHECK-A32-HARDFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP2]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[TMP3:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-HARDFP-NEXT:    [[TMP4:%.*]] = bitcast <16 x i8> [[TMP3]] to <4 x 
i32>
+// CHECK-A32-HARDFP-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP4]], 
splat (i32 16)
+// CHECK-A32-HARDFP-NEXT:    [[TMP5:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] 
to <4 x float>
+// CHECK-A32-HARDFP-NEXT:    ret <4 x float> [[TMP5]]
 //
 // CHECK-A32-SOFTFP-LABEL: @test_vcvtq_high_f32_bf16(
 // CHECK-A32-SOFTFP-NEXT:  entry:
@@ -142,10 +158,12 @@ float32x4_t test_vcvtq_low_f32_bf16(bfloat16x8_t a) {
 // CHECK-A32-SOFTFP-NEXT:    [[TMP9:%.*]] = bitcast <4 x bfloat> [[TMP8]] to 
<4 x i16>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP10:%.*]] = bitcast <4 x i16> [[TMP9]] to <8 
x i8>
 // CHECK-A32-SOFTFP-NEXT:    [[TMP11:%.*]] = bitcast <8 x i8> [[TMP10]] to <4 
x i16>
-// CHECK-A32-SOFTFP-NEXT:    [[TMP12:%.*]] = zext <4 x i16> [[TMP11]] to <4 x 
i32>
-// CHECK-A32-SOFTFP-NEXT:    [[VSHLL_N_I_I:%.*]] = shl <4 x i32> [[TMP12]], 
splat (i32 16)
-// CHECK-A32-SOFTFP-NEXT:    [[TMP13:%.*]] = bitcast <4 x i32> [[VSHLL_N_I_I]] 
to <4 x float>
-// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP13]]
+// CHECK-A32-SOFTFP-NEXT:    [[VMOVL_I:%.*]] = zext <4 x i16> [[TMP11]] to <4 
x i32>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP12:%.*]] = bitcast <4 x i32> [[VMOVL_I]] to 
<16 x i8>
+// CHECK-A32-SOFTFP-NEXT:    [[TMP13:%.*]] = bitcast <16 x i8> [[TMP12]] to <4 
x i32>
+// CHECK-A32-SOFTFP-NEXT:    [[VSHL_N_I_I:%.*]] = shl <4 x i32> [[TMP13]], 
splat (i32 16)
+// CHECK-A32-SOFTFP-NEXT:    [[TMP14:%.*]] = bitcast <4 x i32> [[VSHL_N_I_I]] 
to <4 x float>
+// CHECK-A32-SOFTFP-NEXT:    ret <4 x float> [[TMP14]]
 //
 float32x4_t test_vcvtq_high_f32_bf16(bfloat16x8_t a) {
   return vcvtq_high_f32_bf16(a);
diff --git a/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c 
b/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c
index 1def72fc843d9..ce0da4419d184 100644
--- a/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c
+++ b/clang/test/Sema/aarch64-neon-immediate-ranges/vector-shift-left.c
@@ -3,11 +3,6 @@
 #include <arm_neon.h>
 // REQUIRES: aarch64-registered-target
 
-// Widening left-shifts should have a range of 0..(sizeinbits(arg)-1), this 
range has had
-// to be weakened to 0..((sizeinbits(arg)*2)-1) due to a use of vshll_n_s16 
with an
-// out-of-bounds immediate in the defintiion of vcvt_f32_bf16. As a result, 
the upper bounds
-// of widening left-shift intrinsics are not currently tested here.
-
 void test_vector_shift_left_s8(int8x8_t arg_i8x8, int8x16_t arg_i8x16) {
        vshl_n_s8(arg_i8x8, 0);
        vshl_n_s8(arg_i8x8, 7);
@@ -18,7 +13,6 @@ void test_vector_shift_left_s8(int8x8_t arg_i8x8, int8x16_t 
arg_i8x16) {
        vshlq_n_s8(arg_i8x16, 7);
        vshlq_n_s8(arg_i8x16, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vshlq_n_s8(arg_i8x16, 8); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_shift_left_s16(int16x4_t arg_i16x4, int16x8_t arg_i16x8) {
@@ -31,7 +25,6 @@ void test_vector_shift_left_s16(int16x4_t arg_i16x4, 
int16x8_t arg_i16x8) {
        vshlq_n_s16(arg_i16x8, 15);
        vshlq_n_s16(arg_i16x8, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vshlq_n_s16(arg_i16x8, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_s32(int32x2_t arg_i32x2, int32x4_t arg_i32x4) {
@@ -44,7 +37,6 @@ void test_vector_shift_left_s32(int32x2_t arg_i32x2, 
int32x4_t arg_i32x4) {
        vshlq_n_s32(arg_i32x4, 31);
        vshlq_n_s32(arg_i32x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vshlq_n_s32(arg_i32x4, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_s64(int64_t arg_i64, int64x2_t arg_i64x2, 
int64x1_t arg_i64x1) {
@@ -62,7 +54,6 @@ void test_vector_shift_left_s64(int64_t arg_i64, int64x2_t 
arg_i64x2, int64x1_t
        vshld_n_s64(arg_i64, 63);
        vshld_n_s64(arg_i64, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vshld_n_s64(arg_i64, 64); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_shift_left_u8(uint8x8_t arg_u8x8, uint8x16_t arg_u8x16) {
@@ -75,7 +66,6 @@ void test_vector_shift_left_u8(uint8x8_t arg_u8x8, uint8x16_t 
arg_u8x16) {
        vshlq_n_u8(arg_u8x16, 7);
        vshlq_n_u8(arg_u8x16, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vshlq_n_u8(arg_u8x16, 8); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_shift_left_u16(uint16x4_t arg_u16x4, uint16x8_t arg_u16x8) {
@@ -88,7 +78,6 @@ void test_vector_shift_left_u16(uint16x4_t arg_u16x4, 
uint16x8_t arg_u16x8) {
        vshlq_n_u16(arg_u16x8, 15);
        vshlq_n_u16(arg_u16x8, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vshlq_n_u16(arg_u16x8, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_u32(uint32x2_t arg_u32x2, uint32x4_t arg_u32x4) {
@@ -101,7 +90,6 @@ void test_vector_shift_left_u32(uint32x2_t arg_u32x2, 
uint32x4_t arg_u32x4) {
        vshlq_n_u32(arg_u32x4, 31);
        vshlq_n_u32(arg_u32x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vshlq_n_u32(arg_u32x4, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_u64(uint64x1_t arg_u64x1, uint64_t arg_u64, 
uint64x2_t arg_u64x2) {
@@ -119,7 +107,6 @@ void test_vector_shift_left_u64(uint64x1_t arg_u64x1, 
uint64_t arg_u64, uint64x2
        vshld_n_u64(arg_u64, 63);
        vshld_n_u64(arg_u64, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vshld_n_u64(arg_u64, 64); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_s8(int8x8_t arg_i8x8, int8x16_t 
arg_i8x16, int8_t arg_i8) {
@@ -152,7 +139,6 @@ void test_vector_saturating_shift_left_s8(int8x8_t 
arg_i8x8, int8x16_t arg_i8x16
        vqshlub_n_s8(arg_i8, 7);
        vqshlub_n_s8(arg_i8, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vqshlub_n_s8(arg_i8, 8); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_s16(int16x4_t arg_i16x4, int16_t 
arg_i16, int16x8_t arg_i16x8) {
@@ -185,7 +171,6 @@ void test_vector_saturating_shift_left_s16(int16x4_t 
arg_i16x4, int16_t arg_i16,
        vqshluh_n_s16(arg_i16, 15);
        vqshluh_n_s16(arg_i16, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vqshluh_n_s16(arg_i16, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_s32(int32x2_t arg_i32x2, int32_t 
arg_i32, int32x4_t arg_i32x4) {
@@ -218,7 +203,6 @@ void test_vector_saturating_shift_left_s32(int32x2_t 
arg_i32x2, int32_t arg_i32,
        vqshlus_n_s32(arg_i32, 31);
        vqshlus_n_s32(arg_i32, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vqshlus_n_s32(arg_i32, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_s64(int64_t arg_i64, int64x2_t 
arg_i64x2, int64x1_t arg_i64x1) {
@@ -251,7 +235,6 @@ void test_vector_saturating_shift_left_s64(int64_t arg_i64, 
int64x2_t arg_i64x2,
        vqshlud_n_s64(arg_i64, 63);
        vqshlud_n_s64(arg_i64, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
        vqshlud_n_s64(arg_i64, 64); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_u8(uint8x8_t arg_u8x8, uint8_t arg_u8, 
uint8x16_t arg_u8x16) {
@@ -269,7 +252,6 @@ void test_vector_saturating_shift_left_u8(uint8x8_t 
arg_u8x8, uint8_t arg_u8, ui
        vqshlb_n_u8(arg_u8, 7);
        vqshlb_n_u8(arg_u8, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vqshlb_n_u8(arg_u8, 8); // expected-error-re {{argument value {{.*}} is 
outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_u16(uint16_t arg_u16, uint16x4_t 
arg_u16x4, uint16x8_t arg_u16x8) {
@@ -287,7 +269,6 @@ void test_vector_saturating_shift_left_u16(uint16_t 
arg_u16, uint16x4_t arg_u16x
        vqshlh_n_u16(arg_u16, 15);
        vqshlh_n_u16(arg_u16, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vqshlh_n_u16(arg_u16, 16); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_u32(uint32x2_t arg_u32x2, uint32x4_t 
arg_u32x4, uint32_t arg_u32) {
@@ -305,7 +286,6 @@ void test_vector_saturating_shift_left_u32(uint32x2_t 
arg_u32x2, uint32x4_t arg_
        vqshls_n_u32(arg_u32, 31);
        vqshls_n_u32(arg_u32, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vqshls_n_u32(arg_u32, 32); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_saturating_shift_left_u64(uint64x1_t arg_u64x1, uint64_t 
arg_u64, uint64x2_t arg_u64x2) {
@@ -323,68 +303,78 @@ void test_vector_saturating_shift_left_u64(uint64x1_t 
arg_u64x1, uint64_t arg_u6
        vqshld_n_u64(arg_u64, 63);
        vqshld_n_u64(arg_u64, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
        vqshld_n_u64(arg_u64, 64); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_widen_s8(int8x8_t arg_i8x8, int8x16_t 
arg_i8x16) {
        vshll_n_s8(arg_i8x8, 0);
        vshll_n_s8(arg_i8x8, 7);
        vshll_n_s8(arg_i8x8, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
-
+       vshll_n_s8(arg_i8x8, 8); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
 
        vshll_high_n_s8(arg_i8x16, 0);
        vshll_high_n_s8(arg_i8x16, 7);
        vshll_high_n_s8(arg_i8x16, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_s8(arg_i8x16, 8); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_widen_s16(int16x4_t arg_i16x4, int16x8_t 
arg_i16x8) {
        vshll_n_s16(arg_i16x4, 0);
        vshll_n_s16(arg_i16x4, 15);
        vshll_n_s16(arg_i16x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_n_s16(arg_i16x4, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 
        vshll_high_n_s16(arg_i16x8, 0);
        vshll_high_n_s16(arg_i16x8, 15);
        vshll_high_n_s16(arg_i16x8, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_s16(arg_i16x8, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_widen_s32(int32x2_t arg_i32x2, int32x4_t 
arg_i32x4) {
        vshll_n_s32(arg_i32x2, 0);
        vshll_n_s32(arg_i32x2, 31);
        vshll_n_s32(arg_i32x2, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_n_s32(arg_i32x2, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 
        vshll_high_n_s32(arg_i32x4, 0);
        vshll_high_n_s32(arg_i32x4, 31);
        vshll_high_n_s32(arg_i32x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_s32(arg_i32x4, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_widen_u8(uint8x8_t arg_u8x8, uint8x16_t 
arg_u8x16) {
        vshll_n_u8(arg_u8x8, 0);
        vshll_n_u8(arg_u8x8, 7);
        vshll_n_u8(arg_u8x8, -1); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
+       vshll_n_u8(arg_u8x8, 8); // expected-error-re {{argument value {{.*}} 
is outside the valid range}}
 
        vshll_high_n_u8(arg_u8x16, 0);
        vshll_high_n_u8(arg_u8x16, 7);
        vshll_high_n_u8(arg_u8x16, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_u8(arg_u8x16, 8); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_widen_u16(uint16x4_t arg_u16x4, uint16x8_t 
arg_u16x8) {
        vshll_n_u16(arg_u16x4, 0);
        vshll_n_u16(arg_u16x4, 15);
        vshll_n_u16(arg_u16x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_n_u16(arg_u16x4, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 
        vshll_high_n_u16(arg_u16x8, 0);
        vshll_high_n_u16(arg_u16x8, 15);
        vshll_high_n_u16(arg_u16x8, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_u16(arg_u16x8, 16); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_widen_u32(uint32x2_t arg_u32x2, uint32x4_t 
arg_u32x4) {
        vshll_n_u32(arg_u32x2, 0);
        vshll_n_u32(arg_u32x2, 31);
        vshll_n_u32(arg_u32x2, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_n_u32(arg_u32x2, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 
        vshll_high_n_u32(arg_u32x4, 0);
        vshll_high_n_u32(arg_u32x4, 31);
        vshll_high_n_u32(arg_u32x4, -1); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
+       vshll_high_n_u32(arg_u32x4, 32); // expected-error-re {{argument value 
{{.*}} is outside the valid range}}
 }
 
 void test_vector_shift_left_and_insert_s8(int8x8_t arg_i8x8, int8x16_t 
arg_i8x16) {
@@ -397,7 +387,6 @@ void test_vector_shift_left_and_insert_s8(int8x8_t 
arg_i8x8, int8x16_t arg_i8x16
        vsliq_n_s8(arg_i8x16, arg_i8x16, 7);
        vsliq_n_s8(arg_i8x16, arg_i8x16, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_s8(arg_i8x16, arg_i8x16, 8); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_s16(int16x4_t arg_i16x4, int16x8_t 
arg_i16x8) {
@@ -410,7 +399,6 @@ void test_vector_shift_left_and_insert_s16(int16x4_t 
arg_i16x4, int16x8_t arg_i1
        vsliq_n_s16(arg_i16x8, arg_i16x8, 15);
        vsliq_n_s16(arg_i16x8, arg_i16x8, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_s16(arg_i16x8, arg_i16x8, 16); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_s32(int32x2_t arg_i32x2, int32x4_t 
arg_i32x4) {
@@ -423,7 +411,6 @@ void test_vector_shift_left_and_insert_s32(int32x2_t 
arg_i32x2, int32x4_t arg_i3
        vsliq_n_s32(arg_i32x4, arg_i32x4, 31);
        vsliq_n_s32(arg_i32x4, arg_i32x4, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_s32(arg_i32x4, arg_i32x4, 32); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_s64(int64_t arg_i64, int64x2_t 
arg_i64x2, int64x1_t arg_i64x1) {
@@ -441,7 +428,6 @@ void test_vector_shift_left_and_insert_s64(int64_t arg_i64, 
int64x2_t arg_i64x2,
        vslid_n_s64(arg_i64, arg_i64, 63);
        vslid_n_s64(arg_i64, arg_i64, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vslid_n_s64(arg_i64, arg_i64, 64); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_u8(uint8x8_t arg_u8x8, uint8x16_t 
arg_u8x16) {
@@ -454,7 +440,6 @@ void test_vector_shift_left_and_insert_u8(uint8x8_t 
arg_u8x8, uint8x16_t arg_u8x
        vsliq_n_u8(arg_u8x16, arg_u8x16, 7);
        vsliq_n_u8(arg_u8x16, arg_u8x16, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_u8(arg_u8x16, arg_u8x16, 8); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_u16(uint16x4_t arg_u16x4, uint16x8_t 
arg_u16x8) {
@@ -467,7 +452,6 @@ void test_vector_shift_left_and_insert_u16(uint16x4_t 
arg_u16x4, uint16x8_t arg_
        vsliq_n_u16(arg_u16x8, arg_u16x8, 15);
        vsliq_n_u16(arg_u16x8, arg_u16x8, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_u16(arg_u16x8, arg_u16x8, 16); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_u32(uint32x2_t arg_u32x2, uint32x4_t 
arg_u32x4) {
@@ -480,7 +464,6 @@ void test_vector_shift_left_and_insert_u32(uint32x2_t 
arg_u32x2, uint32x4_t arg_
        vsliq_n_u32(arg_u32x4, arg_u32x4, 31);
        vsliq_n_u32(arg_u32x4, arg_u32x4, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_u32(arg_u32x4, arg_u32x4, 32); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_u64(uint64x1_t arg_u64x1, uint64_t 
arg_u64, uint64x2_t arg_u64x2) {
@@ -498,7 +481,6 @@ void test_vector_shift_left_and_insert_u64(uint64x1_t 
arg_u64x1, uint64_t arg_u6
        vslid_n_u64(arg_u64, arg_u64, 63);
        vslid_n_u64(arg_u64, arg_u64, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vslid_n_u64(arg_u64, arg_u64, 64); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_p64(poly64x2_t arg_p64x2, poly64x1_t 
arg_p64x1) {
@@ -511,7 +493,6 @@ void test_vector_shift_left_and_insert_p64(poly64x2_t 
arg_p64x2, poly64x1_t arg_
        vsliq_n_p64(arg_p64x2, arg_p64x2, 63);
        vsliq_n_p64(arg_p64x2, arg_p64x2, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_p64(arg_p64x2, arg_p64x2, 64); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_p8(poly8x16_t arg_p8x16, poly8x8_t 
arg_p8x8) {
@@ -524,7 +505,6 @@ void test_vector_shift_left_and_insert_p8(poly8x16_t 
arg_p8x16, poly8x8_t arg_p8
        vsliq_n_p8(arg_p8x16, arg_p8x16, 7);
        vsliq_n_p8(arg_p8x16, arg_p8x16, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_p8(arg_p8x16, arg_p8x16, 8); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
 void test_vector_shift_left_and_insert_p16(poly16x4_t arg_p16x4, poly16x8_t 
arg_p16x8) {
@@ -537,6 +517,5 @@ void test_vector_shift_left_and_insert_p16(poly16x4_t 
arg_p16x4, poly16x8_t arg_
        vsliq_n_p16(arg_p16x8, arg_p16x8, 15);
        vsliq_n_p16(arg_p16x8, arg_p16x8, -1); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
        vsliq_n_p16(arg_p16x8, arg_p16x8, 16); // expected-error-re {{argument 
value {{.*}} is outside the valid range}}
-
 }
 
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td 
b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index a660a3f11bdb2..ca221d49c55d7 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -9541,6 +9541,11 @@ def : Pat<(v4i32 (concat_vectors (v2i32 V64:$Rd),
           (SHRNv4i32_shift (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
                            V128:$Rn, vecshiftR32Narrow:$imm)>;
 
+def : Pat<(shl (v4i32 (zext (v4i16 (extract_high_v8i16 (v8i16 V128:$Rm))))), 
(v4i32 (AArch64dup (i32 16)))),
+          (SHLLv8i16 V128:$Rm)>;
+def : Pat<(shl (v4i32 (zext (v4i16 V64:$Rm))), (v4i32 (AArch64dup (i32 16)))),
+          (SHLLv4i16 V64:$Rm)>;
+
 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)))),
diff --git a/llvm/test/CodeGen/AArch64/arm64-vcvt_f.ll 
b/llvm/test/CodeGen/AArch64/arm64-vcvt_f.ll
index 43137f4b97feb..4bafeea3bc363 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vcvt_f.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vcvt_f.ll
@@ -186,6 +186,60 @@ define <2 x bfloat> @test_vcvt_bf16_f64(<2 x double> %v) 
nounwind readnone ssp {
   ret <2 x bfloat> %vcvt1.i
 }
 
+define dso_local <4 x float> @test_vcvt_f32_bf16(<4 x bfloat> noundef %a) 
local_unnamed_addr #0 {
+; CHECK-LABEL: test_vcvt_f32_bf16:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    shll.4s v0, v0, #16
+; CHECK-NEXT:    ret
+entry:
+  %0 = bitcast <4 x bfloat> %a to <4 x i16>
+  %vmovl.i = zext <4 x i16> %0 to <4 x i32>
+  %vshl_n.i = shl nuw <4 x i32> %vmovl.i, splat (i32 16)
+  %1 = bitcast <4 x i32> %vshl_n.i to <4 x float>
+  ret <4 x float> %1
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn 
memory(none) uwtable
+define dso_local <4 x float> @test_vcvtq_low_f32_bf16(<8 x bfloat> noundef %a) 
local_unnamed_addr #0 {
+; CHECK-SD-LABEL: test_vcvtq_low_f32_bf16:
+; CHECK-SD:       // %bb.0: // %entry
+; CHECK-SD-NEXT:    shll.4s v0, v0, #16
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-FI-LABEL: test_vcvtq_low_f32_bf16:
+; CHECK-FI:       // %bb.0: // %entry
+; CHECK-FI-NEXT:    // kill: def $d0 killed $d0 killed $q0
+; CHECK-FI-NEXT:    shll.4s v0, v0, #16
+; CHECK-FI-NEXT:    ret
+;
+; CHECK-GI-LABEL: test_vcvtq_low_f32_bf16:
+; CHECK-GI:       // %bb.0: // %entry
+; CHECK-GI-NEXT:    shll.4s v0, v0, #16
+; CHECK-GI-NEXT:    ret
+entry:
+  %0 = bitcast <8 x bfloat> %a to <8 x i16>
+  %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <4 x i32> <i32 0, i32 1, 
i32 2, i32 3>
+  %vmovl.i = zext <4 x i16> %1 to <4 x i32>
+  %vshl_n.i.i = shl nuw <4 x i32> %vmovl.i, splat (i32 16)
+  %2 = bitcast <4 x i32> %vshl_n.i.i to <4 x float>
+  ret <4 x float> %2
+}
+
+; Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn 
memory(none) uwtable
+define dso_local <4 x float> @test_vcvtq_high_f32_bf16(<8 x bfloat> noundef 
%a) local_unnamed_addr #0 {
+; CHECK-LABEL: test_vcvtq_high_f32_bf16:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    shll2.4s v0, v0, #16
+; CHECK-NEXT:    ret
+entry:
+  %0 = bitcast <8 x bfloat> %a to <8 x i16>
+  %1 = shufflevector <8 x i16> %0, <8 x i16> poison, <4 x i32> <i32 4, i32 5, 
i32 6, i32 7>
+  %vmovl.i = zext <4 x i16> %1 to <4 x i32>
+  %vshl_n.i.i = shl nuw <4 x i32> %vmovl.i, splat (i32 16)
+  %2 = bitcast <4 x i32> %vshl_n.i.i to <4 x float>
+  ret <4 x float> %2
+}
+
 define half @test_vcvt_f16_f32(<1 x float> %x) {
 ; CHECK-SD-LABEL: test_vcvt_f16_f32:
 ; CHECK-SD:       // %bb.0:
diff --git a/llvm/test/CodeGen/AArch64/arm64-vshift.ll 
b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
index 8d17836a2b761..ee500710c1a97 100644
--- a/llvm/test/CodeGen/AArch64/arm64-vshift.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-vshift.ll
@@ -4135,16 +4135,10 @@ define <8 x i16> @shll(<8 x i8> %in) {
 }
 
 define <4 x i32> @shll_high(<8 x i16> %in) {
-; CHECK-SD-LABEL: shll_high:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    shll2 v0.4s, v0.8h, #16
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: shll_high:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    ushll2 v0.4s, v0.8h, #0
-; CHECK-GI-NEXT:    shl v0.4s, v0.4s, #16
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: shll_high:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    shll2 v0.4s, v0.8h, #16
+; CHECK-NEXT:    ret
   %extract = shufflevector <8 x i16> %in, <8 x i16> undef, <4 x i32> <i32 4, 
i32 5, i32 6, i32 7>
   %ext = zext <4 x i16> %extract to <4 x i32>
   %res = shl <4 x i32> %ext, <i32 16, i32 16, i32 16, i32 16>

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to