sdesmalen created this revision.
sdesmalen added reviewers: efriedma, SjoerdMeijer, rovka.
Herald added a subscriber: tschuett.
Herald added a project: clang.
sdesmalen added a parent revision: D76679: [SveEmitter] Add more immediate 
operand checks..

Adds another bunch of of intrinsics that take immediates with
varying ranges based, some being a complex rotation immediate
which are a set of allowed immediates rather than a range.

  svmla_lane:   lane immediate ranging 0..(128/(1*sizeinbits(elt)) - 1)
  svcmla_lane:  lane immediate ranging 0..(128/(2*sizeinbits(elt)) - 1)
  svdot_lane:   lane immediate ranging 0..(128/(4*sizeinbits(elt)) - 1)
  svcadd:       complex rotate immediate [90, 270]
  svcmla:
  svcmla_lane:  complex rotate immediate [0, 90, 180, 270]


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D76680

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Basic/arm_sve.td
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla_shortform.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot_shortform.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla_shortform.c
  clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdech_shortform.c
  clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_cmla.c
  clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_dot.c
  clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_mla.c
  clang/utils/TableGen/SveEmitter.cpp

Index: clang/utils/TableGen/SveEmitter.cpp
===================================================================
--- clang/utils/TableGen/SveEmitter.cpp
+++ clang/utils/TableGen/SveEmitter.cpp
@@ -471,9 +471,19 @@
     Bitwidth = ElementBitwidth;
     NumVectors = 0;
     break;
+  case 'e':
+    Signed = false;
+    ElementBitwidth /= 2;
+    break;
   case 'h':
     ElementBitwidth /= 2;
     break;
