diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 04dbcb0..61a5e54 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2015-12-03 Jeff Law + + * 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-11-27 Jiri Engelthaler PR driver/68029 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4e62a06..893aab1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2015-12-02 Jeff Law + + * gcc.dg/tree-ssa/reassoc-43.c: New test. + 2015-12-02 Andreas Krebbel * gcc.dg/optimize-bswapdi-1.c: Force using -mzarch on s390 and 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 index 0000000..ea44f30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-43.c @@ -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"} } */ diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c index dfd0da1..315b0bf 100644 --- a/gcc/tree-ssa-reassoc.c +++ b/gcc/tree-ssa-reassoc.c @@ -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 ops; auto_vec 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 (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 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 {