junparser created this revision.
junparser added reviewers: efriedma, bsmith, joechrisellis, c-rhodes, 
paulwalker-arm.
Herald added subscribers: psnobl, kristof.beyls, tschuett.
junparser requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

According to https://godbolt.org/z/q5rME1naY and acle, we found that
there are different SVE conversion behaviors between clang and gcc. It turns
out that llvm does not handle SVE predicates width properly.

This patch 1) checks SVE predicates width rightly with svbool_t type.

2. removes warning on svbool_t VLST <-> VLAT/GNUT conversion.
3. disables VLST <-> VLAT/GNUT conversion between SVE vectors and predicates

due to different width.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D106333

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/test/CodeGen/attr-arm-sve-vector-bits-codegen.c
  clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
  clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
  clang/test/SemaCXX/attr-arm-sve-vector-bits.cpp

Index: clang/test/SemaCXX/attr-arm-sve-vector-bits.cpp
===================================================================
--- clang/test/SemaCXX/attr-arm-sve-vector-bits.cpp
+++ clang/test/SemaCXX/attr-arm-sve-vector-bits.cpp
@@ -9,6 +9,10 @@
 typedef svint8_t fixed_int8_t __attribute__((arm_sve_vector_bits(N)));
 typedef int8_t gnu_int8_t __attribute__((vector_size(N / 8)));
 
+typedef __SVBool_t svbool_t;
+typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+typedef int8_t gnu_bool_t __attribute__((vector_size(N / 64)));
+
 template<typename T> struct S { T var; };
 
 S<fixed_int8_t> s;
@@ -24,3 +28,11 @@
 // Test implicit casts between GNU and VLS vectors
 fixed_int8_t to_fixed_int8_t__from_gnu_int8_t(gnu_int8_t x) { return x; }
 gnu_int8_t from_fixed_int8_t__to_gnu_int8_t(fixed_int8_t x) { return x; }
+
+// Test implicit casts between VLA and VLS perdicates
+svbool_t to_svbool_t(fixed_bool_t x) { return x; }
+fixed_bool_t from_svbool_t(svbool_t x) { return x; }
+
+// Test implicit casts between GNU and VLA predicates
+svbool_t to_svbool_t__from_gnu_bool_t(gnu_bool_t x) { return x; }
+gnu_bool_t from_svbool_t__to_gnu_bool_t(svbool_t x) { return x; }
Index: clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
===================================================================
--- clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
+++ clang/test/SemaCXX/aarch64-sve-lax-vector-conversions.cpp
@@ -2,22 +2,24 @@
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=integer -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-integer %s
 // RUN: %clang_cc1 -triple aarch64-none-linux-gnu -target-feature +sve -msve-vector-bits=512 -flax-vector-conversions=all -fallow-half-arguments-and-returns -ffreestanding -fsyntax-only -verify=lax-vector-all %s
 
-// lax-vector-all-no-diagnostics
-
 #include <arm_sve.h>
 
 #define N __ARM_FEATURE_SVE_BITS
 #define SVE_FIXED_ATTR __attribute__((arm_sve_vector_bits(N)))
 #define GNU_FIXED_ATTR __attribute__((vector_size(N / 8)))
+#define GNU_BOOL_FIXED_ATTR __attribute__((vector_size(N / 64)))
 
 typedef svfloat32_t sve_fixed_float32_t SVE_FIXED_ATTR;
 typedef svint32_t sve_fixed_int32_t SVE_FIXED_ATTR;
+typedef svbool_t sve_fixed_bool_t SVE_FIXED_ATTR;
 typedef float gnu_fixed_float32_t GNU_FIXED_ATTR;
 typedef int gnu_fixed_int32_t GNU_FIXED_ATTR;