+  case 'q':
+    ElementBitwidth /= 4;
+    break;
+  case 'o':
+    ElementBitwidth *= 4;
+    break;
   case 'P':
     Signed = true;
     Float = false;
Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_mla.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_mla.c
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -D__ARM_FEATURE_SVE %s
+
+#include <arm_sve.h>
+//
+// mla
+//
+
+svfloat16_t test_svmla_lane_f16(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  return svmla_lane_f16(op1, op2, op3, 8); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+}
+
+svfloat16_t test_svmla_lane(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  return svmla_lane(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 7]}}
+}
+
+svfloat32_t test_svmla_lane_f32(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  return svmla_lane_f32(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svfloat32_t test_svmla_lane_1(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  return svmla_lane(op1, op2, op3, 4); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svfloat64_t test_svmla_lane_f64(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  return svmla_lane_f64(op1, op2, op3, 2); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
+
+svfloat64_t test_svmla_lane_2(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  return svmla_lane(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_dot.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_dot.c
@@ -0,0 +1,46 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -D__ARM_FEATURE_SVE %s
+
+#include <arm_sve.h>
+//
+// dot
+//
+
+svint32_t test_svdot_lane_s32(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  return svdot_lane_s32(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svint32_t test_svdot_lane_s32_2(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  return svdot_lane_s32(op1, op2, op3, 4); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svint64_t test_svdot_lane_s64(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  return svdot_lane_s64(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
+
+svint64_t test_svdot_lane_s64_2(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  return svdot_lane_s64(op1, op2, op3, 2); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
+
+svuint32_t test_svdot_lane_u32(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  return svdot_lane_u32(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svuint32_t test_svdot_lane_u32_2(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  return svdot_lane_u32(op1, op2, op3, 4); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 3]}}
+}
+
+svuint64_t test_svdot_lane_u64(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  return svdot_lane_u64(op1, op2, op3, -1); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
+
+svuint64_t test_svdot_lane_u64_2(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  return svdot_lane_u64(op1, op2, op3, 2); // expected-error-re {{argument value {{[0-9]+}} is outside the valid range [0, 1]}}
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_cmla.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/negative/acle_sve_cmla.c
@@ -0,0 +1,39 @@
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -fsyntax-only -verify -D__ARM_FEATURE_SVE %s
+
+#include <arm_sve.h>
+//
+// cmla
+//
+
+svfloat16_t test_svcmla_f16_m_1(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  return svcmla_f16_m(pg, op1, op2, op3, 1); // expected-error {{argument should be the value 0,90,180 or 270}}
+}
+
+svfloat32_t test_svcmla_f32_m_1(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  return svcmla_f32_m(pg, op1, op2, op3, 1); // expected-error {{argument should be the value 0,90,180 or 270}}
+}
+
+
+// LANE
+
+svfloat16_t test_svcmla_lane_f16_neg1(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  return svcmla_lane_f16(op1, op2, op3, -1, 0); // expected-error {{argument value 18446744073709551615 is outside the valid range [0, 3]}}
+}
+
+svfloat16_t test_svcmla_lane_f16_4(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  return svcmla_lane_f16(op1, op2, op3, 4, 0); // expected-error {{argument value 4 is outside the valid range [0, 3]}}
+}
+
+svfloat32_t test_svcmla_lane_f32_neg1(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  return svcmla_lane_f32(op1, op2, op3, -1, 0); // expected-error    {{argument value 18446744073709551615 is outside the valid range [0, 1]}}
+}
+
+svfloat32_t test_svcmla_lane_f32_1(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  return svcmla_lane_f32(op1, op2, op3, 2, 0); // expected-error    {{argument value 2 is outside the valid range [0, 1]}}
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdech_shortform.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_qdech_shortform.c
@@ -0,0 +1,155 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o - -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svint16_t test_svqdech_pat_s16(svint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_s16
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.sqdech.nxv8i16(<vscale x 8 x i16> %op, i32 0, i32 1)
+  // CHECK: ret
+  return svqdech_pat(op, SV_POW2, 1);
+}
+
+svint16_t test_svqdech_pat_s16_all(svint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_s16_all
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.sqdech.nxv8i16(<vscale x 8 x i16> %op, i32 31, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_ALL, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_pow2(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_pow2
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 0, i32 1)
+  // CHECK: ret
+  return svqdech_pat(op, SV_POW2, 1);
+}
+
+svuint16_t test_svqdech_pat_u16_vl1(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl1
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 1, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL1, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl2(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl2
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 2, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL2, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl3(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl3
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 3, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL3, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl4(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl4
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 4, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL4, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl5(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl5
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 5, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL5, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl6(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl6
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 6, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL6, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl7(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl7
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 7, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL7, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl8(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl8
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 8, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL8, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl16(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl16
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 9, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL16, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl32(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl32
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 10, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL32, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl64(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl64
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 11, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL64, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl128(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl128
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 12, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL128, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_vl256(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_vl256
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 13, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_VL256, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_mul4(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_mul4
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 29, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_MUL4, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_mul3(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_mul3
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 30, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_MUL3, 16);
+}
+
+svuint16_t test_svqdech_pat_u16_all(svuint16_t op)
+{
+  // CHECK-LABEL: test_svqdech_pat_u16_all
+  // CHECK: <vscale x 8 x i16> @llvm.aarch64.sve.uqdech.nxv8i16(<vscale x 8 x i16> %op, i32 31, i32 16)
+  // CHECK: ret
+  return svqdech_pat(op, SV_ALL, 16);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla_shortform.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla_shortform.c
@@ -0,0 +1,51 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svfloat16_t test_svmla_lane_f16(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 0);
+}
+
+svfloat16_t test_svmla_lane_f16_7(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f16_7
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 7)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 7);
+}
+
+svfloat32_t test_svmla_lane_f32(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 0);
+}
+
+svfloat32_t test_svmla_lane_f32_3(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 3)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 3);
+}
+
+svfloat64_t test_svmla_lane_f64(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fmla.lane.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 0);
+}
+
+svfloat64_t test_svmla_lane_f64_1(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fmla.lane.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 1)
+  // CHECK: ret
+  return svmla_lane(op1, op2, op3, 1);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_mla.c
@@ -0,0 +1,51 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svfloat16_t test_svmla_lane_f16(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f16
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane_f16(op1, op2, op3, 0);
+}
+
+svfloat16_t test_svmla_lane_f16_7(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f16_7
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 7)
+  // CHECK: ret
+  return svmla_lane_f16(op1, op2, op3, 7);
+}
+
+svfloat32_t test_svmla_lane_f32(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane_f32(op1, op2, op3, 0);
+}
+
+svfloat32_t test_svmla_lane_f32_3(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 3)
+  // CHECK: ret
+  return svmla_lane_f32(op1, op2, op3, 3);
+}
+
+svfloat64_t test_svmla_lane_f64(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fmla.lane.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 0)
+  // CHECK: ret
+  return svmla_lane_f64(op1, op2, op3, 0);
+}
+
+svfloat64_t test_svmla_lane_f64_1(svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svmla_lane_f64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fmla.lane.nxv2f64(<vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 1)
+  // CHECK: ret
+  return svmla_lane_f64(op1, op2, op3, 1);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot_shortform.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot_shortform.c
@@ -0,0 +1,99 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svint32_t test_svdot_lane_s32(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 0);
+}
+
+svint32_t test_svdot_lane_s32_1(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 1);
+}
+
+svint32_t test_svdot_lane_s32_2(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_2
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 2)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 2);
+}
+
+svint32_t test_svdot_lane_s32_3(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 3)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 3);
+}
+
+svuint32_t test_svdot_lane_u32(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 0);
+}
+
+svuint32_t test_svdot_lane_u32_1(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 1);
+}
+
+svuint32_t test_svdot_lane_u32_2(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_2
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 2)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 2);
+}
+
+svuint32_t test_svdot_lane_u32_3(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 3)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 3);
+}
+
+svint64_t test_svdot_lane_s64(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sdot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 0);
+}
+
+svint64_t test_svdot_lane_s64_1(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sdot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 1);
+}
+
+svuint64_t test_svdot_lane_u64(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.udot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 0);
+}
+
+svuint64_t test_svdot_lane_u64_1(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.udot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane(op1, op2, op3, 1);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_dot.c
@@ -0,0 +1,99 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svint32_t test_svdot_lane_s32(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane_s32(op1, op2, op3, 0);
+}
+
+svint32_t test_svdot_lane_s32_1(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane_s32(op1, op2, op3, 1);
+}
+
+svint32_t test_svdot_lane_s32_2(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_2
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 2)
+  // CHECK: ret
+  return svdot_lane_s32(op1, op2, op3, 2);
+}
+
+svint32_t test_svdot_lane_s32_3(svint32_t op1, svint8_t op2, svint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.sdot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 3)
+  // CHECK: ret
+  return svdot_lane_s32(op1, op2, op3, 3);
+}
+
+svuint32_t test_svdot_lane_u32(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane_u32(op1, op2, op3, 0);
+}
+
+svuint32_t test_svdot_lane_u32_1(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane_u32(op1, op2, op3, 1);
+}
+
+svuint32_t test_svdot_lane_u32_2(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_2
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 2)
+  // CHECK: ret
+  return svdot_lane_u32(op1, op2, op3, 2);
+}
+
+svuint32_t test_svdot_lane_u32_3(svuint32_t op1, svuint8_t op2, svuint8_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u32_3
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.udot.lane.nxv4i32(<vscale x 4 x i32> %op1, <vscale x 16 x i8> %op2, <vscale x 16 x i8> %op3, i32 3)
+  // CHECK: ret
+  return svdot_lane_u32(op1, op2, op3, 3);
+}
+
+svint64_t test_svdot_lane_s64(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sdot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane_s64(op1, op2, op3, 0);
+}
+
+svint64_t test_svdot_lane_s64_1(svint64_t op1, svint16_t op2, svint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_s64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.sdot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane_s64(op1, op2, op3, 1);
+}
+
+svuint64_t test_svdot_lane_u64(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u64
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.udot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 0)
+  // CHECK: ret
+  return svdot_lane_u64(op1, op2, op3, 0);
+}
+
+svuint64_t test_svdot_lane_u64_1(svuint64_t op1, svuint16_t op2, svuint16_t op3)
+{
+  // CHECK-LABEL: test_svdot_lane_u64_1
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x i64> @llvm.aarch64.sve.udot.lane.nxv2i64(<vscale x 2 x i64> %op1, <vscale x 8 x i16> %op2, <vscale x 8 x i16> %op3, i32 1)
+  // CHECK: ret
+  return svdot_lane_u64(op1, op2, op3, 1);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla_shortform.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla_shortform.c
@@ -0,0 +1,178 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svfloat16_t test_svcmla_f16_m_0(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 0);
+}
+
+svfloat16_t test_svcmla_f16_m_90(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 90);
+}
+
+svfloat16_t test_svcmla_f16_m_180(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 180);
+}
+
+svfloat16_t test_svcmla_f16_m_270(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 270);
+}
+
+svfloat32_t test_svcmla_f32_m_0(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 0);
+}
+
+svfloat32_t test_svcmla_f32_m_90(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 90);
+}
+
+svfloat32_t test_svcmla_f32_m_180(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 180);
+}
+
+svfloat32_t test_svcmla_f32_m_270(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 270);
+}
+
+svfloat64_t test_svcmla_f64_m_0(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 0);
+}
+
+svfloat64_t test_svcmla_f64_m_90(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 90);
+}
+
+svfloat64_t test_svcmla_f64_m_180(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 180);
+}
+
+svfloat64_t test_svcmla_f64_m_270(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_m(pg, op1, op2, op3, 270);
+}
+
+
+// LANE
+
+svfloat16_t test_svcmla_lane_f16_0_0(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_0_0
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0, i32 0)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 0, 0);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_90(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_90
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 90)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 3, 90);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_180(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_180
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 180)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 3, 180);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_270(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_270
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 270)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 3, 270);
+}
+
+svfloat32_t test_svcmla_lane_f32_0_0(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_0_0
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0, i32 0)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 0, 0);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_90(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_90
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 90)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 1, 90);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_180(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_180
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 180)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 1, 180);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_270(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_270
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 270)
+  // CHECK: ret
+  return svcmla_lane(op1, op2, op3, 1, 270);
+}
Index: clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/aarch64-sve-intrinsics/acle_sve_cmla.c
@@ -0,0 +1,178 @@
+// RUN:  %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -fallow-half-arguments-and-returns -S -O1 -Werror -Wall -emit-llvm -o -  -D__ARM_FEATURE_SVE %s | FileCheck %s
+
+#include <arm_sve.h>
+
+svfloat16_t test_svcmla_f16_m_0(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_f16_m(pg, op1, op2, op3, 0);
+}
+
+svfloat16_t test_svcmla_f16_m_90(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_f16_m(pg, op1, op2, op3, 90);
+}
+
+svfloat16_t test_svcmla_f16_m_180(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_f16_m(pg, op1, op2, op3, 180);
+}
+
+svfloat16_t test_svcmla_f16_m_270(svbool_t pg, svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f16_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 8 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.nxv8f16(<vscale x 8 x i1> %[[P0]], <vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_f16_m(pg, op1, op2, op3, 270);
+}
+
+svfloat32_t test_svcmla_f32_m_0(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_f32_m(pg, op1, op2, op3, 0);
+}
+
+svfloat32_t test_svcmla_f32_m_90(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_f32_m(pg, op1, op2, op3, 90);
+}
+
+svfloat32_t test_svcmla_f32_m_180(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_f32_m(pg, op1, op2, op3, 180);
+}
+
+svfloat32_t test_svcmla_f32_m_270(svbool_t pg, svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f32_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 4 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.nxv4f32(<vscale x 4 x i1> %[[P0]], <vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_f32_m(pg, op1, op2, op3, 270);
+}
+
+svfloat64_t test_svcmla_f64_m_0(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_0
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 0)
+  // CHECK: ret
+  return svcmla_f64_m(pg, op1, op2, op3, 0);
+}
+
+svfloat64_t test_svcmla_f64_m_90(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_90
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 90)
+  // CHECK: ret
+  return svcmla_f64_m(pg, op1, op2, op3, 90);
+}
+
+svfloat64_t test_svcmla_f64_m_180(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_180
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 180)
+  // CHECK: ret
+  return svcmla_f64_m(pg, op1, op2, op3, 180);
+}
+
+svfloat64_t test_svcmla_f64_m_270(svbool_t pg, svfloat64_t op1, svfloat64_t op2, svfloat64_t op3)
+{
+  // CHECK-LABEL: test_svcmla_f64_m_270
+  // CHECK: %[[P0:.*]] = call <vscale x 2 x i1>  @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1> %pg)
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 2 x double> @llvm.aarch64.sve.fcmla.nxv2f64(<vscale x 2 x i1> %[[P0]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2, <vscale x 2 x double> %op3, i32 270)
+  // CHECK: ret
+  return svcmla_f64_m(pg, op1, op2, op3, 270);
+}
+
+
+// LANE
+
+svfloat16_t test_svcmla_lane_f16_0_0(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_0_0
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 0, i32 0)
+  // CHECK: ret
+  return svcmla_lane_f16(op1, op2, op3, 0, 0);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_90(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_90
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 90)
+  // CHECK: ret
+  return svcmla_lane_f16(op1, op2, op3, 3, 90);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_180(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_180
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 180)
+  // CHECK: ret
+  return svcmla_lane_f16(op1, op2, op3, 3, 180);
+}
+
+svfloat16_t test_svcmla_lane_f16_3_270(svfloat16_t op1, svfloat16_t op2, svfloat16_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f16_3_270
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 8 x half> @llvm.aarch64.sve.fcmla.lane.nxv8f16(<vscale x 8 x half> %op1, <vscale x 8 x half> %op2, <vscale x 8 x half> %op3, i32 3, i32 270)
+  // CHECK: ret
+  return svcmla_lane_f16(op1, op2, op3, 3, 270);
+}
+
+svfloat32_t test_svcmla_lane_f32_0_0(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_0_0
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 0, i32 0)
+  // CHECK: ret
+  return svcmla_lane_f32(op1, op2, op3, 0, 0);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_90(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_90
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 90)
+  // CHECK: ret
+  return svcmla_lane_f32(op1, op2, op3, 1, 90);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_180(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_180
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 180)
+  // CHECK: ret
+  return svcmla_lane_f32(op1, op2, op3, 1, 180);
+}
+
+svfloat32_t test_svcmla_lane_f32_1_270(svfloat32_t op1, svfloat32_t op2, svfloat32_t op3)
+{
+  // CHECK-LABEL: test_svcmla_lane_f32_1_270
+  // CHECK: %[[INTRINSIC:.*]] = call <vscale x 4 x float> @llvm.aarch64.sve.fcmla.lane.nxv4f32(<vscale x 4 x float> %op1, <vscale x 4 x float> %op2, <vscale x 4 x float> %op3, i32 1, i32 270)
+  // CHECK: ret
+  return svcmla_lane_f32(op1, op2, op3, 1, 270);
+}
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -2011,6 +2011,27 @@
     int ArgNum, CheckTy, ElementSizeInBits;
     std::tie(ArgNum, CheckTy, ElementSizeInBits) = I;
 
