re PR target/84945 (UBSAN: gcc/config/i386/i386.c:33312:22: runtime error: shift...
authorJakub Jelinek <jakub@redhat.com>
Tue, 20 Mar 2018 08:14:42 +0000 (09:14 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 20 Mar 2018 08:14:42 +0000 (09:14 +0100)
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
gcc/config/i386/i386.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr84945.c [new file with mode: 0644]
libgcc/ChangeLog
libgcc/config/i386/cpuinfo.c
libgcc/config/i386/cpuinfo.h

index 67162701d12eadd82f25de4bb3607268bb40cec0..f7829760592482237f84afddcde5991b53f0effd 100644 (file)
@@ -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.
index f45c756e289bc667cd77ae88a03515df3923c4a0..5b1e962dedb04b220c9cc717580b9bddba7619b8 100644 (file)
@@ -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));
index d141e99537dc6486d0545a00126fe65616bf396a..3058d9147ae65aec4809d86082dbf514e53bebdb 100644 (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>
 
        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 (file)
index 0000000..9599867
--- /dev/null
@@ -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;
+}
index 40407abef7c45367746fe52567b8ef99db1c4633..a3da8dca79343ce5d4c230ec9f76f5edc312b23d 100644 (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>
 
        * config/i386/cpuinfo.c (get_available_features): Add
index 8a6eef599112d0a9ac60c557f5a006ff1bb97290..4eb3f5cd9441e55668b3f2b1ce10902bc9cf8e6b 100644 (file)
@@ -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
index 371c8f60bb2a2dc9f5017131c215c4dffbeacad7..ab2260c38dfc09d8918b567064fa2933c93f9e6a 100644 (file)
@@ -124,3 +124,4 @@ extern struct __processor_model
   unsigned int __cpu_subtype;
   unsigned int __cpu_features[1];
 } __cpu_model;
+extern unsigned int __cpu_features2;