re PR target/84945 (UBSAN: gcc/config/i386/i386.c:33312:22: runtime error: shift exponent 32 is too large for 32-bit type 'int')

PR target/84945
	* config/i386/i386.c (fold_builtin_cpu): For features above 31
	use __cpu_features2 variable instead of __cpu_model.__cpu_features[0].
	Use 1U instead of 1.  Formatting fixes.

	* gcc.target/i386/pr84945.c: New test.

	* config/i386/cpuinfo.h (__cpu_features2): Declare.
	* config/i386/cpuinfo.c (__cpu_features2): New variable for
	ifndef SHARED only.
	(set_feature): Define.
	(get_available_features): Use set_feature macro.  Set __cpu_features2
	to the second word of features ifndef SHARED.

From-SVN: r258673
This commit is contained in:
Jakub Jelinek 2018-03-20 09:14:42 +01:00 committed by Jakub Jelinek
parent 18c5bc3f90
commit ae6dca8c65
7 changed files with 108 additions and 41 deletions

View File

@ -1,5 +1,10 @@
2018-03-20 Jakub Jelinek <jakub@redhat.com> 2018-03-20 Jakub Jelinek <jakub@redhat.com>
PR target/84945
* config/i386/i386.c (fold_builtin_cpu): For features above 31
use __cpu_features2 variable instead of __cpu_model.__cpu_features[0].
Use 1U instead of 1. Formatting fixes.
PR c/84953 PR c/84953
* builtins.c (fold_builtin_strpbrk): For strpbrk(x, "") use type * builtins.c (fold_builtin_strpbrk): For strpbrk(x, "") use type
instead of TREE_TYPE (s1) for the return value. instead of TREE_TYPE (s1) for the return value.

View File

@ -33265,8 +33265,8 @@ fold_builtin_cpu (tree fndecl, tree *args)
} }
/* Get the appropriate field in __cpu_model. */ /* Get the appropriate field in __cpu_model. */
ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var,
field, NULL_TREE); field, NULL_TREE);
/* Check the value. */ /* Check the value. */
final = build2 (EQ_EXPR, unsigned_type_node, ref, final = build2 (EQ_EXPR, unsigned_type_node, ref,
@ -33296,20 +33296,34 @@ fold_builtin_cpu (tree fndecl, tree *args)
return integer_zero_node; return integer_zero_node;
} }
if (isa_names_table[i].feature >= 32)
{
tree __cpu_features2_var = make_var_decl (unsigned_type_node,
"__cpu_features2");
varpool_node::add (__cpu_features2_var);
field_val = (1U << (isa_names_table[i].feature - 32));
/* Return __cpu_features2 & field_val */
final = build2 (BIT_AND_EXPR, unsigned_type_node,
__cpu_features2_var,
build_int_cstu (unsigned_type_node, field_val));
return build1 (CONVERT_EXPR, integer_type_node, final);
}
field = TYPE_FIELDS (__processor_model_type); field = TYPE_FIELDS (__processor_model_type);
/* Get the last field, which is __cpu_features. */ /* Get the last field, which is __cpu_features. */
while (DECL_CHAIN (field)) while (DECL_CHAIN (field))
field = DECL_CHAIN (field); field = DECL_CHAIN (field);
/* Get the appropriate field: __cpu_model.__cpu_features */ /* Get the appropriate field: __cpu_model.__cpu_features */
ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var,
field, NULL_TREE); field, NULL_TREE);
/* Access the 0th element of __cpu_features array. */ /* Access the 0th element of __cpu_features array. */
array_elt = build4 (ARRAY_REF, unsigned_type_node, ref, array_elt = build4 (ARRAY_REF, unsigned_type_node, ref,
integer_zero_node, NULL_TREE, NULL_TREE); integer_zero_node, NULL_TREE, NULL_TREE);
field_val = (1 << isa_names_table[i].feature); field_val = (1U << isa_names_table[i].feature);
/* Return __cpu_model.__cpu_features[0] & field_val */ /* Return __cpu_model.__cpu_features[0] & field_val */
final = build2 (BIT_AND_EXPR, unsigned_type_node, array_elt, final = build2 (BIT_AND_EXPR, unsigned_type_node, array_elt,
build_int_cstu (unsigned_type_node, field_val)); build_int_cstu (unsigned_type_node, field_val));

View File

@ -1,3 +1,8 @@
2018-03-20 Jakub Jelinek <jakub@redhat.com>
PR target/84945
* gcc.target/i386/pr84945.c: New test.
2018-03-20 Christophe Lyon <christophe.lyon@linaro.org> 2018-03-20 Christophe Lyon <christophe.lyon@linaro.org>
PR target/81647 PR target/81647

View File

