[clang] f9912fe - [PowerPC] Add range checks for P10 Vector Builtins

Quinn Pham via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 23 09:05:55 PDT 2021


Author: Quinn Pham
Date: 2021-09-23T11:05:49-05:00
New Revision: f9912fe4eac91f27965c22d015b3109c5158d050

URL: https://github.com/llvm/llvm-project/commit/f9912fe4eac91f27965c22d015b3109c5158d050
DIFF: https://github.com/llvm/llvm-project/commit/f9912fe4eac91f27965c22d015b3109c5158d050.diff

LOG: [PowerPC] Add range checks for P10 Vector Builtins

This patch adds range checking for some Power10 altivec builtins and
changes the signature of a builtin to match documentation. For `vec_cntm`,
range checking is done via SemaChecking. For `vec_splati_ins`, the second
argument is masked to extract the 0th bit so that we always receive either a `0`
or a `1`.

Reviewed By: lei, amyk

Differential Revision: https://reviews.llvm.org/D109710

Added: 
    clang/test/CodeGen/builtins-ppc-p10vector-error.c

Modified: 
    clang/lib/Headers/altivec.h
    clang/lib/Sema/SemaChecking.cpp
    clang/test/CodeGen/builtins-ppc-p10vector.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h
index 239c93d5b115c..6cfe9815228fa 100644
--- a/clang/lib/Headers/altivec.h
+++ b/clang/lib/Headers/altivec.h
@@ -18221,13 +18221,13 @@ vec_expandm(vector unsigned __int128 __a) {
 
 #define vec_cntm(__a, __mp)                                                    \
   _Generic((__a), vector unsigned char                                         \
-           : __builtin_altivec_vcntmbb((__a), (unsigned int)(__mp)),           \
+           : __builtin_altivec_vcntmbb((__a), (unsigned char)(__mp)),          \
              vector unsigned short                                             \
-           : __builtin_altivec_vcntmbh((__a), (unsigned int)(__mp)),           \
+           : __builtin_altivec_vcntmbh((__a), (unsigned char)(__mp)),          \
              vector unsigned int                                               \
-           : __builtin_altivec_vcntmbw((__a), (unsigned int)(__mp)),           \
+           : __builtin_altivec_vcntmbw((__a), (unsigned char)(__mp)),          \
              vector unsigned long long                                         \
-           : __builtin_altivec_vcntmbd((__a), (unsigned int)(__mp)))
+           : __builtin_altivec_vcntmbd((__a), (unsigned char)(__mp)))
 
 /* vec_gen[b|h|w|d|q]m */
 
@@ -18756,36 +18756,39 @@ static __inline__ vector double __ATTRS_o_ai vec_splatid(const float __a) {
 
 static __inline__ vector signed int __ATTRS_o_ai vec_splati_ins(
     vector signed int __a, const unsigned int __b, const signed int __c) {
+  const unsigned int __d = __b & 0x01;
 #ifdef __LITTLE_ENDIAN__
-  __a[1 - __b] = __c;
-  __a[3 - __b] = __c;
+  __a[1 - __d] = __c;
+  __a[3 - __d] = __c;
 #else
-  __a[__b] = __c;
-  __a[2 + __b] = __c;
+  __a[__d] = __c;
+  __a[2 + __d] = __c;
 #endif
   return __a;
 }
 
 static __inline__ vector unsigned int __ATTRS_o_ai vec_splati_ins(
     vector unsigned int __a, const unsigned int __b, const unsigned int __c) {
+  const unsigned int __d = __b & 0x01;
 #ifdef __LITTLE_ENDIAN__
-  __a[1 - __b] = __c;
-  __a[3 - __b] = __c;
+  __a[1 - __d] = __c;
+  __a[3 - __d] = __c;
 #else
-  __a[__b] = __c;
-  __a[2 + __b] = __c;
+  __a[__d] = __c;
+  __a[2 + __d] = __c;
 #endif
   return __a;
 }
 
 static __inline__ vector float __ATTRS_o_ai
 vec_splati_ins(vector float __a, const unsigned int __b, const float __c) {
+  const unsigned int __d = __b & 0x01;
 #ifdef __LITTLE_ENDIAN__
-  __a[1 - __b] = __c;
-  __a[3 - __b] = __c;
+  __a[1 - __d] = __c;
+  __a[3 - __d] = __c;
 #else
-  __a[__b] = __c;
-  __a[2 + __b] = __c;
+  __a[__d] = __c;
+  __a[2 + __d] = __c;
 #endif
   return __a;
 }

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 9862306325322..5cc968c133ce3 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -3473,6 +3473,11 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
     return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions",
                             diag::err_ppc_builtin_only_on_arch, "8") ||
            SemaBuiltinConstantArgRange(TheCall, 1, 1, 16);
+  case PPC::BI__builtin_altivec_vcntmbb:
+  case PPC::BI__builtin_altivec_vcntmbh:
+  case PPC::BI__builtin_altivec_vcntmbw:
+  case PPC::BI__builtin_altivec_vcntmbd:
+    return SemaBuiltinConstantArgRange(TheCall, 1, 0, 1);
 #define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
   case PPC::BI__builtin_##Name: \
     return SemaBuiltinPPCMMACall(TheCall, Types);

diff  --git a/clang/test/CodeGen/builtins-ppc-p10vector-error.c b/clang/test/CodeGen/builtins-ppc-p10vector-error.c
new file mode 100644
index 0000000000000..e509c5a82c5b0
--- /dev/null
+++ b/clang/test/CodeGen/builtins-ppc-p10vector-error.c
@@ -0,0 +1,32 @@
+// REQUIRES: powerpc-registered-target
+// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -target-cpu pwr10 \
+// RUN:   -fsyntax-only -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -target-cpu pwr10 \
+// RUN:   -fsyntax-only -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc64-unknown-aix -target-cpu pwr10 \
+// RUN:   -fsyntax-only -Wall -Werror -verify %s
+// RUN: %clang_cc1 -triple powerpc-unknown-aix -target-cpu pwr10 \
+// RUN:   -fsyntax-only -Wall -Werror -verify %s
+
+#include <altivec.h>
+
+vector unsigned char vuca;
+vector unsigned short vusa;
+vector unsigned int vuia;
+vector unsigned long long vulla;
+
+unsigned long long test_vec_cntm_uc(void) {
+  return vec_cntm(vuca, -1); // expected-error 1+ {{argument value 255 is outside the valid range [0, 1]}}
+}
+
+unsigned long long test_vec_cntm_us(void) {
+  return vec_cntm(vusa, -1); // expected-error 1+ {{argument value 255 is outside the valid range [0, 1]}}
+}
+
+unsigned long long test_vec_cntm_ui(void) {
+  return vec_cntm(vuia, 2); // expected-error 1+ {{argument value 2 is outside the valid range [0, 1]}}
+}
+
+unsigned long long test_vec_cntm_ull(void) {
+  return vec_cntm(vulla, 2); // expected-error 1+ {{argument value 2 is outside the valid range [0, 1]}}
+}

diff  --git a/clang/test/CodeGen/builtins-ppc-p10vector.c b/clang/test/CodeGen/builtins-ppc-p10vector.c
index 8816ae8028ebf..48a95bf4ab876 100644
--- a/clang/test/CodeGen/builtins-ppc-p10vector.c
+++ b/clang/test/CodeGen/builtins-ppc-p10vector.c
@@ -1371,10 +1371,12 @@ vector double test_vec_vec_splatid(void) {
 }
 
 vector signed int test_vec_vec_splati_ins_si(void) {
+  // CHECK-BE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 %{{.+}}
   // CHECK-BE:  [[T1:%.+]] = add i32 2, %{{.+}}
   // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
   // CHECK-BE: ret <4 x i32>
+  // CHECK-LE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-LE:  [[T1:%.+]] = sub i32 1, %{{.+}}
   // CHECK-LE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
   // CHECK-LE:  [[T2:%.+]] = sub i32 3, %{{.+}}
@@ -1384,10 +1386,12 @@ vector signed int test_vec_vec_splati_ins_si(void) {
 }
 
 vector unsigned int test_vec_vec_splati_ins_ui(void) {
+  // CHECK-BE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 %{{.+}}
   // CHECK-BE:  [[T1:%.+]] = add i32 2, %{{.+}}
   // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
   // CHECK-BE: ret <4 x i32>
+  // CHECK-LE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-LE:  [[T1:%.+]] = sub i32 1, %{{.+}}
   // CHECK-LE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
   // CHECK-LE:  [[T2:%.+]] = sub i32 3, %{{.+}}
@@ -1397,10 +1401,12 @@ vector unsigned int test_vec_vec_splati_ins_ui(void) {
 }
 
 vector float test_vec_vec_splati_ins_f(void) {
+  // CHECK-BE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-BE: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 %{{.+}}
   // CHECK-BE:  [[T1:%.+]] = add i32 2, %{{.+}}
   // CHECK-BE: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 [[T1]]
   // CHECK-BE: ret <4 x float>
+  // CHECK-LE: [[T0:%.+]] = and i32 %{{.+}}, 1
   // CHECK-LE:  [[T1:%.+]] = sub i32 1, %{{.+}}
   // CHECK-LE: insertelement <4 x float> %{{.+}}, float %{{.+}}, i32 [[T1]]
   // CHECK-LE:  [[T2:%.+]] = sub i32 3, %{{.+}}
@@ -1409,6 +1415,24 @@ vector float test_vec_vec_splati_ins_f(void) {
   return vec_splati_ins(vfa, 0, 1.0f);
 }
 
+// In this test case, the second argument of vec_splati_ins is outside of the 
+// expected range [0,1]. A mask of 0x01 is applied to obtain an in-range value 
+// for the second argument.
+vector signed int test_vec_vec_splati_ins_range(void) {
+  // CHECK-BE: [[T0:%.+]] = and i32 %{{.+}}, 1
+  // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 %{{.+}}
+  // CHECK-BE:  [[T1:%.+]] = add i32 2, %{{.+}}
+  // CHECK-BE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
+  // CHECK-BE: ret <4 x i32>
+  // CHECK-LE: [[T0:%.+]] = and i32 %{{.+}}, 1
+  // CHECK-LE:  [[T1:%.+]] = sub i32 1, %{{.+}}
+  // CHECK-LE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T1]]
+  // CHECK-LE:  [[T2:%.+]] = sub i32 3, %{{.+}}
+  // CHECK-LE: insertelement <4 x i32> %{{.+}}, i32 %{{.+}}, i32 [[T2]]
+  // CHECK-LE: ret <4 x i32>
+  return vec_splati_ins(vsia, 2, -17);
+}
+
 void test_vec_xst_trunc_sc(vector signed __int128 __a, signed long long __b,
                            signed char *__c) {
   // CHECK: store i8 %{{.+}}, i8* %{{.+}}, align 1


        


More information about the cfe-commits mailing list