<div dir="ltr">HI Simon,<br><br>With this patch, the test CodeGen/arm-mve-intrinsics/vector-shift-imm.c seems to be failing in the buildbot.<br><br>TEST 'Clang :: CodeGen/arm-mve-intrinsics/vector-shift-imm.c' FAILED<br>Error:<br>/home/buildslave/buildslave1a/clang-with-lto-ubuntu/llvm-project/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c:177:16: error: CHECK-NEXT: expected string not found in input<br>// CHECK-NEXT: [[TMP0:%.*]] = ashr <16 x i8> [[A:%.*]], <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4><br>               ^<br><stdin>:80:2: note: scanning from here<br> %0 = ashr <16 x i8> %a, zeroinitializer<br><br><a href="http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/15132/steps/test-stage1-compiler/logs/stdio">http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/15132/steps/test-stage1-compiler/logs/stdio</a><br><br>Could you please take a look at this?<br><br>Thanks,<br>Rumeet<br><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Dec 9, 2019 at 7:44 AM Simon Tatham via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Author: Simon Tatham<br>
Date: 2019-12-09T15:44:09Z<br>
New Revision: d97b3e3e65cd77a81b39732af84a1a4229e95091<br>
<br>
URL: <a href="https://github.com/llvm/llvm-project/commit/d97b3e3e65cd77a81b39732af84a1a4229e95091" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/d97b3e3e65cd77a81b39732af84a1a4229e95091</a><br>
DIFF: <a href="https://github.com/llvm/llvm-project/commit/d97b3e3e65cd77a81b39732af84a1a4229e95091.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/d97b3e3e65cd77a81b39732af84a1a4229e95091.diff</a><br>
<br>
LOG: [ARM][MVE] Add intrinsics for immediate shifts.<br>
<br>
Summary:<br>
This adds the family of `vshlq_n` and `vshrq_n` ACLE intrinsics, which<br>
shift every lane of a vector left or right by a compile-time<br>
immediate. They mostly work by expanding to the IR `shl`, `lshr` and<br>
`ashr` operations, with their second operand being a vector splat of<br>
the immediate.<br>
<br>
There's a fiddly special case, though. ACLE specifies that the<br>
immediate in `vshrq_n` can take values up to //and including// the bit<br>
size of the vector lane. But LLVM IR thinks that shifting right by the<br>
full size of the lane is UB, and feels free to replace the `lshr` with<br>
an `undef` half way through the optimization pipeline. Hence, to keep<br>
this legal in source code, I have to detect it at codegen time.<br>
Logical (unsigned) right shifts by the element size are handled by<br>
simply emitting the zero vector; arithmetic ones are converted into a<br>
shift of one bit less, which will always give the same output.<br>
<br>
In order to do that check, I also had to enhance the tablegen<br>
MveEmitter so that it can cope with converting a builtin function's<br>
operand into a bare integer to pass to a code-generating subfunction.<br>
Previously the only bare integers it knew how to handle were flags<br>
generated from within `<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a>`.<br>
<br>
Reviewers: dmgreen, miyuki, MarkMurrayARM, ostannard<br>
<br>
Reviewed By: MarkMurrayARM<br>
<br>
Subscribers: kristof.beyls, hiraditya, cfe-commits, llvm-commits<br>
<br>
Tags: #clang, #llvm<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D71065" rel="noreferrer" target="_blank">https://reviews.llvm.org/D71065</a><br>
<br>
Added: <br>
    clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c<br>
    llvm/test/CodeGen/Thumb2/mve-intrinsics/vector-shift-imm.ll<br>
<br>
Modified: <br>
    clang/include/clang/Basic/<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a><br>
    clang/include/clang/Basic/<a href="http://arm_mve_defs.td" rel="noreferrer" target="_blank">arm_mve_defs.td</a><br>
    clang/lib/CodeGen/CGBuiltin.cpp<br>
    clang/utils/TableGen/MveEmitter.cpp<br>
    llvm/include/llvm/IR/IntrinsicsARM.td<br>
    llvm/lib/Target/ARM/ARMInstrMVE.td<br>
<br>
Removed: <br>
<br>
<br>
<br>
################################################################################<br>
diff  --git a/clang/include/clang/Basic/<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a> b/clang/include/clang/Basic/<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a><br>
index 19852702c1bc..cc4b6d9e8234 100644<br>
--- a/clang/include/clang/Basic/<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a><br>
+++ b/clang/include/clang/Basic/<a href="http://arm_mve.td" rel="noreferrer" target="_blank">arm_mve.td</a><br>
@@ -522,6 +522,33 @@ defm vstrhq: scatter_offset_both<!listconcat(T.All16, T.Int32), u16, 1>;<br>
 defm vstrwq: scatter_offset_both<T.All32, u32, 2>;<br>
 defm vstrdq: scatter_offset_both<T.Int64, u64, 3>;<br>
