re PR tree-optimization/91351 (-fstrict-enums generates incorrect code)
authorJakub Jelinek <jakub@redhat.com>
Thu, 29 Aug 2019 09:20:54 +0000 (11:20 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Thu, 29 Aug 2019 09:20:54 +0000 (11:20 +0200)
PR tree-optimization/91351
* tree-cfg.c (generate_range_test): Use range_check_type instead of
unsigned_type_for.
* tree-cfgcleanup.c (convert_single_case_switch): Punt if
range_check_type returns NULL.
* tree-switch-conversion.c (switch_conversion::build_one_array):
Use range_check_type instead of unsigned_type_for, don't perform
linear opt if it returns NULL.
(bit_test_cluster::find_bit_tests): Formatting fix.
(bit_test_cluster::emit): Use range_check_type instead of
unsigned_type_for.
(switch_decision_tree::try_switch_expansion): Punt if range_check_type
returns NULL.

* g++.dg/opt/pr91351.C: New test.

From-SVN: r275026

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/pr91351.C [new file with mode: 0644]
gcc/tree-cfg.c
gcc/tree-cfgcleanup.c
gcc/tree-switch-conversion.c

index 49ab435..6342c4a 100644 (file)
@@ -1,3 +1,19 @@
+2019-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/91351
+       * tree-cfg.c (generate_range_test): Use range_check_type instead of
+       unsigned_type_for.
+       * tree-cfgcleanup.c (convert_single_case_switch): Punt if
+       range_check_type returns NULL.
+       * tree-switch-conversion.c (switch_conversion::build_one_array):
+       Use range_check_type instead of unsigned_type_for, don't perform
+       linear opt if it returns NULL.
+       (bit_test_cluster::find_bit_tests): Formatting fix.
+       (bit_test_cluster::emit): Use range_check_type instead of
+       unsigned_type_for.
+       (switch_decision_tree::try_switch_expansion): Punt if range_check_type
+       returns NULL.
+
 2019-08-29  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/91568
index a051dda..652759a 100644 (file)
@@ -1,3 +1,8 @@
+2019-08-29  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/91351
+       * g++.dg/opt/pr91351.C: New test.
+
 2019-08-29  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * g++.dg/spellcheck-typenames.C: Adjust expected locations.
diff --git a/gcc/testsuite/g++.dg/opt/pr91351.C b/gcc/testsuite/g++.dg/opt/pr91351.C
new file mode 100644 (file)
index 0000000..f793a2f
--- /dev/null
@@ -0,0 +1,38 @@
+// PR tree-optimization/91351
+// { dg-do run }
+// { dg-options "-O2 -fstrict-enums" }
+
+enum E { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11, e12,
+        e13, e14, e15, e16, e17, e18, e19, e20, e21, e22, e23, e24, e25 };
+
+__attribute__((noipa)) void
+foo ()
+{
+  __builtin_abort ();
+}
+
+__attribute__((noipa)) void
+bar ()
+{
+}
+
+__attribute__((noipa)) void
+baz (E e)
+{
+  switch (e)
+    {
+    case e11:
+    case e12:
+    case e13: foo (); break;
+    case e24: break;
+    case e14:
+    case e15: break;
+    default: bar (); break;
+    }
+}
+
+int
+main ()
+{
+  baz (e3);
+}
index 2648663..b75fdb2 100644 (file)
@@ -9221,7 +9221,7 @@ generate_range_test (basic_block bb, tree index, tree low, tree high,
                     tree *lhs, tree *rhs)
 {
   tree type = TREE_TYPE (index);
-  tree utype = unsigned_type_for (type);
+  tree utype = range_check_type (type);
 
   low = fold_convert (utype, low);
   high = fold_convert (utype, high);
index 183b491..4bac38a 100644 (file)
@@ -101,6 +101,8 @@ convert_single_case_switch (gswitch *swtch, gimple_stmt_iterator &gsi)
   if (high)
     {
       tree lhs, rhs;
+      if (range_check_type (TREE_TYPE (index)) == NULL_TREE)
+       return false;
       generate_range_test (bb, index, low, high, &lhs, &rhs);
       cond = gimple_build_cond (LE_EXPR, lhs, rhs, NULL_TREE, NULL_TREE);
     }
index 776db77..e8692a7 100644 (file)
@@ -605,7 +605,9 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
   vec<constructor_elt, va_gc> *constructor = m_constructors[num];
   wide_int coeff_a, coeff_b;
   bool linear_p = contains_linear_function_p (constructor, &coeff_a, &coeff_b);
-  if (linear_p)
+  tree type;
+  if (linear_p
+      && (type = range_check_type (TREE_TYPE ((*constructor)[0].value))))
     {
       if (dump_file && coeff_a.to_uhwi () > 0)
        fprintf (dump_file, "Linear transformation with A = %" PRId64
@@ -613,13 +615,12 @@ switch_conversion::build_one_array (int num, tree arr_index_type,
                 coeff_b.to_shwi ());
 
       /* We must use type of constructor values.  */
-      tree t = unsigned_type_for (TREE_TYPE ((*constructor)[0].value));
       gimple_seq seq = NULL;
-      tree tmp = gimple_convert (&seq, t, m_index_expr);
-      tree tmp2 = gimple_build (&seq, MULT_EXPR, t,
-                               wide_int_to_tree (t, coeff_a), tmp);
-      tree tmp3 = gimple_build (&seq, PLUS_EXPR, t, tmp2,
-                               wide_int_to_tree (t, coeff_b));
+      tree tmp = gimple_convert (&seq, type, m_index_expr);
+      tree tmp2 = gimple_build (&seq, MULT_EXPR, type,
+                               wide_int_to_tree (type, coeff_a), tmp);
+      tree tmp3 = gimple_build (&seq, PLUS_EXPR, type, tmp2,
+                               wide_int_to_tree (type, coeff_b));
       tree tmp4 = gimple_convert (&seq, TREE_TYPE (name), tmp3);
       gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
       load = gimple_build_assign (name, tmp4);
@@ -1351,7 +1352,7 @@ bit_test_cluster::find_bit_tests (vec<cluster *> &clusters)
                                                  entire));
        }
       else
-       for (int i = end - 1; i >=  start; i--)
+       for (int i = end - 1; i >= start; i--)
          output.safe_push (clusters[i]);
 
       end = start;
@@ -1484,7 +1485,7 @@ bit_test_cluster::emit (tree index_expr, tree index_type,
   unsigned int i, j, k;
   unsigned int count;
 
-  tree unsigned_index_type = unsigned_type_for (index_type);
+  tree unsigned_index_type = range_check_type (index_type);
 
   gimple_stmt_iterator gsi;
   gassign *shift_stmt;
@@ -1794,7 +1795,8 @@ switch_decision_tree::try_switch_expansion (vec<cluster *> &clusters)
   tree index_type = TREE_TYPE (index_expr);
   basic_block bb = gimple_bb (m_switch);
 
-  if (gimple_switch_num_labels (m_switch) == 1)
+  if (gimple_switch_num_labels (m_switch) == 1
+      || range_check_type (index_type) == NULL_TREE)
     return false;
 
   /* Find the default case target label.  */