@ -0,0 +1,16 @@
/* PR target/84945 */
/* { dg-do run } */
/* { dg-options "-O2" } */
int
main ()
{
/* AVX512_VNNI instructions are all EVEX encoded, so if
__builtin_cpu_supports says avx512vnni is available and avx512f is not,
this is a GCC bug. Ditto for AVX512_BITALG */
if (!__builtin_cpu_supports ("avx512f")
&& (__builtin_cpu_supports ("avx512vnni")
|| __builtin_cpu_supports ("avx512bitalg")))
__builtin_abort ();
return 0;
}

View File

@ -1,3 +1,13 @@
2018-03-20 Jakub Jelinek <jakub@redhat.com>
PR target/84945
* config/i386/cpuinfo.h (__cpu_features2): Declare.
* config/i386/cpuinfo.c (__cpu_features2): New variable for
ifndef SHARED only.
(set_feature): Define.
(get_available_features): Use set_feature macro. Set __cpu_features2
to the second word of features ifndef SHARED.
2018-03-15 Julia Koval <julia.koval@intel.com> 2018-03-15 Julia Koval <julia.koval@intel.com>
* config/i386/cpuinfo.c (get_available_features): Add * config/i386/cpuinfo.c (get_available_features): Add

View File

@ -39,6 +39,13 @@ int __cpu_indicator_init (void)
struct __processor_model __cpu_model = { }; struct __processor_model __cpu_model = { };
#ifndef SHARED
/* We want to move away from __cpu_model in libgcc_s.so.1 and the
size of __cpu_model is part of ABI. So, new features that don't
fit into __cpu_model.__cpu_features[0] go into extra variables
in libgcc.a only, preferrably hidden. */
unsigned int __cpu_features2;
#endif
/* Get the specific type of AMD CPU. */ /* Get the specific type of AMD CPU. */
@ -231,78 +238,82 @@ get_available_features (unsigned int ecx, unsigned int edx,
unsigned int ext_level; unsigned int ext_level;
unsigned int features = 0; unsigned int features = 0;
unsigned int features2 = 0;
#define set_feature(f) \
if (f < 32) features |= (1U << f); else features2 |= (1U << (f - 32))
if (edx & bit_CMOV) if (edx & bit_CMOV)
features |= (1 << FEATURE_CMOV); set_feature (FEATURE_CMOV);
if (edx & bit_MMX) if (edx & bit_MMX)
features |= (1 << FEATURE_MMX); set_feature (FEATURE_MMX);
if (edx & bit_SSE) if (edx & bit_SSE)
features |= (1 << FEATURE_SSE); set_feature (FEATURE_SSE);
if (edx & bit_SSE2) if (edx & bit_SSE2)
features |= (1 << FEATURE_SSE2); set_feature (FEATURE_SSE2);
if (ecx & bit_POPCNT) if (ecx & bit_POPCNT)
features |= (1 << FEATURE_POPCNT); set_feature (FEATURE_POPCNT);
if (ecx & bit_AES) if (ecx & bit_AES)
features |= (1 << FEATURE_AES); set_feature (FEATURE_AES);
if (ecx & bit_PCLMUL) if (ecx & bit_PCLMUL)
features |= (1 << FEATURE_PCLMUL); set_feature (FEATURE_PCLMUL);
if (ecx & bit_SSE3) if (ecx & bit_SSE3)
features |= (1 << FEATURE_SSE3); set_feature (FEATURE_SSE3);
if (ecx & bit_SSSE3) if (ecx & bit_SSSE3)
features |= (1 << FEATURE_SSSE3); set_feature (FEATURE_SSSE3);
if (ecx & bit_SSE4_1) if (ecx & bit_SSE4_1)
features |= (1 << FEATURE_SSE4_1); set_feature (FEATURE_SSE4_1);
if (ecx & bit_SSE4_2) if (ecx & bit_SSE4_2)
features |= (1 << FEATURE_SSE4_2); set_feature (FEATURE_SSE4_2);
if (ecx & bit_AVX) if (ecx & bit_AVX)
features |= (1 << FEATURE_AVX); set_feature (FEATURE_AVX);
if (ecx & bit_FMA) if (ecx & bit_FMA)
features |= (1 << FEATURE_FMA); set_feature (FEATURE_FMA);
/* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */
if (max_cpuid_level >= 7) if (max_cpuid_level >= 7)
{ {
__cpuid_count (7, 0, eax, ebx, ecx, edx); __cpuid_count (7, 0, eax, ebx, ecx, edx);
if (ebx & bit_BMI) if (ebx & bit_BMI)
features |= (1 << FEATURE_BMI); set_feature (FEATURE_BMI);
if (ebx & bit_AVX2) if (ebx & bit_AVX2)
features |= (1 << FEATURE_AVX2); set_feature (FEATURE_AVX2);
if (ebx & bit_BMI2) if (ebx & bit_BMI2)
features |= (1 << FEATURE_BMI2); set_feature (FEATURE_BMI2);
if (ebx & bit_AVX512F) if (ebx & bit_AVX512F)
features |= (1 << FEATURE_AVX512F); set_feature (FEATURE_AVX512F);
if (ebx & bit_AVX512VL) if (ebx & bit_AVX512VL)
features |= (1 << FEATURE_AVX512VL); set_feature (FEATURE_AVX512VL);
if (ebx & bit_AVX512BW) if (ebx & bit_AVX512BW)
features |= (1 << FEATURE_AVX512BW); set_feature (FEATURE_AVX512BW);
if (ebx & bit_AVX512DQ) if (ebx & bit_AVX512DQ)
features |= (1 << FEATURE_AVX512DQ); set_feature (FEATURE_AVX512DQ);
if (ebx & bit_AVX512CD) if (ebx & bit_AVX512CD)
features |= (1 << FEATURE_AVX512CD); set_feature (FEATURE_AVX512CD);
if (ebx & bit_AVX512PF) if (ebx & bit_AVX512PF)
features |= (1 << FEATURE_AVX512PF); set_feature (FEATURE_AVX512PF);
if (ebx & bit_AVX512ER) if (ebx & bit_AVX512ER)
features |= (1 << FEATURE_AVX512ER); set_feature (FEATURE_AVX512ER);
if (ebx & bit_AVX512IFMA) if (ebx & bit_AVX512IFMA)
features |= (1 << FEATURE_AVX512IFMA); set_feature (FEATURE_AVX512IFMA);
if (ecx & bit_AVX512VBMI) if (ecx & bit_AVX512VBMI)
features |= (1 << FEATURE_AVX512VBMI); set_feature (FEATURE_AVX512VBMI);
if (ecx & bit_AVX512VBMI2) if (ecx & bit_AVX512VBMI2)
features |= (1 << FEATURE_AVX512VBMI2); set_feature (FEATURE_AVX512VBMI2);
if (ecx & bit_GFNI) if (ecx & bit_GFNI)
features |= (1 << FEATURE_GFNI); set_feature (FEATURE_GFNI);
if (ecx & bit_VPCLMULQDQ) if (ecx & bit_VPCLMULQDQ)
features |= (1 << FEATURE_VPCLMULQDQ); set_feature (FEATURE_VPCLMULQDQ);
if (ecx & bit_AVX512VNNI) if (ecx & bit_AVX512VNNI)
features |= (1 << FEATURE_AVX512VNNI); set_feature (FEATURE_AVX512VNNI);
if (ecx & bit_AVX512BITALG) if (ecx & bit_AVX512BITALG)
features |= (1 << FEATURE_AVX512BITALG); set_feature (FEATURE_AVX512BITALG);
if (ecx & bit_AVX512VPOPCNTDQ) if (ecx & bit_AVX512VPOPCNTDQ)
features |= (1 << FEATURE_AVX512VPOPCNTDQ); set_feature (FEATURE_AVX512VPOPCNTDQ);
if (edx & bit_AVX5124VNNIW) if (edx & bit_AVX5124VNNIW)
features |= (1 << FEATURE_AVX5124VNNIW); set_feature (FEATURE_AVX5124VNNIW);
if (edx & bit_AVX5124FMAPS) if (edx & bit_AVX5124FMAPS)
features |= (1 << FEATURE_AVX5124FMAPS); set_feature (FEATURE_AVX5124FMAPS);
} }
/* Check cpuid level of extended features. */ /* Check cpuid level of extended features. */
@ -313,14 +324,19 @@ get_available_features (unsigned int ecx, unsigned int edx,
__cpuid (0x80000001, eax, ebx, ecx, edx); __cpuid (0x80000001, eax, ebx, ecx, edx);
if (ecx & bit_SSE4a) if (ecx & bit_SSE4a)
features |= (1 << FEATURE_SSE4_A); set_feature (FEATURE_SSE4_A);
if (ecx & bit_FMA4) if (ecx & bit_FMA4)
features |= (1 << FEATURE_FMA4); set_feature (FEATURE_FMA4);
if (ecx & bit_XOP) if (ecx & bit_XOP)
features |= (1 << FEATURE_XOP); set_feature (FEATURE_XOP);
} }
__cpu_model.__cpu_features[0] = features; __cpu_model.__cpu_features[0] = features;
#ifndef SHARED
__cpu_features2 = features2;
#else
(void) features2;
#endif
} }
/* A constructor function that is sets __cpu_model and __cpu_features with /* A constructor function that is sets __cpu_model and __cpu_features with

View File

@ -124,3 +124,4 @@ extern struct __processor_model
unsigned int __cpu_subtype; unsigned int __cpu_subtype;
unsigned int __cpu_features[1]; unsigned int __cpu_features[1];
} __cpu_model; } __cpu_model;
extern unsigned int __cpu_features2;