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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits