tree-ssa-reassoc.c (maybe_optimize_range_tests): Return boolean indicating if a gimpl...
authorJeff Law <law@redhat.com>
Fri, 4 Dec 2015 16:19:30 +0000 (09:19 -0700)
committerJeff Law <law@gcc.gnu.org>
Fri, 4 Dec 2015 16:19:30 +0000 (09:19 -0700)
* tree-ssa-reassoc.c (maybe_optimize_range_tests): Return boolean
indicating if a gimple conditional was optimized to true/false.
(reassociate_bb): Bubble up return value from
maybe_optimize_range_tests.
(do_reassoc): Similarly, but for reassociate_bb.
(execute_reassoc): Return TODO_cleanup_cfg as needed.

* gcc.dg/tree-ssa/reassoc-43.c: New test.

From-SVN: r231277

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/reassoc-43.c [new file with mode: 0644]
gcc/tree-ssa-reassoc.c

index 9390f2b129ed49a0175af5c213f8d99ead097397..a3bde22653e77452a919612482b2b96bff62fe89 100644 (file)
@@ -1,3 +1,12 @@
+2015-12-04  Jeff Law  <law@redhat.com>
+
+       * tree-ssa-reassoc.c (maybe_optimize_range_tests): Return boolean
+       indicating if a gimple conditional was optimized to true/false.
+       (reassociate_bb): Bubble up return value from
+       maybe_optimize_range_tests.
+       (do_reassoc): Similarly, but for reassociate_bb.
+       (execute_reassoc): Return TODO_cleanup_cfg as needed.
+
 2015-12-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * config/aarch64/aarch64.c (aarch64_override_options_internal):
index 50df41c365fce038823d211b3a41e68117cad93b..4b1b1a3cee33d2ade6bd342adb18ea806d6b1999 100644 (file)
@@ -1,3 +1,7 @@
+2015-12-02  Jeff Law  <law@redhat.com>
+
+       * gcc.dg/tree-ssa/reassoc-43.c: New test.
+
 2015-12-04  Kyrylo Tkachov  <kyrylo.tkachov@arm.com>
 
        * gcc.target/aarch64/mgeneral-regs_4.c: New test.
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-43.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-43.c
new file mode 100644 (file)
index 0000000..ea44f30
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-reassoc -w" } */
+
+typedef union tree_node *tree;
+enum cpp_ttype { CPP_COLON, CPP_SEMICOLON, CPP_CLOSE_BRACE, CPP_COMMA };
+enum rid { RID_STATIC = 0, RID_ATTRIBUTE, };
+typedef struct c_token
+{
+  enum cpp_ttype type:8;
+}
+c_token;
+typedef struct c_parser
+{
+  c_token tokens[2];
+  short tokens_avail;
+}
+c_parser;
+__inline__ c_token *
+c_parser_peek_token (c_parser * parser)
+{
+  if (parser->tokens_avail == 0)
+    {
+      parser->tokens_avail = 1;
+    }
+  return &parser->tokens[0];
+}
+
+__inline__ unsigned char
+c_parser_next_token_is (c_parser * parser, enum cpp_ttype type)
+{
+  return c_parser_peek_token (parser)->type == type;
+}
+
+void
+c_parser_translation_unit (c_parser * parser)
+{
+  tree prefix_attrs;
+  tree all_prefix_attrs;
+  while (1)
+    {
+      if (c_parser_next_token_is (parser, CPP_COLON)
+         || c_parser_next_token_is (parser, CPP_COMMA)
+         || c_parser_next_token_is (parser, CPP_SEMICOLON)
+         || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
+         || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+       {
+         if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
+           all_prefix_attrs =
+             chainon (c_parser_attributes (parser), prefix_attrs);
+       }
+    }
+}
+/* { dg-final { scan-tree-dump-not "0 != 0" "reassoc2"} } */
index dfd0da1a123ae84323e6e6082690b3f0306e2239..315b0bfc7ffd928fd5f74d3f881eeec486dcb587 100644 (file)
@@ -2976,9 +2976,15 @@ struct inter_bb_range_test_entry
   unsigned int first_idx, last_idx;
 };
 
-/* Inter-bb range test optimization.  */
+/* Inter-bb range test optimization.
 
-static void
+   Returns TRUE if a gimple conditional is optimized to a true/false,
+   otherwise return FALSE.
+
+   This indicates to the caller that it should run a CFG cleanup pass
+   once reassociation is completed.  */
+
+static bool
 maybe_optimize_range_tests (gimple *stmt)
 {
   basic_block first_bb = gimple_bb (stmt);
@@ -2990,6 +2996,7 @@ maybe_optimize_range_tests (gimple *stmt)
   auto_vec<operand_entry *> ops;
   auto_vec<inter_bb_range_test_entry> bbinfo;
   bool any_changes = false;
+  bool cfg_cleanup_needed = false;
 
   /* Consider only basic blocks that end with GIMPLE_COND or
      a cast statement satisfying final_range_test_p.  All
@@ -2998,15 +3005,15 @@ maybe_optimize_range_tests (gimple *stmt)
   if (gimple_code (stmt) == GIMPLE_COND)
     {
       if (EDGE_COUNT (first_bb->succs) != 2)
-       return;
+       return cfg_cleanup_needed;
     }
   else if (final_range_test_p (stmt))
     other_bb = single_succ (first_bb);
   else
-    return;
+    return cfg_cleanup_needed;
 
   if (stmt_could_throw_p (stmt))
-    return;
+    return cfg_cleanup_needed;
 
   /* As relative ordering of post-dominator sons isn't fixed,
      maybe_optimize_range_tests can be called first on any
@@ -3030,14 +3037,14 @@ maybe_optimize_range_tests (gimple *stmt)
       /* As non-GIMPLE_COND last stmt always terminates the range,
         if forward search didn't discover anything, just give up.  */
       if (gimple_code (stmt) != GIMPLE_COND)
-       return;
+       return cfg_cleanup_needed;
       /* Look at both successors.  Either it ends with a GIMPLE_COND
         and satisfies suitable_cond_bb, or ends with a cast and
         other_bb is that cast's successor.  */
       FOR_EACH_EDGE (e, ei, first_bb->succs)
        if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
            || e->dest == first_bb)
-         return;
+         return cfg_cleanup_needed;
        else if (single_pred_p (e->dest))
          {
            stmt = last_stmt (e->dest);
@@ -3060,7 +3067,7 @@ maybe_optimize_range_tests (gimple *stmt)
              }
          }
       if (other_bb == NULL)
-       return;
+       return cfg_cleanup_needed;
     }
   /* Now do the forward search, moving last_bb to successor bbs
      that aren't other_bb.  */
@@ -3080,7 +3087,7 @@ maybe_optimize_range_tests (gimple *stmt)
       last_bb = e->dest;
     }
   if (first_bb == last_bb)
-    return;
+    return cfg_cleanup_needed;
   /* Here basic blocks first_bb through last_bb's predecessor
      end with GIMPLE_COND, all of them have one of the edges to
      other_bb and another to another block in the range,
@@ -3289,10 +3296,18 @@ maybe_optimize_range_tests (gimple *stmt)
              && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
            {
              gcond *cond_stmt = as_a <gcond *> (last_stmt (bb));
+             /* If we collapse the conditional to a true/false
+                condition, then bubble that knowledge up to our caller.  */
              if (integer_zerop (ops[bbinfo[idx].first_idx]->op))
-               gimple_cond_make_false (cond_stmt);
+               {
+                 gimple_cond_make_false (cond_stmt);
+                 cfg_cleanup_needed = true;
+               }
              else if (integer_onep (ops[bbinfo[idx].first_idx]->op))
-               gimple_cond_make_true (cond_stmt);
+               {
+                 gimple_cond_make_true (cond_stmt);
+                 cfg_cleanup_needed = true;
+               }
              else
                {
                  gimple_cond_set_code (cond_stmt, NE_EXPR);
@@ -3306,6 +3321,7 @@ maybe_optimize_range_tests (gimple *stmt)
            break;
        }
     }
+  return cfg_cleanup_needed;
 }
 
 /* Return true if OPERAND is defined by a PHI node which uses the LHS
@@ -4753,17 +4769,20 @@ transform_stmt_to_multiply (gimple_stmt_iterator *gsi, gimple *stmt,
 }
 
 /* Reassociate expressions in basic block BB and its post-dominator as
-   children.  */
+   children.
 
-static void
+   Bubble up return status from maybe_optimize_range_tests.  */
+
+static bool
 reassociate_bb (basic_block bb)
 {
   gimple_stmt_iterator gsi;
   basic_block son;
   gimple *stmt = last_stmt (bb);
+  bool cfg_cleanup_needed = false;
 
   if (stmt && !gimple_visited_p (stmt))
-    maybe_optimize_range_tests (stmt);
+    cfg_cleanup_needed |= maybe_optimize_range_tests (stmt);
 
   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
     {
@@ -4922,7 +4941,9 @@ reassociate_bb (basic_block bb)
   for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
        son;
        son = next_dom_son (CDI_POST_DOMINATORS, son))
-    reassociate_bb (son);
+    cfg_cleanup_needed |= reassociate_bb (son);
+
+  return cfg_cleanup_needed;
 }
 
 /* Add jumps around shifts for range tests turned into bit tests.
@@ -5028,11 +5049,13 @@ debug_ops_vector (vec<operand_entry *> ops)
   dump_ops_vector (stderr, ops);
 }
 
-static void
+/* Bubble up return status from reassociate_bb.  */
+
+static bool
 do_reassoc (void)
 {
   break_up_subtract_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun));
-  reassociate_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
+  return reassociate_bb (EXIT_BLOCK_PTR_FOR_FN (cfun));
 }
 
 /* Initialize the reassociation pass.  */
@@ -5106,7 +5129,10 @@ fini_reassoc (void)
 }
 
 /* Gate and execute functions for Reassociation.  If INSERT_POWI_P, enable
-   insertion of __builtin_powi calls.  */
+   insertion of __builtin_powi calls.
+
+   Returns TODO_cfg_cleanup if a CFG cleanup pass is desired due to
+   optimization of a gimple conditional.  Otherwise returns zero.  */
 
 static unsigned int
 execute_reassoc (bool insert_powi_p)
@@ -5115,12 +5141,13 @@ execute_reassoc (bool insert_powi_p)
 
   init_reassoc ();
 
-  do_reassoc ();
+  bool cfg_cleanup_needed;
+  cfg_cleanup_needed = do_reassoc ();
   repropagate_negates ();
   branch_fixup ();
 
   fini_reassoc ();
-  return 0;
+  return cfg_cleanup_needed ? TODO_cleanup_cfg : 0;
 }
 
 namespace {