c-rhodes updated this revision to Diff 279265.
c-rhodes added a comment.

Change the default for `EnforceFixedLengthSVEAttribute`.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D83553/new/

https://reviews.llvm.org/D83553

Files:
  clang/lib/CodeGen/CGExpr.cpp
  clang/lib/CodeGen/CodeGenFunction.cpp
  clang/lib/CodeGen/CodeGenFunction.h
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/lib/CodeGen/CodeGenTypes.cpp
  clang/lib/CodeGen/CodeGenTypes.h
  clang/test/Sema/attr-arm-sve-vector-bits-bitcast.c
  clang/test/Sema/attr-arm-sve-vector-bits-call.c
  clang/test/Sema/attr-arm-sve-vector-bits-cast.c
  clang/test/Sema/attr-arm-sve-vector-bits-codegen.c
  clang/test/Sema/attr-arm-sve-vector-bits-globals.c
  clang/test/Sema/attr-arm-sve-vector-bits-types.c

Index: clang/test/Sema/attr-arm-sve-vector-bits-types.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-types.c
@@ -0,0 +1,525 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-128
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=256 -fallow-half-arguments-and-returns -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-256
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-512
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=1024 -fallow-half-arguments-and-returns -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-1024
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=2048 -fallow-half-arguments-and-returns -S -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-2048
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint16_t fixed_int16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svuint8_t fixed_uint8_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint16_t fixed_uint16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint32_t fixed_uint32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svuint64_t fixed_uint64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svfloat16_t fixed_float16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat32_t fixed_float32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+//===----------------------------------------------------------------------===//
+// Structs and unions
+//===----------------------------------------------------------------------===//
+#define DEFINE_STRUCT(ty) \
+  struct struct_##ty {    \
+    fixed_##ty##_t x;     \
+  } struct_##ty;
+
+#define DEFINE_UNION(ty) \
+  union union_##ty {     \
+    fixed_##ty##_t x;    \
+  } union_##ty;
+
+DEFINE_STRUCT(int8)
+DEFINE_STRUCT(int16)
+DEFINE_STRUCT(int32)
+DEFINE_STRUCT(int64)
+DEFINE_STRUCT(uint8)
+DEFINE_STRUCT(uint16)
+DEFINE_STRUCT(uint32)
+DEFINE_STRUCT(uint64)
+DEFINE_STRUCT(float16)
+DEFINE_STRUCT(float32)
+DEFINE_STRUCT(float64)
+DEFINE_STRUCT(bfloat16)
+DEFINE_STRUCT(bool)
+
+DEFINE_UNION(int8)
+DEFINE_UNION(int16)
+DEFINE_UNION(int32)
+DEFINE_UNION(int64)
+DEFINE_UNION(uint8)
+DEFINE_UNION(uint16)
+DEFINE_UNION(uint32)
+DEFINE_UNION(uint64)
+DEFINE_UNION(float16)
+DEFINE_UNION(float32)
+DEFINE_UNION(float64)
+DEFINE_UNION(bfloat16)
+DEFINE_UNION(bool)
+
+//===----------------------------------------------------------------------===//
+// Global variables
+//===----------------------------------------------------------------------===//
+fixed_int8_t global_i8;
+fixed_int16_t global_i16;
+fixed_int32_t global_i32;
+fixed_int64_t global_i64;
+
+fixed_uint8_t global_u8;
+fixed_uint16_t global_u16;
+fixed_uint32_t global_u32;
+fixed_uint64_t global_u64;
+
+fixed_float16_t global_f16;
+fixed_float32_t global_f32;
+fixed_float64_t global_f64;
+
+fixed_bfloat16_t global_bf16;
+
+fixed_bool_t global_bool;
+
+//===----------------------------------------------------------------------===//
+// Global arrays
+//===----------------------------------------------------------------------===//
+fixed_int8_t global_arr_i8[3];
+fixed_int16_t global_arr_i16[3];
+fixed_int32_t global_arr_i32[3];
+fixed_int64_t global_arr_i64[3];
+
+fixed_uint8_t global_arr_u8[3];
+fixed_uint16_t global_arr_u16[3];
+fixed_uint32_t global_arr_u32[3];
+fixed_uint64_t global_arr_u64[3];
+
+fixed_float16_t global_arr_f16[3];
+fixed_float32_t global_arr_f32[3];
+fixed_float64_t global_arr_f64[3];
+
+fixed_bfloat16_t global_arr_bf16[3];
+
+fixed_bool_t global_arr_bool[3];
+
+//===----------------------------------------------------------------------===//
+// Locals
+//===----------------------------------------------------------------------===//
+void f() {
+  // Variables
+  fixed_int8_t local_i8;
+  fixed_int16_t local_i16;
+  fixed_int32_t local_i32;
+  fixed_int64_t local_i64;
+  fixed_uint8_t local_u8;
+  fixed_uint16_t local_u16;
+  fixed_uint32_t local_u32;
+  fixed_uint64_t local_u64;
+  fixed_float16_t local_f16;
+  fixed_float32_t local_f32;
+  fixed_float64_t local_f64;
+  fixed_bfloat16_t local_bf16;
+  fixed_bool_t local_bool;
+
+  // Arrays
+  fixed_int8_t local_arr_i8[3];
+  fixed_int16_t local_arr_i16[3];
+  fixed_int32_t local_arr_i32[3];
+  fixed_int64_t local_arr_i64[3];
+  fixed_uint8_t local_arr_u8[3];
+  fixed_uint16_t local_arr_u16[3];
+  fixed_uint32_t local_arr_u32[3];
+  fixed_uint64_t local_arr_u64[3];
+  fixed_float16_t local_arr_f16[3];
+  fixed_float32_t local_arr_f32[3];
+  fixed_float64_t local_arr_f64[3];
+  fixed_bfloat16_t local_arr_bf16[3];
+  fixed_bool_t local_arr_bool[3];
+}
+
+//===----------------------------------------------------------------------===//
+// Structs and unions
+//===----------------------------------------------------------------------===//
+// CHECK-128:      %struct.struct_int8 = type { [16 x i8] }
+// CHECK-128-NEXT: %struct.struct_int16 = type { [8 x i16] }
+// CHECK-128-NEXT: %struct.struct_int32 = type { [4 x i32] }
+// CHECK-128-NEXT: %struct.struct_int64 = type { [2 x i64] }
+// CHECK-128-NEXT: %struct.struct_uint8 = type { [16 x i8] }
+// CHECK-128-NEXT: %struct.struct_uint16 = type { [8 x i16] }
+// CHECK-128-NEXT: %struct.struct_uint32 = type { [4 x i32] }
+// CHECK-128-NEXT: %struct.struct_uint64 = type { [2 x i64] }
+// CHECK-128-NEXT: %struct.struct_float16 = type { [8 x half] }
+// CHECK-128-NEXT: %struct.struct_float32 = type { [4 x float] }
+// CHECK-128-NEXT: %struct.struct_float64 = type { [2 x double] }
+// CHECK-128-NEXT: %struct.struct_bfloat16 = type { [8 x bfloat] }
+// CHECK-128-NEXT: %struct.struct_bool = type { [2 x i8] }
+
+// CHECK-256:      %struct.struct_int8 = type { [32 x i8] }
+// CHECK-256-NEXT: %struct.struct_int16 = type { [16 x i16] }
+// CHECK-256-NEXT: %struct.struct_int32 = type { [8 x i32] }
+// CHECK-256-NEXT: %struct.struct_int64 = type { [4 x i64] }
+// CHECK-256-NEXT: %struct.struct_uint8 = type { [32 x i8] }
+// CHECK-256-NEXT: %struct.struct_uint16 = type { [16 x i16] }
+// CHECK-256-NEXT: %struct.struct_uint32 = type { [8 x i32] }
+// CHECK-256-NEXT: %struct.struct_uint64 = type { [4 x i64] }
+// CHECK-256-NEXT: %struct.struct_float16 = type { [16 x half] }
+// CHECK-256-NEXT: %struct.struct_float32 = type { [8 x float] }
+// CHECK-256-NEXT: %struct.struct_float64 = type { [4 x double] }
+// CHECK-256-NEXT: %struct.struct_bfloat16 = type { [16 x bfloat] }
+// CHECK-256-NEXT: %struct.struct_bool = type { [4 x i8] }
+
+// CHECK-512:      %struct.struct_int8 = type { [64 x i8] }
+// CHECK-512-NEXT: %struct.struct_int16 = type { [32 x i16] }
+// CHECK-512-NEXT: %struct.struct_int32 = type { [16 x i32] }
+// CHECK-512-NEXT: %struct.struct_int64 = type { [8 x i64] }
+// CHECK-512-NEXT: %struct.struct_uint8 = type { [64 x i8] }
+// CHECK-512-NEXT: %struct.struct_uint16 = type { [32 x i16] }
+// CHECK-512-NEXT: %struct.struct_uint32 = type { [16 x i32] }
+// CHECK-512-NEXT: %struct.struct_uint64 = type { [8 x i64] }
+// CHECK-512-NEXT: %struct.struct_float16 = type { [32 x half] }
+// CHECK-512-NEXT: %struct.struct_float32 = type { [16 x float] }
+// CHECK-512-NEXT: %struct.struct_float64 = type { [8 x double] }
+// CHECK-512-NEXT: %struct.struct_bfloat16 = type { [32 x bfloat] }
+// CHECK-512-NEXT: %struct.struct_bool = type { [8 x i8] }
+
+// CHECK-1024:      %struct.struct_int8 = type { [128 x i8] }
+// CHECK-1024-NEXT: %struct.struct_int16 = type { [64 x i16] }
+// CHECK-1024-NEXT: %struct.struct_int32 = type { [32 x i32] }
+// CHECK-1024-NEXT: %struct.struct_int64 = type { [16 x i64] }
+// CHECK-1024-NEXT: %struct.struct_uint8 = type { [128 x i8] }
+// CHECK-1024-NEXT: %struct.struct_uint16 = type { [64 x i16] }
+// CHECK-1024-NEXT: %struct.struct_uint32 = type { [32 x i32] }
+// CHECK-1024-NEXT: %struct.struct_uint64 = type { [16 x i64] }
+// CHECK-1024-NEXT: %struct.struct_float16 = type { [64 x half] }
+// CHECK-1024-NEXT: %struct.struct_float32 = type { [32 x float] }
+// CHECK-1024-NEXT: %struct.struct_float64 = type { [16 x double] }
+// CHECK-1024-NEXT: %struct.struct_bfloat16 = type { [64 x bfloat] }
+// CHECK-1024-NEXT: %struct.struct_bool = type { [16 x i8] }
+
+// CHECK-2048:      %struct.struct_int8 = type { [256 x i8] }
+// CHECK-2048-NEXT: %struct.struct_int16 = type { [128 x i16] }
+// CHECK-2048-NEXT: %struct.struct_int32 = type { [64 x i32] }
+// CHECK-2048-NEXT: %struct.struct_int64 = type { [32 x i64] }
+// CHECK-2048-NEXT: %struct.struct_uint8 = type { [256 x i8] }
+// CHECK-2048-NEXT: %struct.struct_uint16 = type { [128 x i16] }
+// CHECK-2048-NEXT: %struct.struct_uint32 = type { [64 x i32] }
+// CHECK-2048-NEXT: %struct.struct_uint64 = type { [32 x i64] }
+// CHECK-2048-NEXT: %struct.struct_float16 = type { [128 x half] }
+// CHECK-2048-NEXT: %struct.struct_float32 = type { [64 x float] }
+// CHECK-2048-NEXT: %struct.struct_float64 = type { [32 x double] }
+// CHECK-2048-NEXT: %struct.struct_bfloat16 = type { [128 x bfloat] }
+// CHECK-2048-NEXT: %struct.struct_bool = type { [32 x i8] }
+
+// CHECK-128:      %union.union_int8 = type { [16 x i8] }
+// CHECK-128-NEXT: %union.union_int16 = type { [8 x i16] }
+// CHECK-128-NEXT: %union.union_int32 = type { [4 x i32] }
+// CHECK-128-NEXT: %union.union_int64 = type { [2 x i64] }
+// CHECK-128-NEXT: %union.union_uint8 = type { [16 x i8] }
+// CHECK-128-NEXT: %union.union_uint16 = type { [8 x i16] }
+// CHECK-128-NEXT: %union.union_uint32 = type { [4 x i32] }
+// CHECK-128-NEXT: %union.union_uint64 = type { [2 x i64] }
+// CHECK-128-NEXT: %union.union_float16 = type { [8 x half] }
+// CHECK-128-NEXT: %union.union_float32 = type { [4 x float] }
+// CHECK-128-NEXT: %union.union_float64 = type { [2 x double] }
+// CHECK-128-NEXT: %union.union_bfloat16 = type { [8 x bfloat] }
+// CHECK-128-NEXT: %union.union_bool = type { [2 x i8] }
+
+// CHECK-256:      %union.union_int8 = type { [32 x i8] }
+// CHECK-256-NEXT: %union.union_int16 = type { [16 x i16] }
+// CHECK-256-NEXT: %union.union_int32 = type { [8 x i32] }
+// CHECK-256-NEXT: %union.union_int64 = type { [4 x i64] }
+// CHECK-256-NEXT: %union.union_uint8 = type { [32 x i8] }
+// CHECK-256-NEXT: %union.union_uint16 = type { [16 x i16] }
+// CHECK-256-NEXT: %union.union_uint32 = type { [8 x i32] }
+// CHECK-256-NEXT: %union.union_uint64 = type { [4 x i64] }
+// CHECK-256-NEXT: %union.union_float16 = type { [16 x half] }
+// CHECK-256-NEXT: %union.union_float32 = type { [8 x float] }
+// CHECK-256-NEXT: %union.union_float64 = type { [4 x double] }
+// CHECK-256-NEXT: %union.union_bfloat16 = type { [16 x bfloat] }
+// CHECK-256-NEXT: %union.union_bool = type { [4 x i8] }
+
+// CHECK-512:      %union.union_int8 = type { [64 x i8] }
+// CHECK-512-NEXT: %union.union_int16 = type { [32 x i16] }
+// CHECK-512-NEXT: %union.union_int32 = type { [16 x i32] }
+// CHECK-512-NEXT: %union.union_int64 = type { [8 x i64] }
+// CHECK-512-NEXT: %union.union_uint8 = type { [64 x i8] }
+// CHECK-512-NEXT: %union.union_uint16 = type { [32 x i16] }
+// CHECK-512-NEXT: %union.union_uint32 = type { [16 x i32] }
+// CHECK-512-NEXT: %union.union_uint64 = type { [8 x i64] }
+// CHECK-512-NEXT: %union.union_float16 = type { [32 x half] }
+// CHECK-512-NEXT: %union.union_float32 = type { [16 x float] }
+// CHECK-512-NEXT: %union.union_float64 = type { [8 x double] }
+// CHECK-512-NEXT: %union.union_bfloat16 = type { [32 x bfloat] }
+// CHECK-512-NEXT: %union.union_bool = type { [8 x i8] }
+
+// CHECK-1024:      %union.union_int8 = type { [128 x i8] }
+// CHECK-1024-NEXT: %union.union_int16 = type { [64 x i16] }
+// CHECK-1024-NEXT: %union.union_int32 = type { [32 x i32] }
+// CHECK-1024-NEXT: %union.union_int64 = type { [16 x i64] }
+// CHECK-1024-NEXT: %union.union_uint8 = type { [128 x i8] }
+// CHECK-1024-NEXT: %union.union_uint16 = type { [64 x i16] }
+// CHECK-1024-NEXT: %union.union_uint32 = type { [32 x i32] }
+// CHECK-1024-NEXT: %union.union_uint64 = type { [16 x i64] }
+// CHECK-1024-NEXT: %union.union_float16 = type { [64 x half] }
+// CHECK-1024-NEXT: %union.union_float32 = type { [32 x float] }
+// CHECK-1024-NEXT: %union.union_float64 = type { [16 x double] }
+// CHECK-1024-NEXT: %union.union_bfloat16 = type { [64 x bfloat] }
+// CHECK-1024-NEXT: %union.union_bool = type { [16 x i8] }
+
+// CHECK-2048:      %union.union_int8 = type { [256 x i8] }
+// CHECK-2048-NEXT: %union.union_int16 = type { [128 x i16] }
+// CHECK-2048-NEXT: %union.union_int32 = type { [64 x i32] }
+// CHECK-2048-NEXT: %union.union_int64 = type { [32 x i64] }
+// CHECK-2048-NEXT: %union.union_uint8 = type { [256 x i8] }
+// CHECK-2048-NEXT: %union.union_uint16 = type { [128 x i16] }
+// CHECK-2048-NEXT: %union.union_uint32 = type { [64 x i32] }
+// CHECK-2048-NEXT: %union.union_uint64 = type { [32 x i64] }
+// CHECK-2048-NEXT: %union.union_float16 = type { [128 x half] }
+// CHECK-2048-NEXT: %union.union_float32 = type { [64 x float] }
+// CHECK-2048-NEXT: %union.union_float64 = type { [32 x double] }
+// CHECK-2048-NEXT: %union.union_bfloat16 = type { [128 x bfloat] }
+// CHECK-2048-NEXT: %union.union_bool = type { [32 x i8] }
+
+//===----------------------------------------------------------------------===//
+// Global variables
+//===----------------------------------------------------------------------===//
+// CHECK-128:      @global_i8 = global [16 x i8] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_i16 = global [8 x i16] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_i32 = global [4 x i32] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_i64 = global [2 x i64] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_u8 = global [16 x i8] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_u16 = global [8 x i16] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_u32 = global [4 x i32] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_u64 = global [2 x i64] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_f16 = global [8 x half] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_f32 = global [4 x float] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_f64 = global [2 x double] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_bf16 = global [8 x bfloat] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_bool = global [2 x i8] zeroinitializer, align 2
+
+// CHECK-256:      @global_i8 = global [32 x i8] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_i16 = global [16 x i16] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_i32 = global [8 x i32] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_i64 = global [4 x i64] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_u8 = global [32 x i8] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_u16 = global [16 x i16] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_u32 = global [8 x i32] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_u64 = global [4 x i64] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_f16 = global [16 x half] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_f32 = global [8 x float] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_f64 = global [4 x double] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_bf16 = global [16 x bfloat] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_bool = global [4 x i8] zeroinitializer, align 2
+
+// CHECK-512:      @global_i8 = global [64 x i8] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_i16 = global [32 x i16] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_i32 = global [16 x i32] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_i64 = global [8 x i64] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_u8 = global [64 x i8] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_u16 = global [32 x i16] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_u32 = global [16 x i32] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_u64 = global [8 x i64] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_f16 = global [32 x half] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_f32 = global [16 x float] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_f64 = global [8 x double] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_bf16 = global [32 x bfloat] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_bool = global [8 x i8] zeroinitializer, align 2
+
+// CHECK-1024:      @global_i8 = global [128 x i8] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_i16 = global [64 x i16] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_i32 = global [32 x i32] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_i64 = global [16 x i64] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_u8 = global [128 x i8] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_u16 = global [64 x i16] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_u32 = global [32 x i32] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_u64 = global [16 x i64] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_f16 = global [64 x half] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_f32 = global [32 x float] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_f64 = global [16 x double] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_bf16 = global [64 x bfloat] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_bool = global [16 x i8] zeroinitializer, align 2
+
+// CHECK-2048:      @global_i8 = global [256 x i8] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_i16 = global [128 x i16] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_i32 = global [64 x i32] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_i64 = global [32 x i64] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_u8 = global [256 x i8] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_u16 = global [128 x i16] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_u32 = global [64 x i32] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_u64 = global [32 x i64] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_f16 = global [128 x half] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_f32 = global [64 x float] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_f64 = global [32 x double] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_bf16 = global [128 x bfloat] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_bool = global [32 x i8] zeroinitializer, align 2
+
+//===----------------------------------------------------------------------===//
+// Global arrays
+//===----------------------------------------------------------------------===//
+// CHECK-128:      @global_arr_i8 = global [3 x [16 x i8]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_i16 = global [3 x [8 x i16]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_i32 = global [3 x [4 x i32]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_i64 = global [3 x [2 x i64]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_u8 = global [3 x [16 x i8]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_u16 = global [3 x [8 x i16]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_u32 = global [3 x [4 x i32]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_u64 = global [3 x [2 x i64]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_f16 = global [3 x [8 x half]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_f32 = global [3 x [4 x float]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_f64 = global [3 x [2 x double]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_bf16 = global [3 x [8 x bfloat]] zeroinitializer, align 16
+// CHECK-128-NEXT: @global_arr_bool = global [3 x [2 x i8]] zeroinitializer, align 2
+
+// CHECK-256:      @global_arr_i8 = global [3 x [32 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_i16 = global [3 x [16 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_i32 = global [3 x [8 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_i64 = global [3 x [4 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_u8 = global [3 x [32 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_u16 = global [3 x [16 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_u32 = global [3 x [8 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_u64 = global [3 x [4 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_f16 = global [3 x [16 x half]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_f32 = global [3 x [8 x float]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_f64 = global [3 x [4 x double]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_bf16 = global [3 x [16 x bfloat]] zeroinitializer, align 16
+// CHECK-NEXT-256: @global_arr_bool = global [3 x [4 x i8]] zeroinitializer, align 2
+
+// CHECK-512:      @global_arr_i8 = global [3 x [64 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_i16 = global [3 x [32 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_i32 = global [3 x [16 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_i64 = global [3 x [8 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_u8 = global [3 x [64 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_u16 = global [3 x [32 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_u32 = global [3 x [16 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_u64 = global [3 x [8 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_f16 = global [3 x [32 x half]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_f32 = global [3 x [16 x float]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_f64 = global [3 x [8 x double]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_bf16 = global [3 x [32 x bfloat]] zeroinitializer, align 16
+// CHECK-NEXT-512: @global_arr_bool = global [3 x [8 x i8]] zeroinitializer, align 2
+
+// CHECK-1024:      @global_arr_i8 = global [3 x [128 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_i16 = global [3 x [64 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_i32 = global [3 x [32 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_i64 = global [3 x [16 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_u8 = global [3 x [128 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_u16 = global [3 x [64 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_u32 = global [3 x [32 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_u64 = global [3 x [16 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_f16 = global [3 x [64 x half]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_f32 = global [3 x [32 x float]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_f64 = global [3 x [16 x double]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_bf16 = global [3 x [64 x bfloat]] zeroinitializer, align 16
+// CHECK-NEXT-1024: @global_arr_bool = global [3 x [16 x i8]] zeroinitializer, align 2
+
+// CHECK-2048:      @global_arr_i8 = global [3 x [256 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_i16 = global [3 x [128 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_i32 = global [3 x [64 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_i64 = global [3 x [32 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_u8 = global [3 x [256 x i8]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_u16 = global [3 x [128 x i16]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_u32 = global [3 x [64 x i32]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_u64 = global [3 x [32 x i64]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_f16 = global [3 x [128 x half]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_f32 = global [3 x [64 x float]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_f64 = global [3 x [32 x double]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_bf16 = global [3 x [128 x bfloat]] zeroinitializer, align 16
+// CHECK-NEXT-2048: @global_arr_bool = global [3 x [32 x i8]] zeroinitializer, align 2
+
+//===----------------------------------------------------------------------===//
+// Local variables
+//===----------------------------------------------------------------------===//
+// CHECK:      %local_i8 = alloca <vscale x 16 x i8>, align 16
+// CHECK-NEXT: %local_i16 = alloca <vscale x 8 x i16>, align 16
+// CHECK-NEXT: %local_i32 = alloca <vscale x 4 x i32>, align 16
+// CHECK-NEXT: %local_i64 = alloca <vscale x 2 x i64>, align 16
+// CHECK-NEXT: %local_u8 = alloca <vscale x 16 x i8>, align 16
+// CHECK-NEXT: %local_u16 = alloca <vscale x 8 x i16>, align 16
+// CHECK-NEXT: %local_u32 = alloca <vscale x 4 x i32>, align 16
+// CHECK-NEXT: %local_u64 = alloca <vscale x 2 x i64>, align 16
+// CHECK-NEXT: %local_f16 = alloca <vscale x 8 x half>, align 16
+// CHECK-NEXT: %local_f32 = alloca <vscale x 4 x float>, align 16
+// CHECK-NEXT: %local_f64 = alloca <vscale x 2 x double>, align 16
+// CHECK-NEXT: %local_bf16 = alloca <vscale x 8 x bfloat>, align 16
+// CHECK-NEXT: %local_bool = alloca <vscale x 16 x i1>, align 2
+
+//===----------------------------------------------------------------------===//
+// Local arrays
+//===----------------------------------------------------------------------===//
+// CHECK-128:      %local_arr_i8 = alloca [3 x [16 x i8]], align 16
+// CHECK-128-NEXT: %local_arr_i16 = alloca [3 x [8 x i16]], align 16
+// CHECK-128-NEXT: %local_arr_i32 = alloca [3 x [4 x i32]], align 16
+// CHECK-128-NEXT: %local_arr_i64 = alloca [3 x [2 x i64]], align 16
+// CHECK-128-NEXT: %local_arr_u8 = alloca [3 x [16 x i8]], align 16
+// CHECK-128-NEXT: %local_arr_u16 = alloca [3 x [8 x i16]], align 16
+// CHECK-128-NEXT: %local_arr_u32 = alloca [3 x [4 x i32]], align 16
+// CHECK-128-NEXT: %local_arr_u64 = alloca [3 x [2 x i64]], align 16
+// CHECK-128-NEXT: %local_arr_f16 = alloca [3 x [8 x half]], align 16
+// CHECK-128-NEXT: %local_arr_f32 = alloca [3 x [4 x float]], align 16
+// CHECK-128-NEXT: %local_arr_f64 = alloca [3 x [2 x double]], align 16
+// CHECK-128-NEXT: %local_arr_bf16 = alloca [3 x [8 x bfloat]], align 16
+// CHECK-128-NEXT: %local_arr_bool = alloca [3 x [2 x i8]], align 2
+
+// CHECK-256:      %local_arr_i8 = alloca [3 x [32 x i8]], align 16
+// CHECK-256-NEXT: %local_arr_i16 = alloca [3 x [16 x i16]], align 16
+// CHECK-256-NEXT: %local_arr_i32 = alloca [3 x [8 x i32]], align 16
+// CHECK-256-NEXT: %local_arr_i64 = alloca [3 x [4 x i64]], align 16
+// CHECK-256-NEXT: %local_arr_u8 = alloca [3 x [32 x i8]], align 16
+// CHECK-256-NEXT: %local_arr_u16 = alloca [3 x [16 x i16]], align 16
+// CHECK-256-NEXT: %local_arr_u32 = alloca [3 x [8 x i32]], align 16
+// CHECK-256-NEXT: %local_arr_u64 = alloca [3 x [4 x i64]], align 16
+// CHECK-256-NEXT: %local_arr_f16 = alloca [3 x [16 x half]], align 16
+// CHECK-256-NEXT: %local_arr_f32 = alloca [3 x [8 x float]], align 16
+// CHECK-256-NEXT: %local_arr_f64 = alloca [3 x [4 x double]], align 16
+// CHECK-256-NEXT: %local_arr_bf16 = alloca [3 x [16 x bfloat]], align 16
+// CHECK-256-NEXT: %local_arr_bool = alloca [3 x [4 x i8]], align 2
+
+// CHECK-512:      %local_arr_i8 = alloca [3 x [64 x i8]], align 16
+// CHECK-512-NEXT: %local_arr_i16 = alloca [3 x [32 x i16]], align 16
+// CHECK-512-NEXT: %local_arr_i32 = alloca [3 x [16 x i32]], align 16
+// CHECK-512-NEXT: %local_arr_i64 = alloca [3 x [8 x i64]], align 16
+// CHECK-512-NEXT: %local_arr_u8 = alloca [3 x [64 x i8]], align 16
+// CHECK-512-NEXT: %local_arr_u16 = alloca [3 x [32 x i16]], align 16
+// CHECK-512-NEXT: %local_arr_u32 = alloca [3 x [16 x i32]], align 16
+// CHECK-512-NEXT: %local_arr_u64 = alloca [3 x [8 x i64]], align 16
+// CHECK-512-NEXT: %local_arr_f16 = alloca [3 x [32 x half]], align 16
+// CHECK-512-NEXT: %local_arr_f32 = alloca [3 x [16 x float]], align 16
+// CHECK-512-NEXT: %local_arr_f64 = alloca [3 x [8 x double]], align 16
+// CHECK-512-NEXT: %local_arr_bf16 = alloca [3 x [32 x bfloat]], align 16
+// CHECK-512-NEXT: %local_arr_bool = alloca [3 x [8 x i8]], align 2
+
+// CHECK-1024:       %local_arr_i8 = alloca [3 x [128 x i8]], align 16
+// CHECK-1024-NEXT:  %local_arr_i16 = alloca [3 x [64 x i16]], align 16
+// CHECK-1024-NEXT:  %local_arr_i32 = alloca [3 x [32 x i32]], align 16
+// CHECK-1024-NEXT:  %local_arr_i64 = alloca [3 x [16 x i64]], align 16
+// CHECK-1024-NEXT:  %local_arr_u8 = alloca [3 x [128 x i8]], align 16
+// CHECK-1024-NEXT:  %local_arr_u16 = alloca [3 x [64 x i16]], align 16
+// CHECK-1024-NEXT:  %local_arr_u32 = alloca [3 x [32 x i32]], align 16
+// CHECK-1024-NEXT:  %local_arr_u64 = alloca [3 x [16 x i64]], align 16
+// CHECK-1024-NEXT:  %local_arr_f16 = alloca [3 x [64 x half]], align 16
+// CHECK-1024-NEXT:  %local_arr_f32 = alloca [3 x [32 x float]], align 16
+// CHECK-1024-NEXT:  %local_arr_f64 = alloca [3 x [16 x double]], align 16
+// CHECK-1024-NEXT:  %local_arr_bf16 = alloca [3 x [64 x bfloat]], align 16
+// CHECK-1024-NEXT:  %local_arr_bool = alloca [3 x [16 x i8]], align 2
+
+// CHECK-2048:       %local_arr_i8 = alloca [3 x [256 x i8]], align 16
+// CHECK-2048-NEXT:  %local_arr_i16 = alloca [3 x [128 x i16]], align 16
+// CHECK-2048-NEXT:  %local_arr_i32 = alloca [3 x [64 x i32]], align 16
+// CHECK-2048-NEXT:  %local_arr_i64 = alloca [3 x [32 x i64]], align 16
+// CHECK-2048-NEXT:  %local_arr_u8 = alloca [3 x [256 x i8]], align 16
+// CHECK-2048-NEXT:  %local_arr_u16 = alloca [3 x [128 x i16]], align 16
+// CHECK-2048-NEXT:  %local_arr_u32 = alloca [3 x [64 x i32]], align 16
+// CHECK-2048-NEXT:  %local_arr_u64 = alloca [3 x [32 x i64]], align 16
+// CHECK-2048-NEXT:  %local_arr_f16 = alloca [3 x [128 x half]], align 16
+// CHECK-2048-NEXT:  %local_arr_f32 = alloca [3 x [64 x float]], align 16
+// CHECK-2048-NEXT:  %local_arr_f64 = alloca [3 x [32 x double]], align 16
+// CHECK-2048-NEXT:  %local_arr_bf16 = alloca [3 x [128 x bfloat]], align 16
+// CHECK-2048-NEXT:  %local_arr_bool = alloca [3 x [32 x i8]], align 2
Index: clang/test/Sema/attr-arm-sve-vector-bits-globals.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-globals.c
@@ -0,0 +1,96 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-128
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-512
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+fixed_int64_t global_i64;
+fixed_bfloat16_t global_bf16;
+fixed_bool_t global_bool;
+
+//===----------------------------------------------------------------------===//
+// WRITES
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @write_global_i64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    store <vscale x 2 x i64> [[V:%.*]], <vscale x 2 x i64>* bitcast ([2 x i64]* @global_i64 to <vscale x 2 x i64>*), align 16, !tbaa !2
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_global_i64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    store <vscale x 2 x i64> [[V:%.*]], <vscale x 2 x i64>* bitcast ([8 x i64]* @global_i64 to <vscale x 2 x i64>*), align 16, !tbaa !2
+// CHECK-512-NEXT:    ret void
+//
+void write_global_i64(svint64_t v) { global_i64 = v; }
+
+// CHECK-128-LABEL: @write_global_bf16(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    store <vscale x 8 x bfloat> [[V:%.*]], <vscale x 8 x bfloat>* bitcast ([8 x bfloat]* @global_bf16 to <vscale x 8 x bfloat>*), align 16, !tbaa !6
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_global_bf16(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    store <vscale x 8 x bfloat> [[V:%.*]], <vscale x 8 x bfloat>* bitcast ([32 x bfloat]* @global_bf16 to <vscale x 8 x bfloat>*), align 16, !tbaa !6
+// CHECK-512-NEXT:    ret void
+//
+void write_global_bf16(svbfloat16_t v) { global_bf16 = v; }
+
+// CHECK-128-LABEL: @write_global_bool(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    store <vscale x 16 x i1> [[V:%.*]], <vscale x 16 x i1>* bitcast ([2 x i8]* @global_bool to <vscale x 16 x i1>*), align 2, !tbaa !8
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_global_bool(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    store <vscale x 16 x i1> [[V:%.*]], <vscale x 16 x i1>* bitcast ([8 x i8]* @global_bool to <vscale x 16 x i1>*), align 2, !tbaa !8
+// CHECK-512-NEXT:    ret void
+//
+void write_global_bool(svbool_t v) { global_bool = v; }
+
+//===----------------------------------------------------------------------===//
+// READS
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @read_global_i64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x i64>, <vscale x 2 x i64>* bitcast ([2 x i64]* @global_i64 to <vscale x 2 x i64>*), align 16, !tbaa !2
+// CHECK-128-NEXT:    ret <vscale x 2 x i64> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_global_i64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x i64>, <vscale x 2 x i64>* bitcast ([8 x i64]* @global_i64 to <vscale x 2 x i64>*), align 16, !tbaa !2
+// CHECK-512-NEXT:    ret <vscale x 2 x i64> [[TMP0]]
+//
+svint64_t read_global_i64() { return global_i64; }
+
+// CHECK-128-LABEL: @read_global_bf16(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x bfloat>, <vscale x 8 x bfloat>* bitcast ([8 x bfloat]* @global_bf16 to <vscale x 8 x bfloat>*), align 16, !tbaa !6
+// CHECK-128-NEXT:    ret <vscale x 8 x bfloat> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_global_bf16(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x bfloat>, <vscale x 8 x bfloat>* bitcast ([32 x bfloat]* @global_bf16 to <vscale x 8 x bfloat>*), align 16, !tbaa !6
+// CHECK-512-NEXT:    ret <vscale x 8 x bfloat> [[TMP0]]
+//
+svbfloat16_t read_global_bf16() { return global_bf16; }
+
+// CHECK-128-LABEL: @read_global_bool(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* bitcast ([2 x i8]* @global_bool to <vscale x 16 x i1>*), align 2, !tbaa !8
+// CHECK-128-NEXT:    ret <vscale x 16 x i1> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_global_bool(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* bitcast ([8 x i8]* @global_bool to <vscale x 16 x i1>*), align 2, !tbaa !8
+// CHECK-512-NEXT:    ret <vscale x 16 x i1> [[TMP0]]
+//
+svbool_t read_global_bool() { return global_bool; }
Index: clang/test/Sema/attr-arm-sve-vector-bits-codegen.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-codegen.c
@@ -0,0 +1,26 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+fixed_bool_t global_pred;
+fixed_int32_t global_vec;
+
+// CHECK-LABEL: @foo(
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* bitcast ([8 x i8]* @global_pred to <vscale x 16 x i1>*), align 2, !tbaa !2
+// CHECK-NEXT:    [[TMP1:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> [[PRED:%.*]], <vscale x 16 x i1> [[TMP0]], <vscale x 16 x i1> [[TMP0]])
+// CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 4 x i32>, <vscale x 4 x i32>* bitcast ([16 x i32]* @global_vec to <vscale x 4 x i32>*), align 16, !tbaa !6
+// CHECK-NEXT:    [[TMP3:%.*]] = call <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1> [[TMP1]])
+// CHECK-NEXT:    [[TMP4:%.*]] = call <vscale x 4 x i32> @llvm.aarch64.sve.add.nxv4i32(<vscale x 4 x i1> [[TMP3]], <vscale x 4 x i32> [[TMP2]], <vscale x 4 x i32> [[VEC:%.*]])
+// CHECK-NEXT:    ret <vscale x 4 x i32> [[TMP4]]
+//
+fixed_int32_t foo(svbool_t pred, svint32_t vec) {
+  svbool_t pg = svand_z(pred, global_pred, global_pred);
+  return svadd_m(pg, global_vec, vec);
+}
Index: clang/test/Sema/attr-arm-sve-vector-bits-cast.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-cast.c
@@ -0,0 +1,61 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=256 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=1024 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=2048 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+#define CAST(TYPE)                                        \
+  sv##TYPE##_t to_sv##TYPE##_t(fixed_##TYPE##_t type) {   \
+    return type;                                          \
+  }                                                       \
+                                                          \
+  fixed_##TYPE##_t from_sv##TYPE##_t(sv##TYPE##_t type) { \
+    return type;                                          \
+  }
+
+CAST(int64)
+CAST(float64)
+CAST(bfloat16)
+CAST(bool)
+
+// CHECK-LABEL: to_svint64_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 2 x i64> %type
+
+// CHECK-LABEL: from_svint64_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 2 x i64> %type
+
+// CHECK-LABEL: to_svfloat64_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 2 x double> %type
+
+// CHECK-LABEL: from_svfloat64_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 2 x double> %type
+
+// CHECK-LABEL: to_svbfloat16_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 8 x bfloat> %type
+
+// CHECK-LABEL: from_svbfloat16_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 8 x bfloat> %type
+
+// CHECK-LABEL: to_svbool_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 16 x i1> %type
+
+// CHECK-LABEL: from_svbool_t
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:  ret <vscale x 16 x i1> %type
Index: clang/test/Sema/attr-arm-sve-vector-bits-call.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-call.c
@@ -0,0 +1,105 @@
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=256 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=1024 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=2048 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+#define CALL_FIXED_FIXED(ty)                                                \
+  fixed_##ty##_t                                                            \
+      call_##ty##_ff(svbool_t pg, fixed_##ty##_t op1, fixed_##ty##_t op2) { \
+    return svsel(pg, op1, op2);                                             \
+  }
+
+#define CALL_FIXED_SCALABLE(ty)                                         \
+  fixed_##ty##_t                                                        \
+      call_##ty##_fs(svbool_t pg, fixed_##ty##_t op1, sv##ty##_t op2) { \
+    return svsel(pg, op1, op2);                                         \
+  }
+
+#define CALL_SCALABLE_FIXED(ty)                                         \
+  fixed_##ty##_t                                                        \
+      call_##ty##_sf(svbool_t pg, sv##ty##_t op1, fixed_##ty##_t op2) { \
+    return svsel(pg, op1, op2);                                         \
+  }
+
+CALL_FIXED_FIXED(int64);
+CALL_FIXED_FIXED(float64);
+CALL_FIXED_FIXED(bfloat16);
+CALL_FIXED_FIXED(bool);
+
+CALL_FIXED_SCALABLE(int64);
+CALL_FIXED_SCALABLE(float64);
+CALL_FIXED_SCALABLE(bfloat16);
+CALL_FIXED_SCALABLE(bool);
+
+CALL_SCALABLE_FIXED(int64);
+CALL_SCALABLE_FIXED(float64);
+CALL_SCALABLE_FIXED(bfloat16);
+CALL_SCALABLE_FIXED(bool);
+
+// CHECK-LABEL: call_int64_ff
+// CHECK: %[[PG:.*]] = 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 i64> @llvm.aarch64.sve.sel.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2)
+// CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_float64_ff
+// CHECK: %[[PG:.*]] = 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.sel.nxv2f64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2)
+// CHECK: ret <vscale x 2 x double> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bfloat16_ff
+// CHECK: %[[PG:.*]] = 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 bfloat> @llvm.aarch64.sve.sel.nxv8bf16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x bfloat> %op1, <vscale x 8 x bfloat> %op2)
+// CHECK: ret <vscale x 8 x bfloat> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bool_ff
+// CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.sel.nxv16i1(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %op1, <vscale x 16 x i1> %op2)
+// CHECK: ret <vscale x 16 x i1> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_int64_fs
+// CHECK: %[[PG:.*]] = 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 i64> @llvm.aarch64.sve.sel.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2)
+// CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_float64_fs
+// CHECK: %[[PG:.*]] = 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.sel.nxv2f64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2)
+// CHECK: ret <vscale x 2 x double> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bfloat16_fs
+// CHECK: %[[PG:.*]] = 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 bfloat> @llvm.aarch64.sve.sel.nxv8bf16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x bfloat> %op1, <vscale x 8 x bfloat> %op2)
+// CHECK: ret <vscale x 8 x bfloat> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bool_fs
+// CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.sel.nxv16i1(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %op1, <vscale x 16 x i1> %op2)
+// CHECK: ret <vscale x 16 x i1> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_int64_sf
+// CHECK: %[[PG:.*]] = 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 i64> @llvm.aarch64.sve.sel.nxv2i64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x i64> %op1, <vscale x 2 x i64> %op2)
+// CHECK: ret <vscale x 2 x i64> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_float64_sf
+// CHECK: %[[PG:.*]] = 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.sel.nxv2f64(<vscale x 2 x i1> %[[PG]], <vscale x 2 x double> %op1, <vscale x 2 x double> %op2)
+// CHECK: ret <vscale x 2 x double> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bfloat16_sf
+// CHECK: %[[PG:.*]] = 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 bfloat> @llvm.aarch64.sve.sel.nxv8bf16(<vscale x 8 x i1> %[[PG]], <vscale x 8 x bfloat> %op1, <vscale x 8 x bfloat> %op2)
+// CHECK: ret <vscale x 8 x bfloat> %[[INTRINSIC]]
+
+// CHECK-LABEL: call_bool_sf
+// CHECK: %[[INTRINSIC:.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.sel.nxv16i1(<vscale x 16 x i1> %pg, <vscale x 16 x i1> %op1, <vscale x 16 x i1> %op2)
+// CHECK: ret <vscale x 16 x i1> %[[INTRINSIC]]
Index: clang/test/Sema/attr-arm-sve-vector-bits-bitcast.c
===================================================================
--- /dev/null
+++ clang/test/Sema/attr-arm-sve-vector-bits-bitcast.c
@@ -0,0 +1,240 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// REQUIRES: aarch64-registered-target
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=128 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-128
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=256 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-256
+// RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -target-feature +bf16 -msve-vector-bits=512 -fallow-half-arguments-and-returns -S -O1 -emit-llvm -o - %s | FileCheck %s --check-prefix=CHECK-512
+
+#include <arm_sve.h>
+
+#define N __ARM_FEATURE_SVE_BITS_EXPERIMENTAL
+
+typedef svint64_t fixed_int64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svfloat64_t fixed_float64_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbfloat16_t fixed_bfloat16_t __attribute__((arm_sve_vector_bits(N)));
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+
+#define DEFINE_STRUCT(ty)   \
+  struct struct_##ty {      \
+    fixed_##ty##_t x, y[3]; \
+  } struct_##ty;
+
+DEFINE_STRUCT(int64)
+DEFINE_STRUCT(float64)
+DEFINE_STRUCT(bfloat16)
+DEFINE_STRUCT(bool)
+
+//===----------------------------------------------------------------------===//
+// int64
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @read_int64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x i64>, <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-128-NEXT:    ret <vscale x 2 x i64> [[TMP0]]
+//
+// CHECK-256-LABEL: @read_int64(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-256-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x i64>, <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-256-NEXT:    ret <vscale x 2 x i64> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_int64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x i64>, <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-512-NEXT:    ret <vscale x 2 x i64> [[TMP0]]
+//
+svint64_t read_int64(struct struct_int64 *s) {
+  return s->y[0];
+}
+
+// CHECK-128-LABEL: @write_int64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-128-NEXT:    store <vscale x 2 x i64> [[X:%.*]], <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-256-LABEL: @write_int64(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-256-NEXT:    store <vscale x 2 x i64> [[X:%.*]], <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-256-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_int64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_INT64:%.*]], %struct.struct_int64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x i64]* [[ARRAYIDX]] to <vscale x 2 x i64>*
+// CHECK-512-NEXT:    store <vscale x 2 x i64> [[X:%.*]], <vscale x 2 x i64>* [[CAST_TO_SCALABLE]], align 16, !tbaa !2
+// CHECK-512-NEXT:    ret void
+//
+void write_int64(struct struct_int64 *s, svint64_t x) {
+  s->y[0] = x;
+}
+
+//===----------------------------------------------------------------------===//
+// float64
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @read_float64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x double>, <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-128-NEXT:    ret <vscale x 2 x double> [[TMP0]]
+//
+// CHECK-256-LABEL: @read_float64(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-256-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x double>, <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-256-NEXT:    ret <vscale x 2 x double> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_float64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 2 x double>, <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-512-NEXT:    ret <vscale x 2 x double> [[TMP0]]
+//
+svfloat64_t read_float64(struct struct_float64 *s) {
+  return s->y[0];
+}
+
+// CHECK-128-LABEL: @write_float64(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-128-NEXT:    store <vscale x 2 x double> [[X:%.*]], <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-256-LABEL: @write_float64(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-256-NEXT:    store <vscale x 2 x double> [[X:%.*]], <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-256-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_float64(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_FLOAT64:%.*]], %struct.struct_float64* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x double]* [[ARRAYIDX]] to <vscale x 2 x double>*
+// CHECK-512-NEXT:    store <vscale x 2 x double> [[X:%.*]], <vscale x 2 x double>* [[CAST_TO_SCALABLE]], align 16, !tbaa !6
+// CHECK-512-NEXT:    ret void
+//
+void write_float64(struct struct_float64 *s, svfloat64_t x) {
+  s->y[0] = x;
+}
+
+//===----------------------------------------------------------------------===//
+// bfloat16
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @read_bfloat16(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x bfloat>, <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-128-NEXT:    ret <vscale x 8 x bfloat> [[TMP0]]
+//
+// CHECK-256-LABEL: @read_bfloat16(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [16 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-256-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x bfloat>, <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-256-NEXT:    ret <vscale x 8 x bfloat> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_bfloat16(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [32 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 8 x bfloat>, <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-512-NEXT:    ret <vscale x 8 x bfloat> [[TMP0]]
+//
+svbfloat16_t read_bfloat16(struct struct_bfloat16 *s) {
+  return s->y[0];
+}
+
+// CHECK-128-LABEL: @write_bfloat16(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-128-NEXT:    store <vscale x 8 x bfloat> [[X:%.*]], <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-256-LABEL: @write_bfloat16(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [16 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-256-NEXT:    store <vscale x 8 x bfloat> [[X:%.*]], <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-256-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_bfloat16(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BFLOAT16:%.*]], %struct.struct_bfloat16* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [32 x bfloat]* [[ARRAYIDX]] to <vscale x 8 x bfloat>*
+// CHECK-512-NEXT:    store <vscale x 8 x bfloat> [[X:%.*]], <vscale x 8 x bfloat>* [[CAST_TO_SCALABLE]], align 16, !tbaa !8
+// CHECK-512-NEXT:    ret void
+//
+void write_bfloat16(struct struct_bfloat16 *s, svbfloat16_t x) {
+  s->y[0] = x;
+}
+
+//===----------------------------------------------------------------------===//
+// bool
+//===----------------------------------------------------------------------===//
+
+// CHECK-128-LABEL: @read_bool(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-128-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-128-NEXT:    ret <vscale x 16 x i1> [[TMP0]]
+//
+// CHECK-256-LABEL: @read_bool(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-256-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-256-NEXT:    ret <vscale x 16 x i1> [[TMP0]]
+//
+// CHECK-512-LABEL: @read_bool(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-512-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-512-NEXT:    ret <vscale x 16 x i1> [[TMP0]]
+//
+svbool_t read_bool(struct struct_bool *s) {
+  return s->y[0];
+}
+
+// CHECK-128-LABEL: @write_bool(
+// CHECK-128-NEXT:  entry:
+// CHECK-128-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-128-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [2 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-128-NEXT:    store <vscale x 16 x i1> [[X:%.*]], <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-128-NEXT:    ret void
+//
+// CHECK-256-LABEL: @write_bool(
+// CHECK-256-NEXT:  entry:
+// CHECK-256-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-256-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [4 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-256-NEXT:    store <vscale x 16 x i1> [[X:%.*]], <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-256-NEXT:    ret void
+//
+// CHECK-512-LABEL: @write_bool(
+// CHECK-512-NEXT:  entry:
+// CHECK-512-NEXT:    [[ARRAYIDX:%.*]] = getelementptr inbounds [[STRUCT_STRUCT_BOOL:%.*]], %struct.struct_bool* [[S:%.*]], i64 0, i32 1, i64 0
+// CHECK-512-NEXT:    [[CAST_TO_SCALABLE:%.*]] = bitcast [8 x i8]* [[ARRAYIDX]] to <vscale x 16 x i1>*
+// CHECK-512-NEXT:    store <vscale x 16 x i1> [[X:%.*]], <vscale x 16 x i1>* [[CAST_TO_SCALABLE]], align 2, !tbaa !10
+// CHECK-512-NEXT:    ret void
+//
+void write_bool(struct struct_bool *s, svbool_t x) {
+  s->y[0] = x;
+}
Index: clang/lib/CodeGen/CodeGenTypes.h
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.h
+++ clang/lib/CodeGen/CodeGenTypes.h
@@ -134,7 +134,10 @@
   /// ConvertType in that it is used to convert to the memory representation for
   /// a type.  For example, the scalar representation for _Bool is i1, but the
   /// memory representation is usually i8 or i32, depending on the target.
-  llvm::Type *ConvertTypeForMem(QualType T, bool ForBitField = false);
+  /// If \arg EnforceFixedLengthSVEAttribute is specified \arg T is converted to
+  /// a fixed-length type. This only applies if T->isVLST().
+  llvm::Type *ConvertTypeForMem(QualType T, bool ForBitField = false,
+                                bool EnforceFixedLengthSVEAttribute = true);
 
   /// GetFunctionType - Get the LLVM function type for \arg Info.
   llvm::FunctionType *GetFunctionType(const CGFunctionInfo &Info);
@@ -290,6 +293,11 @@
   void getExpandedTypes(QualType Ty,
                         SmallVectorImpl<llvm::Type *>::iterator &TI);
 
+  /// Returns the fixed-length type for an SVE ACLE scalable vector attributed
+  /// with 'arm_sve_vector_bits' that can be used in certain places where
+  /// size is really needed, e.g. members of structs or arrays or globals.
+  llvm::Optional<llvm::Type *> getFixedLengthSVETypeForMemory(const Type *T);
+
   /// IsZeroInitializable - Return whether a type can be
   /// zero-initialized (in the C++ sense) with an LLVM zeroinitializer.
   bool isZeroInitializable(QualType T);
Index: clang/lib/CodeGen/CodeGenTypes.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenTypes.cpp
+++ clang/lib/CodeGen/CodeGenTypes.cpp
@@ -77,11 +77,64 @@
   Ty->setName(OS.str());
 }
 
+llvm::Optional<llvm::Type *>
+CodeGenTypes::getFixedLengthSVETypeForMemory(const Type *T) {
+  if (!T->isVLST())
+    return {};
+
+  unsigned VectorSize = Context.getBitwidthForAttributedSveType(T);
+
+  llvm::LLVMContext &Context = getLLVMContext();
+
+  llvm::Type *MemEltTy = nullptr;
+  switch (T->castAs<BuiltinType>()->getKind()) {
+  default:
+    llvm_unreachable("unhandled type!");
+  case BuiltinType::SveInt8:
+  case BuiltinType::SveUint8:
+  case BuiltinType::SveBool:
+    // Represent predicates in memory as i8 rather than i1 to avoid any layout
+    // issues. The type is bitcasted to the appropriate scalable predicate type
+    // when dealing with memory.
+    MemEltTy = llvm::Type::getInt8Ty(Context);
+    break;
+  case BuiltinType::SveInt16:
+  case BuiltinType::SveUint16:
+    MemEltTy = llvm::Type::getInt16Ty(Context);
+    break;
+  case BuiltinType::SveInt32:
+  case BuiltinType::SveUint32:
+    MemEltTy = llvm::Type::getInt32Ty(Context);
+    break;
+  case BuiltinType::SveInt64:
+  case BuiltinType::SveUint64:
+    MemEltTy = llvm::Type::getInt64Ty(Context);
+    break;
+  case BuiltinType::SveFloat16:
+    MemEltTy = llvm::Type::getHalfTy(Context);
+    break;
+  case BuiltinType::SveFloat32:
+    MemEltTy = llvm::Type::getFloatTy(Context);
+    break;
+  case BuiltinType::SveFloat64:
+    MemEltTy = llvm::Type::getDoubleTy(Context);
+    break;
+  case BuiltinType::SveBFloat16:
+    MemEltTy = llvm::Type::getBFloatTy(Context);
+    break;
+  }
+
+  return {llvm::ArrayType::get(
+      MemEltTy, VectorSize / MemEltTy->getPrimitiveSizeInBits())};
+}
+
 /// ConvertTypeForMem - Convert type T into a llvm::Type.  This differs from
 /// ConvertType in that it is used to convert to the memory representation for
 /// a type.  For example, the scalar representation for _Bool is i1, but the
 /// memory representation is usually i8 or i32, depending on the target.
-llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField) {
+llvm::Type *
+CodeGenTypes::ConvertTypeForMem(QualType T, bool ForBitField,
+                                bool EnforceFixedLengthSVEAttribute) {
   if (T->isConstantMatrixType()) {
     const Type *Ty = Context.getCanonicalType(T).getTypePtr();
     const ConstantMatrixType *MT = cast<ConstantMatrixType>(Ty);
@@ -89,6 +142,19 @@
                                 MT->getNumRows() * MT->getNumColumns());
   }
 
+  if (T->isConstantArrayType()) {
+    const ConstantArrayType *A = Context.getAsConstantArrayType(T);
+    const QualType EltTy = A->getElementType();
+
+    if (auto MemTy = getFixedLengthSVETypeForMemory(EltTy.getTypePtr()))
+      return llvm::ArrayType::get(*MemTy, A->getSize().getZExtValue());
+  }
+
+  if (EnforceFixedLengthSVEAttribute) {
+    if (auto MemTy = getFixedLengthSVETypeForMemory(T.getTypePtr()))
+      return *MemTy;
+  }
+
   llvm::Type *R = ConvertType(T);
 
   // If this is a bool type, or an ExtIntType in a bitfield representation,
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3977,7 +3977,12 @@
     // exists. A use may still exists, however, so we still may need
     // to do a RAUW.
     assert(!ASTTy->isIncompleteType() && "Unexpected incomplete type");
-    Init = EmitNullConstant(D->getType());
+    // Lower global scalable vectors to fixed-length vectors.
+    if (auto MemTy =
+            getTypes().getFixedLengthSVETypeForMemory(ASTTy.getTypePtr()))
+      Init = llvm::Constant::getNullValue(*MemTy);
+    else
+      Init = EmitNullConstant(D->getType());
   } else {
     initializedGlobalDecl = GlobalDecl(D);
     emitter.emplace(*this);
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -2257,7 +2257,8 @@
   /// a terminate scope encloses a try.
   llvm::BasicBlock *getTerminateHandler();
 
-  llvm::Type *ConvertTypeForMem(QualType T);
+  llvm::Type *ConvertTypeForMem(QualType T, bool ForBitField = false,
+                                bool EnforceFixedLengthSVEAttribute = true);
   llvm::Type *ConvertType(QualType T);
   llvm::Type *ConvertType(const TypeDecl *T) {
     return ConvertType(getContext().getTypeDeclType(T));
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -193,9 +193,11 @@
   return MakeAddrLValue(Address(V, Align), T, BaseInfo, TBAAInfo);
 }
 
-
-llvm::Type *CodeGenFunction::ConvertTypeForMem(QualType T) {
-  return CGM.getTypes().ConvertTypeForMem(T);
+llvm::Type *
+CodeGenFunction::ConvertTypeForMem(QualType T, bool ForBitField,
+                                   bool EnforceFixedLengthSVEAttribute) {
+  return CGM.getTypes().ConvertTypeForMem(T, ForBitField,
+                                          EnforceFixedLengthSVEAttribute);
 }
 
 llvm::Type *CodeGenFunction::ConvertType(QualType T) {
Index: clang/lib/CodeGen/CGExpr.cpp
===================================================================
--- clang/lib/CodeGen/CGExpr.cpp
+++ clang/lib/CodeGen/CGExpr.cpp
@@ -145,8 +145,11 @@
 
 Address CodeGenFunction::CreateMemTemp(QualType Ty, CharUnits Align,
                                        const Twine &Name, Address *Alloca) {
-  Address Result = CreateTempAlloca(ConvertTypeForMem(Ty), Align, Name,
-                                    /*ArraySize=*/nullptr, Alloca);
+  Address Result = CreateTempAlloca(
+      ConvertTypeForMem(Ty, /*ForBitField=*/false,
+                        /*EnforceFixedLengthSVEAttribute=*/false),
+      Align, Name,
+      /*ArraySize=*/nullptr, Alloca);
 
   if (Ty->isConstantMatrixType()) {
     auto *ArrayTy = cast<llvm::ArrayType>(Result.getType()->getElementType());
@@ -1699,6 +1702,13 @@
     }
   }
 
+  // If we're loading from a fixed-length address to a scalable vector, bitcast
+  // the pointer, e.g. bitcast [N x i8]* %addr.ptr to <vscale x 16 x i8>*
+  if (Ty->isVLST()) {
+    llvm::Type *VecTy = ConvertType(Ty);
+    Addr = Builder.CreateElementBitCast(Addr, VecTy, "cast.to.scalable");
+  }
+
   // Atomic operations have to be done on integral types.
   LValue AtomicLValue =
       LValue::MakeAddr(Addr, Ty, getContext(), BaseInfo, TBAAInfo);
@@ -1810,6 +1820,13 @@
     }
   }
 
+  // If we're storing a scalable vector to a fixed-length address, bitcast the
+  // pointer, e.g. bitcast [N x i8]* %addr.ptr to <vscale x 16 x i8>*
+  if (Ty->isVLST()) {
+    llvm::Type *VecTy = ConvertType(Ty);
+    Addr = Builder.CreateElementBitCast(Addr, VecTy, "cast.to.scalable");
+  }
+
   Value = EmitToMemory(Value, Ty);
 
   LValue AtomicLValue =
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to