+    typedef bool(*OptionSetCheckFnTy)(int64_t Value);
+
+    // Function that checks whether the operand (ArgNum) is an immediate
+    // that is one of the predefined values.
+    auto CheckImmediateInSet = [&](OptionSetCheckFnTy CheckImm,
+                                   int ErrDiag) -> bool {
+      // We can't check the value of a dependent argument.
+      Expr *Arg = TheCall->getArg(ArgNum);
+      if (Arg->isTypeDependent() || Arg->isValueDependent())
+        return false;
+
+      // Check constant-ness first.
+      llvm::APSInt Imm;
+      if (SemaBuiltinConstantArg(TheCall, ArgNum, Imm))
+        return true;
+
+      if (!CheckImm(Imm.getSExtValue()))
+        return Diag(TheCall->getBeginLoc(), ErrDiag) << Arg->getSourceRange();
+      return false;
+    };
+
     switch ((SVETypeFlags::ImmCheckType)CheckTy) {
     case SVETypeFlags::ImmCheckPredicatePattern:
       if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0, 31))
@@ -2043,6 +2064,34 @@
                                       ElementSizeInBits - 1))
         HasError = true;
       break;
+    case SVETypeFlags::ImmCheckLaneIndex:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0,
+                                      (128 / (1 * ElementSizeInBits)) - 1))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckLaneIndexCompRotate:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0,
+                                      (128 / (2 * ElementSizeInBits)) - 1))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckLaneIndexDot:
+      if (SemaBuiltinConstantArgRange(TheCall, ArgNum, 0,
+                                      (128 / (4 * ElementSizeInBits)) - 1))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckComplexRot90_270:
+      if (CheckImmediateInSet([](int64_t V) { return V == 90 || V == 270; },
+                              diag::err_rotation_argument_to_cadd))
+        HasError = true;
+      break;
+    case SVETypeFlags::ImmCheckComplexRotAll90:
+      if (CheckImmediateInSet(
+              [](int64_t V) {
+                return V == 0 || V == 90 || V == 180 || V == 270;
+              },
+              diag::err_rotation_argument_to_cmla))
+        HasError = true;
+      break;
     }
   }
 