<br>
+multiclass PredicatedImmediateVectorShift<<br>
+    Immediate immtype, string predIntrName, list<dag> unsignedFlag = []> {<br>
+  foreach predIntr = [IRInt<predIntrName, [Vector, Predicate]>] in {<br>
+    def _m_n: Intrinsic<Vector, (args Vector:$inactive, Vector:$v,<br>
+                                      immtype:$sh, Predicate:$pred),<br>
+       !con((predIntr $v, $sh), !dag(predIntr, unsignedFlag, ?),<br>
+            (predIntr $pred, $inactive))>;<br>
+    def _x_n: Intrinsic<Vector, (args Vector:$v, immtype:$sh,<br>
+                                      Predicate:$pred),<br>
+       !con((predIntr $v, $sh), !dag(predIntr, unsignedFlag, ?),<br>
+            (predIntr $pred, (undef Vector)))>;<br>
+  }<br>
+}<br>
+<br>
+let params = T.Int in {<br>
+  def vshlq_n: Intrinsic<Vector, (args Vector:$v, imm_0toNm1:$sh),<br>
+                         (shl $v, (splat (Scalar $sh)))>;<br>
+  defm vshlq: PredicatedImmediateVectorShift<imm_0toNm1, "shl_imm_predicated">;<br>
+<br>
+  let pnt = PNT_NType in {<br>
+    def vshrq_n: Intrinsic<Vector, (args Vector:$v, imm_1toN:$sh),<br>
+                            (immshr $v, $sh, (unsignedflag Scalar))>;<br>
+    defm vshrq: PredicatedImmediateVectorShift<imm_1toN, "shr_imm_predicated",<br>
+                                     [(unsignedflag Scalar)]>;<br>
+  }<br>
+}<br>
+<br>
 // Base class for the scalar shift intrinsics.<br>
 class ScalarShift<Type argtype, dag shiftCountArg, dag shiftCodeGen>:<br>
   Intrinsic<argtype, !con((args argtype:$value), shiftCountArg), shiftCodeGen> {<br>
<br>
diff  --git a/clang/include/clang/Basic/<a href="http://arm_mve_defs.td" rel="noreferrer" target="_blank">arm_mve_defs.td</a> b/clang/include/clang/Basic/<a href="http://arm_mve_defs.td" rel="noreferrer" target="_blank">arm_mve_defs.td</a><br>
index d837a1d33d00..5aa10f250eda 100644<br>
--- a/clang/include/clang/Basic/<a href="http://arm_mve_defs.td" rel="noreferrer" target="_blank">arm_mve_defs.td</a><br>
+++ b/clang/include/clang/Basic/<a href="http://arm_mve_defs.td" rel="noreferrer" target="_blank">arm_mve_defs.td</a><br>
@@ -66,6 +66,10 @@ def xor: IRBuilder<"CreateXor">;<br>
 def sub: IRBuilder<"CreateSub">;<br>
 def shl: IRBuilder<"CreateShl">;<br>
 def lshr: IRBuilder<"CreateLShr">;<br>
+def immshr: CGHelperFn<"MVEImmediateShr"> {<br>
+  let special_params = [IRBuilderIntParam<1, "unsigned">,<br>
+                        IRBuilderIntParam<2, "bool">];<br>
+}<br>
 def fadd: IRBuilder<"CreateFAdd">;<br>
 def fmul: IRBuilder<"CreateFMul">;<br>
 def fsub: IRBuilder<"CreateFSub">;<br>
@@ -308,8 +312,8 @@ def imm_simd_vmvn : Immediate<u32, IB_UEltValue> {<br>
 //<br>
 // imm_0toNm1 is the same but with the range offset by 1, i.e. 0 to N-1<br>
 // inclusive.<br>
-def imm_1toN : Immediate<u32, IB_EltBit<1>>;<br>
-def imm_0toNm1 : Immediate<u32, IB_EltBit<0>>;<br>
+def imm_1toN : Immediate<sint, IB_EltBit<1>>;<br>
+def imm_0toNm1 : Immediate<sint, IB_EltBit<0>>;<br>
<br>
 // imm_lane has to be the index of a vector lane in the main vector type, i.e<br>
 // it can range from 0 to (128 / size of scalar)-1 inclusive. (e.g. vgetq_lane)<br>
<br>
diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp<br>
index b5b0c3e61d47..94d10a1aedf2 100644<br>
--- a/clang/lib/CodeGen/CGBuiltin.cpp<br>
+++ b/clang/lib/CodeGen/CGBuiltin.cpp<br>
@@ -6801,6 +6801,14 @@ Value *CodeGenFunction::EmitARMBuiltinExpr(unsigned BuiltinID,<br>
   }<br>
 }<br>
<br>
+template<typename Integer><br>
+static Integer GetIntegerConstantValue(const Expr *E, ASTContext &Context) {<br>
+  llvm::APSInt IntVal;<br>
+  bool IsConst = E->isIntegerConstantExpr(IntVal, Context);<br>
+  assert(IsConst && "Sema should have checked this was a constant");<br>
+  return IntVal.getExtValue();<br>
+}<br>
+<br>
 static llvm::Value *SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V,<br>
                                      llvm::Type *T, bool Unsigned) {<br>
   // Helper function called by Tablegen-constructed ARM MVE builtin codegen,<br>
@@ -6808,6 +6816,27 @@ static llvm::Value *SignOrZeroExtend(CGBuilderTy &Builder, llvm::Value *V,<br>
   return Unsigned ? Builder.CreateZExt(V, T) : Builder.CreateSExt(V, T);<br>
 }<br>
<br>
+static llvm::Value *MVEImmediateShr(CGBuilderTy &Builder, llvm::Value *V,<br>
+                                    uint32_t Shift, bool Unsigned) {<br>
+  // MVE helper function for integer shift right. This must handle signed vs<br>
+  // unsigned, and also deal specially with the case where the shift count is<br>
+  // equal to the lane size. In LLVM IR, an LShr with that parameter would be<br>
+  // undefined behavior, but in MVE it's legal, so we must convert it to code<br>
+  // that is not undefined in IR.<br>
+  unsigned LaneBits =<br>
+      V->getType()->getVectorElementType()->getPrimitiveSizeInBits();<br>
+  if (Shift == LaneBits) {<br>
+    // An unsigned shift of the full lane size always generates zero, so we can<br>
+    // simply emit a zero vector. A signed shift of the full lane size does the<br>
+    // same thing as shifting by one bit fewer.<br>
+    if (Unsigned)<br>
+      return llvm::Constant::getNullValue(V->getType());<br>
+    else<br>
+      --Shift;<br>
+  }<br>
+  return Unsigned ? Builder.CreateLShr(V, Shift) : Builder.CreateAShr(V, Shift);<br>
+}<br>
+<br>
 static llvm::Value *ARMMVEVectorSplat(CGBuilderTy &Builder, llvm::Value *V) {<br>
   // MVE-specific helper function for a vector splat, which infers the element<br>
   // count of the output vector by knowing that MVE vectors are all 128 bits<br>
<br>
diff  --git a/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c b/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c<br>
new file mode 100644<br>
index 000000000000..200273c03654<br>
--- /dev/null<br>
+++ b/clang/test/CodeGen/arm-mve-intrinsics/vector-shift-imm.c<br>
@@ -0,0 +1,722 @@<br>
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py<br>
+// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s<br>
+// RUN: %clang_cc1 -triple thumbv8.1m.main-arm-none-eabi -target-feature +mve.fp -mfloat-abi hard -fallow-half-arguments-and-returns -O0 -disable-O0-optnone -DPOLYMORPHIC -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s<br>
+<br>
+#include <arm_mve.h><br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <16 x i8> [[A:%.*]], <i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5><br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+int8x16_t test_vshlq_n_s8(int8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 5);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s8(a, 5);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <8 x i16> [[A:%.*]], <i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5><br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+int16x8_t test_vshlq_n_s16(int16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 5);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s16(a, 5);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <4 x i32> [[A:%.*]], <i32 18, i32 18, i32 18, i32 18><br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+int32x4_t test_vshlq_n_s32(int32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 18);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s32(a, 18);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s8_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <16 x i8> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+int8x16_t test_vshlq_n_s8_trivial(int8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s8(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s16_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <8 x i16> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+int16x8_t test_vshlq_n_s16_trivial(int16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s16(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_s32_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <4 x i32> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+int32x4_t test_vshlq_n_s32_trivial(int32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_s32(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <16 x i8> [[A:%.*]], <i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3, i8 3><br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+uint8x16_t test_vshlq_n_u8(uint8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 3);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u8(a, 3);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <8 x i16> [[A:%.*]], <i16 11, i16 11, i16 11, i16 11, i16 11, i16 11, i16 11, i16 11><br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+uint16x8_t test_vshlq_n_u16(uint16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 11);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u16(a, 11);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <4 x i32> [[A:%.*]], <i32 7, i32 7, i32 7, i32 7><br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+uint32x4_t test_vshlq_n_u32(uint32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 7);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u32(a, 7);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u8_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <16 x i8> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+uint8x16_t test_vshlq_n_u8_trivial(uint8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u8(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u16_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <8 x i16> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+uint16x8_t test_vshlq_n_u16_trivial(uint16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u16(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_n_u32_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = shl <4 x i32> [[A:%.*]], zeroinitializer<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+uint32x4_t test_vshlq_n_u32_trivial(uint32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_n(a, 0);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_n_u32(a, 0);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <16 x i8> [[A:%.*]], <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4><br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+int8x16_t test_vshrq_n_s8(int8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 4);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s8(a, 4);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <8 x i16> [[A:%.*]], <i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10><br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+int16x8_t test_vshrq_n_s16(int16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 10);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s16(a, 10);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <4 x i32> [[A:%.*]], <i32 19, i32 19, i32 19, i32 19><br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+int32x4_t test_vshrq_n_s32(int32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 19);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s32(a, 19);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s8_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <16 x i8> [[A:%.*]], <i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7, i8 7><br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+int8x16_t test_vshrq_n_s8_trivial(int8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 8);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s8(a, 8);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s16_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <8 x i16> [[A:%.*]], <i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15, i16 15><br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+int16x8_t test_vshrq_n_s16_trivial(int16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 16);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s16(a, 16);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_s32_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = ashr <4 x i32> [[A:%.*]], <i32 31, i32 31, i32 31, i32 31><br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+int32x4_t test_vshrq_n_s32_trivial(int32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 32);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_s32(a, 32);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = lshr <16 x i8> [[A:%.*]], <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1><br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP0]]<br>
+//<br>
+uint8x16_t test_vshrq_n_u8(uint8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 1);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u8(a, 1);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = lshr <8 x i16> [[A:%.*]], <i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10><br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP0]]<br>
+//<br>
+uint16x8_t test_vshrq_n_u16(uint16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 10);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u16(a, 10);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = lshr <4 x i32> [[A:%.*]], <i32 10, i32 10, i32 10, i32 10><br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP0]]<br>
+//<br>
+uint32x4_t test_vshrq_n_u32(uint32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 10);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u32(a, 10);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u8_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    ret <16 x i8> zeroinitializer<br>
+//<br>
+uint8x16_t test_vshrq_n_u8_trivial(uint8x16_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 8);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u8(a, 8);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u16_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    ret <8 x i16> zeroinitializer<br>
+//<br>
+uint16x8_t test_vshrq_n_u16_trivial(uint16x8_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 16);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u16(a, 16);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_n_u32_trivial(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    ret <4 x i32> zeroinitializer<br>
+//<br>
+uint32x4_t test_vshrq_n_u32_trivial(uint32x4_t a)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq(a, 32);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_n_u32(a, 32);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 6, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+int8x16_t test_vshlq_m_n_s8(int8x16_t inactive, int8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 6, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_s8(inactive, a, 6, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 13, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+int16x8_t test_vshlq_m_n_s16(int16x8_t inactive, int16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 13, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_s16(inactive, a, 13, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+int32x4_t test_vshlq_m_n_s32(int32x4_t inactive, int32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 0, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_s32(inactive, a, 0, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 3, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+uint8x16_t test_vshlq_m_n_u8(uint8x16_t inactive, uint8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 3, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_u8(inactive, a, 3, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+uint16x8_t test_vshlq_m_n_u16(uint16x8_t inactive, uint16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 1, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_u16(inactive, a, 1, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_m_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 24, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+uint32x4_t test_vshlq_m_n_u32(uint32x4_t inactive, uint32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_m_n(inactive, a, 24, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_m_n_u32(inactive, a, 24, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 2, i32 0, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+int8x16_t test_vshrq_m_n_s8(int8x16_t inactive, int8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 2, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_s8(inactive, a, 2, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 3, i32 0, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+int16x8_t test_vshrq_m_n_s16(int16x8_t inactive, int16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 3, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_s16(inactive, a, 3, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 13, i32 0, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+int32x4_t test_vshrq_m_n_s32(int32x4_t inactive, int32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 13, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_s32(inactive, a, 13, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 4, i32 1, <16 x i1> [[TMP1]], <16 x i8> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+uint8x16_t test_vshrq_m_n_u8(uint8x16_t inactive, uint8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 4, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_u8(inactive, a, 4, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 14, i32 1, <8 x i1> [[TMP1]], <8 x i16> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+uint16x8_t test_vshrq_m_n_u16(uint16x8_t inactive, uint16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 14, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_u16(inactive, a, 14, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_m_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 21, i32 1, <4 x i1> [[TMP1]], <4 x i32> [[INACTIVE:%.*]])<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+uint32x4_t test_vshrq_m_n_u32(uint32x4_t inactive, uint32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_m(inactive, a, 21, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_m_n_u32(inactive, a, 21, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 1, <16 x i1> [[TMP1]], <16 x i8> undef)<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+int8x16_t test_vshlq_x_n_s8(int8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 1, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_s8(a, 1, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 15, <8 x i1> [[TMP1]], <8 x i16> undef)<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+int16x8_t test_vshlq_x_n_s16(int16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 15, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_s16(a, 15, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 13, <4 x i1> [[TMP1]], <4 x i32> undef)<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+int32x4_t test_vshlq_x_n_s32(int32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 13, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_s32(a, 13, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 4, <16 x i1> [[TMP1]], <16 x i8> undef)<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+uint8x16_t test_vshlq_x_n_u8(uint8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 4, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_u8(a, 4, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 10, <8 x i1> [[TMP1]], <8 x i16> undef)<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+uint16x8_t test_vshlq_x_n_u16(uint16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 10, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_u16(a, 10, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshlq_x_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 30, <4 x i1> [[TMP1]], <4 x i32> undef)<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+uint32x4_t test_vshlq_x_n_u32(uint32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshlq_x_n(a, 30, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshlq_x_n_u32(a, 30, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_s8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 4, i32 0, <16 x i1> [[TMP1]], <16 x i8> undef)<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+int8x16_t test_vshrq_x_n_s8(int8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 4, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_s8(a, 4, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_s16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 10, i32 0, <8 x i1> [[TMP1]], <8 x i16> undef)<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+int16x8_t test_vshrq_x_n_s16(int16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 10, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_s16(a, 10, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_s32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 7, i32 0, <4 x i1> [[TMP1]], <4 x i32> undef)<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+int32x4_t test_vshrq_x_n_s32(int32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 7, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_s32(a, 7, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_u8(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> [[A:%.*]], i32 7, i32 1, <16 x i1> [[TMP1]], <16 x i8> undef)<br>
+// CHECK-NEXT:    ret <16 x i8> [[TMP2]]<br>
+//<br>
+uint8x16_t test_vshrq_x_n_u8(uint8x16_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 7, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_u8(a, 7, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_u16(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> [[A:%.*]], i32 7, i32 1, <8 x i1> [[TMP1]], <8 x i16> undef)<br>
+// CHECK-NEXT:    ret <8 x i16> [[TMP2]]<br>
+//<br>
+uint16x8_t test_vshrq_x_n_u16(uint16x8_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 7, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_u16(a, 7, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
+<br>
+// CHECK-LABEL: @test_vshrq_x_n_u32(<br>
+// CHECK-NEXT:  entry:<br>
+// CHECK-NEXT:    [[TMP0:%.*]] = zext i16 [[P:%.*]] to i32<br>
+// CHECK-NEXT:    [[TMP1:%.*]] = call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 [[TMP0]])<br>
+// CHECK-NEXT:    [[TMP2:%.*]] = call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> [[A:%.*]], i32 6, i32 1, <4 x i1> [[TMP1]], <4 x i32> undef)<br>
+// CHECK-NEXT:    ret <4 x i32> [[TMP2]]<br>
+//<br>
+uint32x4_t test_vshrq_x_n_u32(uint32x4_t a, mve_pred16_t p)<br>
+{<br>
+#ifdef POLYMORPHIC<br>
+    return vshrq_x(a, 6, p);<br>
+#else /* POLYMORPHIC */<br>
+    return vshrq_x_n_u32(a, 6, p);<br>
+#endif /* POLYMORPHIC */<br>
+}<br>
<br>
diff  --git a/clang/utils/TableGen/MveEmitter.cpp b/clang/utils/TableGen/MveEmitter.cpp<br>
index 422188a5f3dd..37bf3220182a 100644<br>
--- a/clang/utils/TableGen/MveEmitter.cpp<br>
+++ b/clang/utils/TableGen/MveEmitter.cpp<br>
@@ -469,6 +469,10 @@ class Result {<br>
   virtual void genCode(raw_ostream &OS, CodeGenParamAllocator &) const = 0;<br>
   virtual bool hasIntegerConstantValue() const { return false; }<br>
   virtual uint32_t integerConstantValue() const { return 0; }<br>
+  virtual bool hasIntegerValue() const { return false; }<br>
+  virtual std::string getIntegerValue(const std::string &) {<br>
+    llvm_unreachable("non-working Result::getIntegerValue called");<br>
+  }<br>
   virtual std::string typeName() const { return "Value *"; }<br>
<br>
   // Mostly, when a code-generation operation has a dependency on prior<br>
@@ -543,8 +547,9 @@ class BuiltinArgResult : public Result {<br>
 public:<br>
   unsigned ArgNum;<br>
   bool AddressType;<br>
-  BuiltinArgResult(unsigned ArgNum, bool AddressType)<br>
-      : ArgNum(ArgNum), AddressType(AddressType) {}<br>
+  bool Immediate;<br>
+  BuiltinArgResult(unsigned ArgNum, bool AddressType, bool Immediate)<br>
+      : ArgNum(ArgNum), AddressType(AddressType), Immediate(Immediate) {}<br>
   void genCode(raw_ostream &OS, CodeGenParamAllocator &) const override {<br>
     OS << (AddressType ? "EmitPointerWithAlignment" : "EmitScalarExpr")<br>
        << "(E->getArg(" << ArgNum << "))";<br>
@@ -558,6 +563,11 @@ class BuiltinArgResult : public Result {<br>
       return "(" + varname() + ".getPointer())";<br>
     return Result::asValue();<br>
   }<br>
+  bool hasIntegerValue() const override { return Immediate; }<br>
+  virtual std::string getIntegerValue(const std::string &IntType) {<br>
+    return "GetIntegerConstantValue<" + IntType + ">(E->getArg(" +<br>
+           utostr(ArgNum) + "), getContext())";<br>
+  }<br>
 };<br>
<br>
 // Result subclass for an integer literal appearing in Tablegen. This may need<br>
@@ -632,27 +642,34 @@ class IRBuilderResult : public Result {<br>
   StringRef CallPrefix;<br>
   std::vector<Ptr> Args;<br>
   std::set<unsigned> AddressArgs;<br>
-  std::map<unsigned, std::string> IntConstantArgs;<br>
+  std::map<unsigned, std::string> IntegerArgs;<br>
   IRBuilderResult(StringRef CallPrefix, std::vector<Ptr> Args,<br>
                   std::set<unsigned> AddressArgs,<br>
-                  std::map<unsigned, std::string> IntConstantArgs)<br>
-    : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs),<br>
-        IntConstantArgs(IntConstantArgs) {}<br>
+                  std::map<unsigned, std::string> IntegerArgs)<br>
+      : CallPrefix(CallPrefix), Args(Args), AddressArgs(AddressArgs),<br>
+        IntegerArgs(IntegerArgs) {}<br>
   void genCode(raw_ostream &OS,<br>
                CodeGenParamAllocator &ParamAlloc) const override {<br>
     OS << CallPrefix;<br>
     const char *Sep = "";<br>
     for (unsigned i = 0, e = Args.size(); i < e; ++i) {<br>
       Ptr Arg = Args[i];<br>
-      auto it = IntConstantArgs.find(i);<br>
-      if (it != IntConstantArgs.end()) {<br>
-        assert(Arg->hasIntegerConstantValue());<br>
-        OS << Sep << "static_cast<" << it->second << ">("<br>
-           << ParamAlloc.allocParam("unsigned",<br>
-                                    utostr(Arg->integerConstantValue()))<br>
-           << ")";<br>
+      auto it = IntegerArgs.find(i);<br>
+<br>
+      OS << Sep;<br>
+      Sep = ", ";<br>
+<br>
+      if (it != IntegerArgs.end()) {<br>
+        if (Arg->hasIntegerConstantValue())<br>
+          OS << "static_cast<" << it->second << ">("<br>
+             << ParamAlloc.allocParam(it->second,<br>
+                                      utostr(Arg->integerConstantValue()))<br>
+             << ")";<br>
+        else if (Arg->hasIntegerValue())<br>
+          OS << ParamAlloc.allocParam(it->second,<br>
+                                      Arg->getIntegerValue(it->second));<br>
       } else {<br>
-        OS << Sep << Arg->varname();<br>
+        OS << Arg->varname();<br>
       }<br>
       Sep = ", ";<br>
     }<br>
@@ -661,7 +678,8 @@ class IRBuilderResult : public Result {<br>
   void morePrerequisites(std::vector<Ptr> &output) const override {<br>
     for (unsigned i = 0, e = Args.size(); i < e; ++i) {<br>
       Ptr Arg = Args[i];<br>
-      if (IntConstantArgs.find(i) != IntConstantArgs.end())<br>
+      if (IntegerArgs.find(i) != IntegerArgs.end() &&<br>
+          Arg->hasIntegerConstantValue())<br>
         continue;<br>
       output.push_back(Arg);<br>
     }<br>
@@ -980,8 +998,8 @@ class MveEmitter {<br>
                             const Type *Param);<br>
   Result::Ptr getCodeForDagArg(DagInit *D, unsigned ArgNum,<br>
                                const Result::Scope &Scope, const Type *Param);<br>
-  Result::Ptr getCodeForArg(unsigned ArgNum, const Type *ArgType,<br>
-                            bool Promote);<br>
+  Result::Ptr getCodeForArg(unsigned ArgNum, const Type *ArgType, bool Promote,<br>
+                            bool Immediate);<br>
<br>
   // Constructor and top-level functions.<br>
<br>
@@ -1144,17 +1162,17 @@ Result::Ptr MveEmitter::getCodeForDag(DagInit *D, const Result::Scope &Scope,<br>
       Args.push_back(getCodeForDagArg(D, i, Scope, Param));<br>
     if (Op->isSubClassOf("IRBuilderBase")) {<br>
       std::set<unsigned> AddressArgs;<br>
-      std::map<unsigned, std::string> IntConstantArgs;<br>
+      std::map<unsigned, std::string> IntegerArgs;<br>
       for (Record *sp : Op->getValueAsListOfDefs("special_params")) {<br>
         unsigned Index = sp->getValueAsInt("index");<br>
         if (sp->isSubClassOf("IRBuilderAddrParam")) {<br>
           AddressArgs.insert(Index);<br>
         } else if (sp->isSubClassOf("IRBuilderIntParam")) {<br>
-          IntConstantArgs[Index] = sp->getValueAsString("type");<br>
+          IntegerArgs[Index] = sp->getValueAsString("type");<br>
         }<br>
       }<br>
-      return std::make_shared<IRBuilderResult>(<br>
-          Op->getValueAsString("prefix"), Args, AddressArgs, IntConstantArgs);<br>
+      return std::make_shared<IRBuilderResult>(Op->getValueAsString("prefix"),<br>
+                                               Args, AddressArgs, IntegerArgs);<br>
     } else if (Op->isSubClassOf("IRIntBase")) {<br>
       std::vector<const Type *> ParamTypes;<br>
       for (Record *RParam : Op->getValueAsListOfDefs("params"))<br>
@@ -1204,9 +1222,9 @@ Result::Ptr MveEmitter::getCodeForDagArg(DagInit *D, unsigned ArgNum,<br>
 }<br>
<br>
 Result::Ptr MveEmitter::getCodeForArg(unsigned ArgNum, const Type *ArgType,<br>
-                                      bool Promote) {<br>
-  Result::Ptr V =<br>
-      std::make_shared<BuiltinArgResult>(ArgNum, isa<PointerType>(ArgType));<br>
+                                      bool Promote, bool Immediate) {<br>
+  Result::Ptr V = std::make_shared<BuiltinArgResult>(<br>
+      ArgNum, isa<PointerType>(ArgType), Immediate);<br>
<br>
   if (Promote) {<br>
     if (const auto *ST = dyn_cast<ScalarType>(ArgType)) {<br>
@@ -1279,17 +1297,14 @@ ACLEIntrinsic::ACLEIntrinsic(MveEmitter &ME, Record *R, const Type *Param)<br>
     const Type *ArgType = ME.getType(TypeInit, Param);<br>
     ArgTypes.push_back(ArgType);<br>
<br>
-    // The argument will usually have a name in the arguments dag, which goes<br>
-    // into the variable-name scope that the code gen will refer to.<br>
-    StringRef ArgName = ArgsDag->getArgNameStr(i);<br>
-    if (!ArgName.empty())<br>
-      Scope[ArgName] = ME.getCodeForArg(i, ArgType, Promote);<br>
-<br>
     // If the argument is a subclass of Immediate, record the details about<br>
     // what values it can take, for Sema checking.<br>
+    bool Immediate = false;<br>
     if (auto TypeDI = dyn_cast<DefInit>(TypeInit)) {<br>
       Record *TypeRec = TypeDI->getDef();<br>
       if (TypeRec->isSubClassOf("Immediate")) {<br>
+        Immediate = true;<br>
+<br>
         Record *Bounds = TypeRec->getValueAsDef("bounds");<br>
         ImmediateArg &IA = ImmediateArgs[i];<br>
         if (Bounds->isSubClassOf("IB_ConstRange")) {<br>
@@ -1303,7 +1318,7 @@ ACLEIntrinsic::ACLEIntrinsic(MveEmitter &ME, Record *R, const Type *Param)<br>
           IA.boundsType = ImmediateArg::BoundsType::ExplicitRange;<br>
           IA.i1 = 0;<br>
           IA.i2 = 128 / Param->sizeInBits() - 1;<br>
-        } else if (Bounds->getName() == "IB_EltBit") {<br>
+        } else if (Bounds->isSubClassOf("IB_EltBit")) {<br>
           IA.boundsType = ImmediateArg::BoundsType::ExplicitRange;<br>
           IA.i1 = Bounds->getValueAsInt("base");<br>
           IA.i2 = IA.i1 + Param->sizeInBits() - 1;<br>
@@ -1320,6 +1335,12 @@ ACLEIntrinsic::ACLEIntrinsic(MveEmitter &ME, Record *R, const Type *Param)<br>
         }<br>
       }<br>
     }<br>
+<br>
+    // The argument will usually have a name in the arguments dag, which goes<br>
+    // into the variable-name scope that the code gen will refer to.<br>
+    StringRef ArgName = ArgsDag->getArgNameStr(i);<br>
+    if (!ArgName.empty())<br>
+      Scope[ArgName] = ME.getCodeForArg(i, ArgType, Promote, Immediate);<br>
   }<br>
<br>
   // Finally, go through the codegen dag and translate it into a Result object<br>
<br>
diff  --git a/llvm/include/llvm/IR/IntrinsicsARM.td b/llvm/include/llvm/IR/IntrinsicsARM.td<br>
index 71e08d18ae3c..cf896643caf8 100644<br>
--- a/llvm/include/llvm/IR/IntrinsicsARM.td<br>
+++ b/llvm/include/llvm/IR/IntrinsicsARM.td<br>
@@ -884,6 +884,14 @@ defm int_arm_mve_vstr_scatter_offset: MVEPredicated<<br>
    [], [llvm_anyptr_ty, llvm_anyvector_ty, llvm_anyvector_ty,<br>
    llvm_i32_ty, llvm_i32_ty], llvm_anyvector_ty, [IntrWriteMem]>;<br>
<br>
+def int_arm_mve_shl_imm_predicated: Intrinsic<[llvm_anyvector_ty],<br>
+   [LLVMMatchType<0>, llvm_i32_ty, llvm_anyvector_ty, LLVMMatchType<0>],<br>
+   [IntrNoMem]>;<br>
+def int_arm_mve_shr_imm_predicated: Intrinsic<[llvm_anyvector_ty],<br>
+   [LLVMMatchType<0>, llvm_i32_ty, llvm_i32_ty, // extra i32 is unsigned flag<br>
+    llvm_anyvector_ty, LLVMMatchType<0>],<br>
+   [IntrNoMem]>;<br>
+<br>
 // MVE scalar shifts.<br>
 class ARM_MVE_qrshift_single<list<LLVMType> value,<br>
                              list<LLVMType> saturate = []> :<br>
<br>
diff  --git a/llvm/lib/Target/ARM/ARMInstrMVE.td b/llvm/lib/Target/ARM/ARMInstrMVE.td<br>
index 3c0499ac4908..087ea1926694 100644<br>
--- a/llvm/lib/Target/ARM/ARMInstrMVE.td<br>
+++ b/llvm/lib/Target/ARM/ARMInstrMVE.td<br>
@@ -2689,28 +2689,38 @@ def MVE_VSHL_immi32 : MVE_VSHL_imm<"i32", (ins imm0_31:$imm)> {<br>
   let Inst{21} = 0b1;<br>
 }<br>
<br>
-let Predicates = [HasMVEInt] in {<br>
-  def : Pat<(v4i32 (ARMvshlImm (v4i32 MQPR:$src), imm0_31:$imm)),<br>
-            (v4i32 (MVE_VSHL_immi32 (v4i32 MQPR:$src), imm0_31:$imm))>;<br>
-  def : Pat<(v8i16 (ARMvshlImm (v8i16 MQPR:$src), imm0_15:$imm)),<br>
-            (v8i16 (MVE_VSHL_immi16 (v8i16 MQPR:$src), imm0_15:$imm))>;<br>
-  def : Pat<(v16i8 (ARMvshlImm (v16i8 MQPR:$src), imm0_7:$imm)),<br>
-            (v16i8 (MVE_VSHL_immi8 (v16i8 MQPR:$src), imm0_7:$imm))>;<br>
-<br>
-  def : Pat<(v4i32 (ARMvshruImm (v4i32 MQPR:$src), imm0_31:$imm)),<br>
-            (v4i32 (MVE_VSHR_immu32 (v4i32 MQPR:$src), imm0_31:$imm))>;<br>
-  def : Pat<(v8i16 (ARMvshruImm (v8i16 MQPR:$src), imm0_15:$imm)),<br>
-            (v8i16 (MVE_VSHR_immu16 (v8i16 MQPR:$src), imm0_15:$imm))>;<br>
-  def : Pat<(v16i8 (ARMvshruImm (v16i8 MQPR:$src), imm0_7:$imm)),<br>
-            (v16i8 (MVE_VSHR_immu8 (v16i8 MQPR:$src), imm0_7:$imm))>;<br>
-<br>
-  def : Pat<(v4i32 (ARMvshrsImm (v4i32 MQPR:$src), imm0_31:$imm)),<br>
-            (v4i32 (MVE_VSHR_imms32 (v4i32 MQPR:$src), imm0_31:$imm))>;<br>
-  def : Pat<(v8i16 (ARMvshrsImm (v8i16 MQPR:$src), imm0_15:$imm)),<br>
-            (v8i16 (MVE_VSHR_imms16 (v8i16 MQPR:$src), imm0_15:$imm))>;<br>
-  def : Pat<(v16i8 (ARMvshrsImm (v16i8 MQPR:$src), imm0_7:$imm)),<br>
-            (v16i8 (MVE_VSHR_imms8 (v16i8 MQPR:$src), imm0_7:$imm))>;<br>
-}<br>
+multiclass MVE_immediate_shift_patterns_inner<<br>
+    MVEVectorVTInfo VTI, Operand imm_operand_type, SDNode unpred_op,<br>
+    Intrinsic pred_int, Instruction inst, list<int> unsignedFlag = []> {<br>
+<br>
+  def : Pat<(VTI.Vec (unpred_op (VTI.Vec MQPR:$src), imm_operand_type:$imm)),<br>
+            (VTI.Vec (inst (VTI.Vec MQPR:$src), imm_operand_type:$imm))>;<br>
+<br>
+  def : Pat<(VTI.Vec !con((pred_int (VTI.Vec MQPR:$src), imm_operand_type:$imm),<br>
+                          !dag(pred_int, unsignedFlag, ?),<br>
+                          (pred_int (VTI.Pred VCCR:$mask),<br>
+                                   (VTI.Vec MQPR:$inactive)))),<br>
+            (VTI.Vec (inst (VTI.Vec MQPR:$src), imm_operand_type:$imm,<br>
+                           ARMVCCThen, (VTI.Pred VCCR:$mask),<br>
+                           (VTI.Vec MQPR:$inactive)))>;<br>
+}<br>
+<br>
+multiclass MVE_immediate_shift_patterns<MVEVectorVTInfo VTI,<br>
+                                        Operand imm_operand_type> {<br>
+  defm : MVE_immediate_shift_patterns_inner<VTI, imm_operand_type,<br>
+      ARMvshlImm, int_arm_mve_shl_imm_predicated,<br>
+      !cast<Instruction>("MVE_VSHL_immi" # VTI.BitsSuffix)>;<br>
+  defm : MVE_immediate_shift_patterns_inner<VTI, imm_operand_type,<br>
+      ARMvshruImm, int_arm_mve_shr_imm_predicated,<br>
+      !cast<Instruction>("MVE_VSHR_immu" # VTI.BitsSuffix), [1]>;<br>
+  defm : MVE_immediate_shift_patterns_inner<VTI, imm_operand_type,<br>
+      ARMvshrsImm, int_arm_mve_shr_imm_predicated,<br>
+      !cast<Instruction>("MVE_VSHR_imms" # VTI.BitsSuffix), [0]>;<br>
+}<br>
+<br>
+defm : MVE_immediate_shift_patterns<MVE_v16i8, imm0_7>;<br>
+defm : MVE_immediate_shift_patterns<MVE_v8i16, imm0_15>;<br>
+defm : MVE_immediate_shift_patterns<MVE_v4i32, imm0_31>;<br>
<br>
 // end of mve_shift instructions<br>
<br>
<br>
diff  --git a/llvm/test/CodeGen/Thumb2/mve-intrinsics/vector-shift-imm.ll b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vector-shift-imm.ll<br>
new file mode 100644<br>
index 000000000000..86228ef94b38<br>
--- /dev/null<br>
+++ b/llvm/test/CodeGen/Thumb2/mve-intrinsics/vector-shift-imm.ll<br>
@@ -0,0 +1,398 @@<br>
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py<br>
+; RUN: llc -mtriple=thumbv8.1m.main -mattr=+mve -verify-machineinstrs -o - %s | FileCheck %s<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshlq_n_s8(<16 x i8> %a) {<br>
+; CHECK-LABEL: test_vshlq_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshl.i8 q0, q0, #5<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = shl <16 x i8> %a, <i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5, i8 5><br>
+  ret <16 x i8> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshlq_n_s16(<8 x i16> %a) {<br>
+; CHECK-LABEL: test_vshlq_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshl.i16 q0, q0, #5<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = shl <8 x i16> %a, <i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5, i16 5><br>
+  ret <8 x i16> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshlq_n_s32(<4 x i32> %a) {<br>
+; CHECK-LABEL: test_vshlq_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshl.i32 q0, q0, #18<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = shl <4 x i32> %a, <i32 18, i32 18, i32 18, i32 18><br>
+  ret <4 x i32> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_n_s8(<16 x i8> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.s8 q0, q0, #4<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = ashr <16 x i8> %a, <i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4, i8 4><br>
+  ret <16 x i8> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_n_s16(<8 x i16> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.s16 q0, q0, #10<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = ashr <8 x i16> %a, <i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10><br>
+  ret <8 x i16> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_n_s32(<4 x i32> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.s32 q0, q0, #19<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = ashr <4 x i32> %a, <i32 19, i32 19, i32 19, i32 19><br>
+  ret <4 x i32> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_n_u8(<16 x i8> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_u8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.u8 q0, q0, #1<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = lshr <16 x i8> %a, <i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1, i8 1><br>
+  ret <16 x i8> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_n_u16(<8 x i16> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_u16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.u16 q0, q0, #10<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = lshr <8 x i16> %a, <i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10, i16 10><br>
+  ret <8 x i16> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_n_u32(<4 x i32> %a) {<br>
+; CHECK-LABEL: test_vshrq_n_u32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vshr.u32 q0, q0, #10<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = lshr <4 x i32> %a, <i32 10, i32 10, i32 10, i32 10><br>
+  ret <4 x i32> %0<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshlq_m_n_s8(<16 x i8> %inactive, <16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_m_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i8 q0, q1, #6<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 6, <16 x i1> %1, <16 x i8> %inactive)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshlq_m_n_s16(<8 x i16> %inactive, <8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_m_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i16 q0, q1, #13<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 13, <8 x i1> %1, <8 x i16> %inactive)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshlq_m_n_s32(<4 x i32> %inactive, <4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_m_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i32 q0, q1, #0<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 0, <4 x i1> %1, <4 x i32> %inactive)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_m_n_s8(<16 x i8> %inactive, <16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s8 q0, q1, #2<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 2, i32 0, <16 x i1> %1, <16 x i8> %inactive)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_m_n_s16(<8 x i16> %inactive, <8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s16 q0, q1, #3<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 3, i32 0, <8 x i1> %1, <8 x i16> %inactive)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_m_n_s32(<4 x i32> %inactive, <4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s32 q0, q1, #13<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 13, i32 0, <4 x i1> %1, <4 x i32> %inactive)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_m_n_u8(<16 x i8> %inactive, <16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_u8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u8 q0, q1, #4<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 4, i32 1, <16 x i1> %1, <16 x i8> %inactive)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_m_n_u16(<8 x i16> %inactive, <8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_u16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u16 q0, q1, #14<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 14, i32 1, <8 x i1> %1, <8 x i16> %inactive)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_m_n_u32(<4 x i32> %inactive, <4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_m_n_u32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u32 q0, q1, #21<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 21, i32 1, <4 x i1> %1, <4 x i32> %inactive)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshlq_x_n_s8(<16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i8 q0, q0, #1<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 1, <16 x i1> %1, <16 x i8> undef)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshlq_x_n_s16(<8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i16 q0, q0, #15<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 15, <8 x i1> %1, <8 x i16> undef)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshlq_x_n_s32(<4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i32 q0, q0, #13<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 13, <4 x i1> %1, <4 x i32> undef)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshlq_x_n_u8(<16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_u8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i8 q0, q0, #4<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 4, <16 x i1> %1, <16 x i8> undef)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshlq_x_n_u16(<8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_u16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i16 q0, q0, #10<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 10, <8 x i1> %1, <8 x i16> undef)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshlq_x_n_u32(<4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshlq_x_n_u32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshlt.i32 q0, q0, #30<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 30, <4 x i1> %1, <4 x i32> undef)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_x_n_s8(<16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_s8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s8 q0, q0, #4<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 4, i32 0, <16 x i1> %1, <16 x i8> undef)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_x_n_s16(<8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_s16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s16 q0, q0, #10<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 10, i32 0, <8 x i1> %1, <8 x i16> undef)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_x_n_s32(<4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_s32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.s32 q0, q0, #7<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 7, i32 0, <4 x i1> %1, <4 x i32> undef)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <16 x i8> @test_vshrq_x_n_u8(<16 x i8> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_u8:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u8 q0, q0, #7<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32 %0)<br>
+  %2 = tail call <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8> %a, i32 7, i32 1, <16 x i1> %1, <16 x i8> undef)<br>
+  ret <16 x i8> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <8 x i16> @test_vshrq_x_n_u16(<8 x i16> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_u16:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u16 q0, q0, #7<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32 %0)<br>
+  %2 = tail call <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16> %a, i32 7, i32 1, <8 x i1> %1, <8 x i16> undef)<br>
+  ret <8 x i16> %2<br>
+}<br>
+<br>
+define arm_aapcs_vfpcc <4 x i32> @test_vshrq_x_n_u32(<4 x i32> %a, i16 zeroext %p) {<br>
+; CHECK-LABEL: test_vshrq_x_n_u32:<br>
+; CHECK:       @ %bb.0: @ %entry<br>
+; CHECK-NEXT:    vmsr p0, r0<br>
+; CHECK-NEXT:    vpst<br>
+; CHECK-NEXT:    vshrt.u32 q0, q0, #6<br>
+; CHECK-NEXT:    bx lr<br>
+entry:<br>
+  %0 = zext i16 %p to i32<br>
+  %1 = tail call <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32 %0)<br>
+  %2 = tail call <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32> %a, i32 6, i32 1, <4 x i1> %1, <4 x i32> undef)<br>
+  ret <4 x i32> %2<br>
+}<br>
+<br>
+declare <16 x i1> @llvm.arm.mve.pred.i2v.v16i1(i32)<br>
+declare <8 x i1> @llvm.arm.mve.pred.i2v.v8i1(i32)<br>
+declare <4 x i1> @llvm.arm.mve.pred.i2v.v4i1(i32)<br>
+<br>
+declare <16 x i8> @llvm.arm.mve.shl.imm.predicated.v16i8.v16i1(<16 x i8>, i32, <16 x i1>, <16 x i8>)<br>
+declare <8 x i16> @llvm.arm.mve.shl.imm.predicated.v8i16.v8i1(<8 x i16>, i32, <8 x i1>, <8 x i16>)<br>
+declare <4 x i32> @llvm.arm.mve.shl.imm.predicated.v4i32.v4i1(<4 x i32>, i32, <4 x i1>, <4 x i32>)<br>
+<br>
+declare <16 x i8> @llvm.arm.mve.shr.imm.predicated.v16i8.v16i1(<16 x i8>, i32, i32, <16 x i1>, <16 x i8>)<br>
+declare <8 x i16> @llvm.arm.mve.shr.imm.predicated.v8i16.v8i1(<8 x i16>, i32, i32, <8 x i1>, <8 x i16>)<br>
+declare <4 x i32> @llvm.arm.mve.shr.imm.predicated.v4i32.v4i1(<4 x i32>, i32, i32, <4 x i1>, <4 x i32>)<br>
<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div>