Commit 8010f31f by Jeff Law Committed by Jeff Law

tree-ssa-reassoc.c (maybe_optimize_range_tests): Return boolean indicating if a…

tree-ssa-reassoc.c (maybe_optimize_range_tests): Return boolean indicating if a gimple conditional was optimized to true/false.

	* 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
parent 7d9425d4
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> 2015-12-04 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* config/aarch64/aarch64.c (aarch64_override_options_internal): * config/aarch64/aarch64.c (aarch64_override_options_internal):
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> 2015-12-04 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
* gcc.target/aarch64/mgeneral-regs_4.c: New test. * gcc.target/aarch64/mgeneral-regs_4.c: New test.
......
/* { 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"} } */
...@@ -2976,9 +2976,15 @@ struct inter_bb_range_test_entry ...@@ -2976,9 +2976,15 @@ struct inter_bb_range_test_entry
unsigned int first_idx, last_idx; 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) maybe_optimize_range_tests (gimple *stmt)
{ {
basic_block first_bb = gimple_bb (stmt); basic_block first_bb = gimple_bb (stmt);
...@@ -2990,6 +2996,7 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -2990,6 +2996,7 @@ maybe_optimize_range_tests (gimple *stmt)
auto_vec<operand_entry *> ops; auto_vec<operand_entry *> ops;
auto_vec<inter_bb_range_test_entry> bbinfo; auto_vec<inter_bb_range_test_entry> bbinfo;
bool any_changes = false; bool any_changes = false;
bool cfg_cleanup_needed = false;
/* Consider only basic blocks that end with GIMPLE_COND or /* Consider only basic blocks that end with GIMPLE_COND or
a cast statement satisfying final_range_test_p. All a cast statement satisfying final_range_test_p. All
...@@ -2998,15 +3005,15 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -2998,15 +3005,15 @@ maybe_optimize_range_tests (gimple *stmt)
if (gimple_code (stmt) == GIMPLE_COND) if (gimple_code (stmt) == GIMPLE_COND)
{ {
if (EDGE_COUNT (first_bb->succs) != 2) if (EDGE_COUNT (first_bb->succs) != 2)
return; return cfg_cleanup_needed;
} }
else if (final_range_test_p (stmt)) else if (final_range_test_p (stmt))
other_bb = single_succ (first_bb); other_bb = single_succ (first_bb);
else else
return; return cfg_cleanup_needed;
if (stmt_could_throw_p (stmt)) if (stmt_could_throw_p (stmt))
return; return cfg_cleanup_needed;
/* As relative ordering of post-dominator sons isn't fixed, /* As relative ordering of post-dominator sons isn't fixed,
maybe_optimize_range_tests can be called first on any maybe_optimize_range_tests can be called first on any
...@@ -3030,14 +3037,14 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -3030,14 +3037,14 @@ maybe_optimize_range_tests (gimple *stmt)
/* As non-GIMPLE_COND last stmt always terminates the range, /* As non-GIMPLE_COND last stmt always terminates the range,
if forward search didn't discover anything, just give up. */ if forward search didn't discover anything, just give up. */
if (gimple_code (stmt) != GIMPLE_COND) if (gimple_code (stmt) != GIMPLE_COND)
return; return cfg_cleanup_needed;
/* Look at both successors. Either it ends with a GIMPLE_COND /* Look at both successors. Either it ends with a GIMPLE_COND
and satisfies suitable_cond_bb, or ends with a cast and and satisfies suitable_cond_bb, or ends with a cast and
other_bb is that cast's successor. */ other_bb is that cast's successor. */
FOR_EACH_EDGE (e, ei, first_bb->succs) FOR_EACH_EDGE (e, ei, first_bb->succs)
if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE)) if (!(e->flags & (EDGE_TRUE_VALUE | EDGE_FALSE_VALUE))
|| e->dest == first_bb) || e->dest == first_bb)
return; return cfg_cleanup_needed;
else if (single_pred_p (e->dest)) else if (single_pred_p (e->dest))
{ {
stmt = last_stmt (e->dest); stmt = last_stmt (e->dest);
...@@ -3060,7 +3067,7 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -3060,7 +3067,7 @@ maybe_optimize_range_tests (gimple *stmt)
} }
} }
if (other_bb == NULL) if (other_bb == NULL)
return; return cfg_cleanup_needed;
} }
/* Now do the forward search, moving last_bb to successor bbs /* Now do the forward search, moving last_bb to successor bbs
that aren't other_bb. */ that aren't other_bb. */
...@@ -3080,7 +3087,7 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -3080,7 +3087,7 @@ maybe_optimize_range_tests (gimple *stmt)
last_bb = e->dest; last_bb = e->dest;
} }
if (first_bb == last_bb) if (first_bb == last_bb)
return; return cfg_cleanup_needed;
/* Here basic blocks first_bb through last_bb's predecessor /* Here basic blocks first_bb through last_bb's predecessor
end with GIMPLE_COND, all of them have one of the edges to end with GIMPLE_COND, all of them have one of the edges to
other_bb and another to another block in the range, other_bb and another to another block in the range,
...@@ -3289,10 +3296,18 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -3289,10 +3296,18 @@ maybe_optimize_range_tests (gimple *stmt)
&& ops[bbinfo[idx].first_idx]->op != NULL_TREE) && ops[bbinfo[idx].first_idx]->op != NULL_TREE)
{ {
gcond *cond_stmt = as_a <gcond *> (last_stmt (bb)); 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)) 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)) 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 else
{ {
gimple_cond_set_code (cond_stmt, NE_EXPR); gimple_cond_set_code (cond_stmt, NE_EXPR);
...@@ -3306,6 +3321,7 @@ maybe_optimize_range_tests (gimple *stmt) ...@@ -3306,6 +3321,7 @@ maybe_optimize_range_tests (gimple *stmt)
break; break;
} }
} }
return cfg_cleanup_needed;
} }
/* Return true if OPERAND is defined by a PHI node which uses the LHS /* 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, ...@@ -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 /* 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) reassociate_bb (basic_block bb)
{ {
gimple_stmt_iterator gsi; gimple_stmt_iterator gsi;
basic_block son; basic_block son;
gimple *stmt = last_stmt (bb); gimple *stmt = last_stmt (bb);
bool cfg_cleanup_needed = false;
if (stmt && !gimple_visited_p (stmt)) 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)) for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
{ {
...@@ -4922,7 +4941,9 @@ reassociate_bb (basic_block bb) ...@@ -4922,7 +4941,9 @@ reassociate_bb (basic_block bb)
for (son = first_dom_son (CDI_POST_DOMINATORS, bb); for (son = first_dom_son (CDI_POST_DOMINATORS, bb);
son; son;
son = next_dom_son (CDI_POST_DOMINATORS, 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. /* Add jumps around shifts for range tests turned into bit tests.
...@@ -5028,11 +5049,13 @@ debug_ops_vector (vec<operand_entry *> ops) ...@@ -5028,11 +5049,13 @@ debug_ops_vector (vec<operand_entry *> ops)
dump_ops_vector (stderr, ops); dump_ops_vector (stderr, ops);
} }
static void /* Bubble up return status from reassociate_bb. */
static bool
do_reassoc (void) do_reassoc (void)
{ {
break_up_subtract_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)); 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. */ /* Initialize the reassociation pass. */
...@@ -5106,7 +5129,10 @@ fini_reassoc (void) ...@@ -5106,7 +5129,10 @@ fini_reassoc (void)
} }
/* Gate and execute functions for Reassociation. If INSERT_POWI_P, enable /* 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 static unsigned int
execute_reassoc (bool insert_powi_p) execute_reassoc (bool insert_powi_p)
...@@ -5115,12 +5141,13 @@ execute_reassoc (bool insert_powi_p) ...@@ -5115,12 +5141,13 @@ execute_reassoc (bool insert_powi_p)
init_reassoc (); init_reassoc ();
do_reassoc (); bool cfg_cleanup_needed;
cfg_cleanup_needed = do_reassoc ();
repropagate_negates (); repropagate_negates ();
branch_fixup (); branch_fixup ();
fini_reassoc (); fini_reassoc ();
return 0; return cfg_cleanup_needed ? TODO_cleanup_cfg : 0;
} }
namespace { namespace {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment