diff --git a/clang/lib/Headers/altivec.h b/clang/lib/Headers/altivec.h --- a/clang/lib/Headers/altivec.h +++ b/clang/lib/Headers/altivec.h @@ -18191,13 +18191,13 @@ #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 */ @@ -18726,36 +18726,39 @@ 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 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3473,6 +3473,11 @@ 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 --- /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 + +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 --- a/clang/test/CodeGen/builtins-ppc-p10vector.c +++ b/clang/test/CodeGen/builtins-ppc-p10vector.c @@ -1370,10 +1370,12 @@ } 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, %{{.+}} @@ -1383,10 +1385,12 @@ } 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, %{{.+}} @@ -1396,10 +1400,12 @@ } 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, %{{.+}} @@ -1408,6 +1414,24 @@ 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