+typedef int8_t gnu_fixed_bool_t GNU_BOOL_FIXED_ATTR;
 
 void sve_allowed_with_integer_lax_conversions() {
   sve_fixed_int32_t fi32;
   svint64_t si64;
+  svbool_t sb8;
 
   // The implicit cast here should fail if -flax-vector-conversions=none, but pass if
   // -flax-vector-conversions={integer,all}.
@@ -25,6 +27,15 @@
   // lax-vector-none-error@-1 {{assigning to 'sve_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
   si64 = fi32;
   // lax-vector-none-error@-1 {{assigning to 'svint64_t' (aka '__SVInt64_t') from incompatible type}}
+
+  fi32 = sb8;
+  // lax-vector-none-error@-1 {{assigning to 'sve_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  // lax-vector-integer-error@-2 {{assigning to 'sve_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  // lax-vector-all-error@-3 {{assigning to 'sve_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  sb8 = fi32;
+  // lax-vector-none-error@-1 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
+  // lax-vector-integer-error@-2 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
+  // lax-vector-all-error@-3 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
 }
 
 void sve_allowed_with_all_lax_conversions() {
@@ -44,6 +55,7 @@
 void gnu_allowed_with_integer_lax_conversions() {
   gnu_fixed_int32_t fi32;
   svint64_t si64;
+  svbool_t sb8;
 
   // The implicit cast here should fail if -flax-vector-conversions=none, but pass if
   // -flax-vector-conversions={integer,all}.
@@ -51,6 +63,15 @@
   // lax-vector-none-error@-1 {{assigning to 'gnu_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
   si64 = fi32;
   // lax-vector-none-error@-1 {{assigning to 'svint64_t' (aka '__SVInt64_t') from incompatible type}}
+
+  fi32 = sb8;
+  // lax-vector-none-error@-1 {{assigning to 'gnu_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  // lax-vector-integer-error@-2 {{assigning to 'gnu_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  // lax-vector-all-error@-3 {{assigning to 'gnu_fixed_int32_t' (vector of 16 'int' values) from incompatible type}}
+  sb8 = fi32;
+  // lax-vector-none-error@-1 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
+  // lax-vector-integer-error@-2 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
+  // lax-vector-all-error@-3 {{assigning to 'svbool_t' (aka '__SVBool_t') from incompatible type}}
 }
 
 void gnu_allowed_with_all_lax_conversions() {
Index: clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
===================================================================
--- clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
+++ clang/test/SemaCXX/aarch64-sve-explicit-casts-fixed-size.cpp
@@ -15,6 +15,7 @@
 typedef svfloat64_t fixed_float64_t FIXED_ATTR;
 typedef svint32_t fixed_int32_t FIXED_ATTR;
 typedef svint64_t fixed_int64_t FIXED_ATTR;
+typedef svbool_t fixed_bool_t FIXED_ATTR;
 
 // SVE VLSTs can be cast to SVE VLATs, regardless of lane size.
 // NOTE: the list below is NOT exhaustive for all SVE types.
@@ -47,3 +48,5 @@
 TESTCASE(fixed_int64_t, svfloat64_t)
 TESTCASE(fixed_int64_t, svint32_t)
 TESTCASE(fixed_int64_t, svint64_t)
+
+TESTCASE(fixed_bool_t, svbool_t)
Index: clang/test/CodeGen/attr-arm-sve-vector-bits-codegen.c
===================================================================
--- clang/test/CodeGen/attr-arm-sve-vector-bits-codegen.c
+++ clang/test/CodeGen/attr-arm-sve-vector-bits-codegen.c
@@ -7,6 +7,7 @@
 
 typedef svint32_t fixed_int32_t __attribute__((arm_sve_vector_bits(N)));
 typedef svbool_t fixed_bool_t __attribute__((arm_sve_vector_bits(N)));
+typedef uint8_t uint8_vec_t __attribute__((vector_size(N / 64)));
 
 fixed_bool_t global_pred;
 fixed_int32_t global_vec;
@@ -115,26 +116,26 @@
 // CHECK-NEXT:    [[RETVAL:%.*]] = alloca <16 x i32>, align 16
 // CHECK-NEXT:    [[PRED_ADDR:%.*]] = alloca <vscale x 16 x i1>, align 2
 // CHECK-NEXT:    [[VEC_ADDR:%.*]] = alloca <vscale x 4 x i32>, align 16
-// CHECK-NEXT:    [[XX:%.*]] = alloca <16 x i32>, align 16
-// CHECK-NEXT:    [[YY:%.*]] = alloca <16 x i32>, align 16
+// CHECK-NEXT:    [[XX:%.*]] = alloca <8 x i8>, align 8
+// CHECK-NEXT:    [[YY:%.*]] = alloca <8 x i8>, align 8
 // CHECK-NEXT:    [[PG:%.*]] = alloca <vscale x 16 x i1>, align 2
 // CHECK-NEXT:    [[SAVED_VALUE:%.*]] = alloca <8 x i8>, align 8
-// CHECK-NEXT:    [[SAVED_VALUE1:%.*]] = alloca <16 x i32>, align 64
+// CHECK-NEXT:    [[SAVED_VALUE1:%.*]] = alloca <8 x i8>, align 8
 // CHECK-NEXT:    store <vscale x 16 x i1> [[PRED:%.*]], <vscale x 16 x i1>* [[PRED_ADDR]], align 2
 // CHECK-NEXT:    store <vscale x 4 x i32> [[VEC:%.*]], <vscale x 4 x i32>* [[VEC_ADDR]], align 16
-// CHECK-NEXT:    store <16 x i32> <i32 1, i32 2, i32 3, i32 4, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, <16 x i32>* [[XX]], align 16
-// CHECK-NEXT:    store <16 x i32> <i32 2, i32 5, i32 4, i32 6, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0, i32 0>, <16 x i32>* [[YY]], align 16
+// CHECK-NEXT:    store <8 x i8> <i8 1, i8 2, i8 3, i8 4, i8 0, i8 0, i8 0, i8 0>, <8 x i8>* [[XX]], align 8
+// CHECK-NEXT:    store <8 x i8> <i8 2, i8 5, i8 4, i8 6, i8 0, i8 0, i8 0, i8 0>, <8 x i8>* [[YY]], align 8
 // CHECK-NEXT:    [[TMP0:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[PRED_ADDR]], align 2
 // CHECK-NEXT:    [[TMP1:%.*]] = load <8 x i8>, <8 x i8>* @global_pred, align 2
 // CHECK-NEXT:    store <8 x i8> [[TMP1]], <8 x i8>* [[SAVED_VALUE]], align 8
 // CHECK-NEXT:    [[CASTFIXEDSVE:%.*]] = bitcast <8 x i8>* [[SAVED_VALUE]] to <vscale x 16 x i1>*
 // CHECK-NEXT:    [[TMP2:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CASTFIXEDSVE]], align 8
-// CHECK-NEXT:    [[TMP3:%.*]] = load <16 x i32>, <16 x i32>* [[XX]], align 16
-// CHECK-NEXT:    [[TMP4:%.*]] = load <16 x i32>, <16 x i32>* [[YY]], align 16
-// CHECK-NEXT:    [[ADD:%.*]] = add <16 x i32> [[TMP3]], [[TMP4]]
-// CHECK-NEXT:    store <16 x i32> [[ADD]], <16 x i32>* [[SAVED_VALUE1]], align 64
-// CHECK-NEXT:    [[CASTFIXEDSVE2:%.*]] = bitcast <16 x i32>* [[SAVED_VALUE1]] to <vscale x 16 x i1>*
-// CHECK-NEXT:    [[TMP5:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CASTFIXEDSVE2]], align 64
+// CHECK-NEXT:    [[TMP3:%.*]] = load <8 x i8>, <8 x i8>* [[XX]], align 8
+// CHECK-NEXT:    [[TMP4:%.*]] = load <8 x i8>, <8 x i8>* [[YY]], align 8
+// CHECK-NEXT:    [[ADD:%.*]] = add <8 x i8> [[TMP3]], [[TMP4]]
+// CHECK-NEXT:    store <8 x i8> [[ADD]], <8 x i8>* [[SAVED_VALUE1]], align 8
+// CHECK-NEXT:    [[CASTFIXEDSVE2:%.*]] = bitcast <8 x i8>* [[SAVED_VALUE1]] to <vscale x 16 x i1>*
+// CHECK-NEXT:    [[TMP5:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[CASTFIXEDSVE2]], align 8
 // CHECK-NEXT:    [[TMP6:%.*]] = call <vscale x 16 x i1> @llvm.aarch64.sve.and.z.nxv16i1(<vscale x 16 x i1> [[TMP0]], <vscale x 16 x i1> [[TMP2]], <vscale x 16 x i1> [[TMP5]])
 // CHECK-NEXT:    store <vscale x 16 x i1> [[TMP6]], <vscale x 16 x i1>* [[PG]], align 2
 // CHECK-NEXT:    [[TMP7:%.*]] = load <vscale x 16 x i1>, <vscale x 16 x i1>* [[PG]], align 2
@@ -150,8 +151,8 @@
 // CHECK-NEXT:    ret <vscale x 4 x i32> [[CASTSCALABLESVE4]]
 //
 fixed_int32_t test_cast(svbool_t pred, svint32_t vec) {
-  fixed_int32_t xx = {1, 2, 3, 4};
-  fixed_int32_t yy = {2, 5, 4, 6};
+  uint8_vec_t xx = {1, 2, 3, 4};
+  uint8_vec_t yy = {2, 5, 4, 6};
   svbool_t pg = svand_z(pred, global_pred, xx + yy);
   return svadd_m(pg, global_vec, vec);
 }
Index: clang/lib/Sema/SemaChecking.cpp
===================================================================
--- clang/lib/Sema/SemaChecking.cpp
+++ clang/lib/Sema/SemaChecking.cpp
@@ -12563,7 +12563,11 @@
       if (SourceVectorKind == VectorType::SveFixedLengthDataVector ||
           SourceVectorKind == VectorType::SveFixedLengthPredicateVector ||
           (SourceVectorKind == VectorType::GenericVector &&
-           S.Context.getTypeSize(Source) == S.getLangOpts().ArmSveVectorBits))
+           S.Context.getTypeSize(Source) ==
+               (Target->getAs<BuiltinType>()->getKind() == BuiltinType::SveBool
+                    ? S.getLangOpts().ArmSveVectorBits /
+                          S.Context.getCharWidth()
+                    : S.getLangOpts().ArmSveVectorBits)))
         return;
     }
 
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -8687,7 +8687,10 @@
           return VT->getElementType().getCanonicalType() ==
                  FirstType->getSveEltType(*this);
         else if (VT->getVectorKind() == VectorType::GenericVector)
-          return getTypeSize(SecondType) == getLangOpts().ArmSveVectorBits &&
+          return getTypeSize(SecondType) ==
+                     (BT->getKind() == BuiltinType::SveBool
+                          ? getLangOpts().ArmSveVectorBits / getCharWidth()
+                          : getLangOpts().ArmSveVectorBits) &&
                  hasSameType(VT->getElementType(),
                              getBuiltinVectorTypeInfo(BT).ElementType);
       }
@@ -8706,7 +8709,8 @@
          "Expected SVE builtin type and vector type!");
 
   auto IsLaxCompatible = [this](QualType FirstType, QualType SecondType) {
-    if (!FirstType->getAs<BuiltinType>())
+    const auto *BT = FirstType->getAs<BuiltinType>();
+    if (!BT)
       return false;
 
     const auto *VecTy = SecondType->getAs<VectorType>();
@@ -8716,13 +8720,22 @@
       const LangOptions::LaxVectorConversionKind LVCKind =
           getLangOpts().getLaxVectorConversions();
 
+      // Can not convert between sve predicates and sve vectors because of
+      // different size.
+      if (BT->getKind() == BuiltinType::SveBool &&
+          VecTy->getVectorKind() == VectorType::SveFixedLengthDataVector)
+        return false;
+
       // If __ARM_FEATURE_SVE_BITS != N do not allow GNU vector lax conversion.
       // "Whenever __ARM_FEATURE_SVE_BITS==N, GNUT implicitly
       // converts to VLAT and VLAT implicitly converts to GNUT."
       // ACLE Spec Version 00bet6, 3.7.3.2. Behavior common to vectors and
       // predicates.
       if (VecTy->getVectorKind() == VectorType::GenericVector &&
-          getTypeSize(SecondType) != getLangOpts().ArmSveVectorBits)
+          getTypeSize(SecondType) !=
+              (BT->getKind() == BuiltinType::SveBool
+                   ? getLangOpts().ArmSveVectorBits / getCharWidth()
+                   : getLangOpts().ArmSveVectorBits))
         return false;
 
       // If -flax-vector-conversions=all is specified, the types are
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to