aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-03-20 09:14:42 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2018-03-20 09:14:42 +0100
commitae6dca8c651783208564001c56786f3abc762cf3 (patch)
tree434aa97e62aef6d534c2885c7c96fb7a40824a55
parent18c5bc3f908b51b44b1b35ece40052221122fe0c (diff)
downloadgcc-ae6dca8c651783208564001c56786f3abc762cf3.zip
gcc-ae6dca8c651783208564001c56786f3abc762cf3.tar.gz
gcc-ae6dca8c651783208564001c56786f3abc762cf3.tar.bz2
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
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/config/i386/i386.c24
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/i386/pr84945.c16
-rw-r--r--libgcc/ChangeLog10
-rw-r--r--libgcc/config/i386/cpuinfo.c88
-rw-r--r--libgcc/config/i386/cpuinfo.h1
7 files changed, 108 insertions, 41 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6716270..f782976 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,10 @@
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
* 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 f45c756..5b1e962 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 d141e99..3058d91 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
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 0000000..9599867
--- /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 40407ab..a3da8dc 100644
--- a/libgcc/ChangeLog
+++ b/libgcc/ChangeLog
@@ -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>
* config/i386/cpuinfo.c (get_available_features): Add
diff --git a/libgcc/config/i386/cpuinfo.c b/libgcc/config/i386/cpuinfo.c
index 8a6eef5..4eb3f5c 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 371c8f6..ab2260c 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;