From ae6dca8c651783208564001c56786f3abc762cf3 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 20 Mar 2018 09:14:42 +0100 Subject: [PATCH] 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 --- gcc/ChangeLog | 5 ++ gcc/config/i386/i386.c | 24 +++++-- gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.target/i386/pr84945.c | 16 +++++ libgcc/ChangeLog | 10 +++ libgcc/config/i386/cpuinfo.c | 88 +++++++++++++++---------- libgcc/config/i386/cpuinfo.h | 1 + 7 files changed, 108 insertions(+), 41 deletions(-) create mode 100644 gcc/testsuite/gcc.target/i386/pr84945.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 67162701d12..f7829760592 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,10 @@ 2018-03-20 Jakub Jelinek + 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 * builtins.c (fold_builtin_strpbrk): For strpbrk(x, "") use type instead of TREE_TYPE (s1) for the return value. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index f45c756e289..5b1e962dedb 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -33265,8 +33265,8 @@ fold_builtin_cpu (tree fndecl, tree *args) } /* Get the appropriate field in __cpu_model. */ - ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, - field, NULL_TREE); + ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, + field, NULL_TREE); /* Check the value. */ final = build2 (EQ_EXPR, unsigned_type_node, ref, @@ -33296,20 +33296,34 @@ fold_builtin_cpu (tree fndecl, tree *args) 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); /* Get the last field, which is __cpu_features. */ while (DECL_CHAIN (field)) field = DECL_CHAIN (field); /* Get the appropriate field: __cpu_model.__cpu_features */ - ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, - field, NULL_TREE); + ref = build3 (COMPONENT_REF, TREE_TYPE (field), __cpu_model_var, + field, NULL_TREE); /* Access the 0th element of __cpu_features array. */ array_elt = build4 (ARRAY_REF, unsigned_type_node, ref, 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 */ final = build2 (BIT_AND_EXPR, unsigned_type_node, array_elt, build_int_cstu (unsigned_type_node, field_val)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d141e99537d..3058d9147ae 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-03-20 Jakub Jelinek + + PR target/84945 + * gcc.target/i386/pr84945.c: New test. + 2018-03-20 Christophe Lyon PR target/81647 diff --git a/gcc/testsuite/gcc.target/i386/pr84945.c b/gcc/testsuite/gcc.target/i386/pr84945.c new file mode 100644 index 00000000000..95998678860 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr84945.c @@ -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; +} diff --git a/libgcc/ChangeLog b/libgcc/ChangeLog index 40407abef7c..a3da8dca793 100644 --- a/libgcc/ChangeLog +++ b/libgcc/ChangeLog @@ -1,3 +1,13 @@ +2018-03-20 Jakub Jelinek + + 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 * config/i386/cpuinfo.c (get_available_features): Add diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c index 8a6eef59911..4eb3f5cd944 100644 --- a/libgcc/config/i386/cpuinfo.c +++ b/libgcc/config/i386/cpuinfo.c @@ -39,6 +39,13 @@ int __cpu_indicator_init (void) 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. */ @@ -231,78 +238,82 @@ get_available_features (unsigned int ecx, unsigned int edx, unsigned int ext_level; 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) - features |= (1 << FEATURE_CMOV); + set_feature (FEATURE_CMOV); if (edx & bit_MMX) - features |= (1 << FEATURE_MMX); + set_feature (FEATURE_MMX); if (edx & bit_SSE) - features |= (1 << FEATURE_SSE); + set_feature (FEATURE_SSE); if (edx & bit_SSE2) - features |= (1 << FEATURE_SSE2); + set_feature (FEATURE_SSE2); if (ecx & bit_POPCNT) - features |= (1 << FEATURE_POPCNT); + set_feature (FEATURE_POPCNT); if (ecx & bit_AES) - features |= (1 << FEATURE_AES); + set_feature (FEATURE_AES); if (ecx & bit_PCLMUL) - features |= (1 << FEATURE_PCLMUL); + set_feature (FEATURE_PCLMUL); if (ecx & bit_SSE3) - features |= (1 << FEATURE_SSE3); + set_feature (FEATURE_SSE3); if (ecx & bit_SSSE3) - features |= (1 << FEATURE_SSSE3); + set_feature (FEATURE_SSSE3); if (ecx & bit_SSE4_1) - features |= (1 << FEATURE_SSE4_1); + set_feature (FEATURE_SSE4_1); if (ecx & bit_SSE4_2) - features |= (1 << FEATURE_SSE4_2); + set_feature (FEATURE_SSE4_2); if (ecx & bit_AVX) - features |= (1 << FEATURE_AVX); + set_feature (FEATURE_AVX); if (ecx & bit_FMA) - features |= (1 << FEATURE_FMA); + set_feature (FEATURE_FMA); /* Get Advanced Features at level 7 (eax = 7, ecx = 0). */ if (max_cpuid_level >= 7) { __cpuid_count (7, 0, eax, ebx, ecx, edx); if (ebx & bit_BMI) - features |= (1 << FEATURE_BMI); + set_feature (FEATURE_BMI); if (ebx & bit_AVX2) - features |= (1 << FEATURE_AVX2); + set_feature (FEATURE_AVX2); if (ebx & bit_BMI2) - features |= (1 << FEATURE_BMI2); + set_feature (FEATURE_BMI2); if (ebx & bit_AVX512F) - features |= (1 << FEATURE_AVX512F); + set_feature (FEATURE_AVX512F); if (ebx & bit_AVX512VL) - features |= (1 << FEATURE_AVX512VL); + set_feature (FEATURE_AVX512VL); if (ebx & bit_AVX512BW) - features |= (1 << FEATURE_AVX512BW); + set_feature (FEATURE_AVX512BW); if (ebx & bit_AVX512DQ) - features |= (1 << FEATURE_AVX512DQ); + set_feature (FEATURE_AVX512DQ); if (ebx & bit_AVX512CD) - features |= (1 << FEATURE_AVX512CD); + set_feature (FEATURE_AVX512CD); if (ebx & bit_AVX512PF) - features |= (1 << FEATURE_AVX512PF); + set_feature (FEATURE_AVX512PF); if (ebx & bit_AVX512ER) - features |= (1 << FEATURE_AVX512ER); + set_feature (FEATURE_AVX512ER); if (ebx & bit_AVX512IFMA) - features |= (1 << FEATURE_AVX512IFMA); + set_feature (FEATURE_AVX512IFMA); if (ecx & bit_AVX512VBMI) - features |= (1 << FEATURE_AVX512VBMI); + set_feature (FEATURE_AVX512VBMI); if (ecx & bit_AVX512VBMI2) - features |= (1 << FEATURE_AVX512VBMI2); + set_feature (FEATURE_AVX512VBMI2); if (ecx & bit_GFNI) - features |= (1 << FEATURE_GFNI); + set_feature (FEATURE_GFNI); if (ecx & bit_VPCLMULQDQ) - features |= (1 << FEATURE_VPCLMULQDQ); + set_feature (FEATURE_VPCLMULQDQ); if (ecx & bit_AVX512VNNI) - features |= (1 << FEATURE_AVX512VNNI); + set_feature (FEATURE_AVX512VNNI); if (ecx & bit_AVX512BITALG) - features |= (1 << FEATURE_AVX512BITALG); + set_feature (FEATURE_AVX512BITALG); if (ecx & bit_AVX512VPOPCNTDQ) - features |= (1 << FEATURE_AVX512VPOPCNTDQ); + set_feature (FEATURE_AVX512VPOPCNTDQ); if (edx & bit_AVX5124VNNIW) - features |= (1 << FEATURE_AVX5124VNNIW); + set_feature (FEATURE_AVX5124VNNIW); if (edx & bit_AVX5124FMAPS) - features |= (1 << FEATURE_AVX5124FMAPS); + set_feature (FEATURE_AVX5124FMAPS); } /* 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); if (ecx & bit_SSE4a) - features |= (1 << FEATURE_SSE4_A); + set_feature (FEATURE_SSE4_A); if (ecx & bit_FMA4) - features |= (1 << FEATURE_FMA4); + set_feature (FEATURE_FMA4); if (ecx & bit_XOP) - features |= (1 << FEATURE_XOP); + set_feature (FEATURE_XOP); } __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 diff --git a/libgcc/config/i386/cpuinfo.h b/libgcc/config/i386/cpuinfo.h index 371c8f60bb2..ab2260c38df 100644 --- a/libgcc/config/i386/cpuinfo.h +++ b/libgcc/config/i386/cpuinfo.h @@ -124,3 +124,4 @@ extern struct __processor_model unsigned int __cpu_subtype; unsigned int __cpu_features[1]; } __cpu_model; +extern unsigned int __cpu_features2; -- 2.30.2