Index: clang/include/clang/Basic/arm_sve.td
===================================================================
--- clang/include/clang/Basic/arm_sve.td
+++ clang/include/clang/Basic/arm_sve.td
@@ -62,7 +62,10 @@
 // d: default
 // c: const pointer type
 // P: predicate type
+// e: 1/2 width unsigned elements, 2x element count
 // h: 1/2 width elements, 2x element count
+// q: 1/4 width elements, 4x element count
+// o: 4x width elements, 1/4 element count
 //
 // i: constant uint64_t
 //
@@ -159,6 +162,11 @@
 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..(128/(1*sizeinbits(elt)) - 1)
+def ImmCheckLaneIndexCompRotate : ImmCheckType<8>;  // 0..(128/(2*sizeinbits(elt)) - 1)
+def ImmCheckLaneIndexDot        : ImmCheckType<9>;  // 0..(128/(4*sizeinbits(elt)) - 1)
+def ImmCheckComplexRot90_270    : ImmCheckType<10>; // [90,270]
+def ImmCheckComplexRotAll90     : ImmCheckType<11>; // [0,90,180,270]
 
 class ImmCheck<int arg, ImmCheckType kind, int eltSizeArg = -1> {
   int Arg = arg;
@@ -306,7 +314,19 @@
 // Floating-point arithmetic
 def SVTMAD  : SInst<"svtmad[_{d}]",  "dddi", "hfd", MergeNone, "aarch64_sve_ftmad_x", [], [ImmCheck<2, ImmCheck0_7>]>;
 
+def SVMLA_LANE  : SInst<"svmla_lane[_{d}]",  "ddddi",  "hfd", MergeNone, "aarch64_sve_fmla_lane", [], [ImmCheck<3, ImmCheckLaneIndex, 2>]>;
+def SVCMLA_LANE : SInst<"svcmla_lane[_{d}]", "ddddii", "hf",  MergeNone, "aarch64_sve_fcmla_lane", [], [ImmCheck<3, ImmCheckLaneIndexCompRotate, 2>,
+                                                                                                        ImmCheck<4, ImmCheckComplexRotAll90>]>;
+
+def SVCADD_M : SInst<"svcadd[_{d}]", "dPddi",  "hfd", MergeOp1,  "aarch64_sve_fcadd", [], [ImmCheck<3, ImmCheckComplexRot90_270>]>;
+def SVCMLA_M : SInst<"svcmla[_{d}]", "dPdddi", "hfd", MergeOp1,  "aarch64_sve_fcmla", [], [ImmCheck<4, ImmCheckComplexRotAll90>]>;
+
 ////////////////////////////////////////////////////////////////////////////////
 // Saturating scalar arithmetic
 def SVQDECH_S : SInst<"svqdech_pat[_{d}]",   "ddIi", "s", MergeNone, "aarch64_sve_sqdech", [], [ImmCheck<2, ImmCheck1_16>]>;
 def SVQDECH_U : SInst<"svqdech_pat[_{d}]",   "ddIi", "Us", MergeNone, "aarch64_sve_uqdech", [], [ImmCheck<2, ImmCheck1_16>]>;
+
+////////////////////////////////////////////////////////////////////////////////
+// Integer arithmetic
+def SVDOT_LANE_S : SInst<"svdot_lane[_{d}]",  "ddqqi",  "il",   MergeNone, "aarch64_sve_sdot_lane", [], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
+def SVDOT_LANE_U : SInst<"svdot_lane[_{d}]",  "ddqqi",  "UiUl", MergeNone, "aarch64_sve_udot_lane", [], [ImmCheck<3, ImmCheckLaneIndexDot, 2>]>;
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9202,6 +9202,10 @@
   "argument should be an 8-bit value shifted by a multiple of 8 bits">;
 def err_argument_not_shifted_byte_or_xxff : Error<
   "argument should be an 8-bit value shifted by a multiple of 8 bits, or in the form 0x??FF">;
+def err_rotation_argument_to_cadd
+    : Error<"argument should be the value 90 or 270">;
+def err_rotation_argument_to_cmla
+    : Error<"argument should be the value 0,90,180 or 270">;
 def warn_neon_vector_initializer_non_portable : Warning<
   "vector initializers are not compatible with NEON intrinsics in big endian "
   "mode">, InGroup<DiagGroup<"nonportable-vector-initialization">>;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to