Commit b02b9b53 by Zdenek Dvorak Committed by Zdenek Dvorak

tree-vrp.c (finalize_jump_threads): Do not care about dominance info.

	* tree-vrp.c (finalize_jump_threads): Do not care about dominance info.
	(execute_vrp): Preserve loops through jump threading.
	* tree-ssa-threadupdate.c (thread_single_edge,
	dbds_continue_enumeration_p, determine_bb_domination_status,
	thread_through_loop_header): New functions.
	(create_edge_and_update_destination_phis,
	create_edge_and_update_destination_phis): Set loops for the new blocks.
	(prune_undesirable_thread_requests): Removed.
	(redirect_edges): Do not pretend that redirect_edge_and_branch can
	create new blocks.
	(thread_block): Do not call prune_undesirable_thread_requests.
	Update loops.
	(mark_threaded_blocks): Select edges to thread here.
	(thread_through_all_blocks): Take may_peel_loop_headers argument.
	Thread edges through loop headers independently.
	* cfgloopmanip.c (create_preheader, mfb_keep_just): Export.
	* tree-pass.h (TODO_mark_first_instance): New.
	(first_pass_instance): Declare.
	* cfghooks.c (duplicate_block): Put the block to the original loop
	if copy is not specified.
	* tree-ssa-dom.c (tree_ssa_dominator_optimize): Preserve loops through
	jump threading.  Pass may_peel_loop_headers to
	thread_through_all_blocks according to first_pass_instance.
	* cfgloop.h (create_preheader): Declare.
	* tree-flow.h (thread_through_all_blocks): Declaration changed.
	* basic-block.h (mfb_keep_just, mfb_kj_edge): Declare.
	* passes.c (first_pass_instance): New variable.
	(next_pass_1): Set TODO_mark_first_instance.
	(execute_todo): Set first_pass_instance.

	* gcc.dg/tree-ssa/ssa-dom-thread-2.c: New test.
	* gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-103.c,
	gcc.dg/vect/vect-104.c: Use more complex construction to prevent vectorizing.
	* gcc.dg/tree-ssa/pr21559.c: Update outcome.

From-SVN: r124786
parent d2594859
2007-05-17 Zdenek Dvorak <dvorakz@suse.cz>
* tree-vrp.c (finalize_jump_threads): Do not care about dominance info.
(execute_vrp): Preserve loops through jump threading.
* tree-ssa-threadupdate.c (thread_single_edge,
dbds_continue_enumeration_p, determine_bb_domination_status,
thread_through_loop_header): New functions.
(create_edge_and_update_destination_phis,
create_edge_and_update_destination_phis): Set loops for the new blocks.
(prune_undesirable_thread_requests): Removed.
(redirect_edges): Do not pretend that redirect_edge_and_branch can
create new blocks.
(thread_block): Do not call prune_undesirable_thread_requests.
Update loops.
(mark_threaded_blocks): Select edges to thread here.
(thread_through_all_blocks): Take may_peel_loop_headers argument.
Thread edges through loop headers independently.
* cfgloopmanip.c (create_preheader, mfb_keep_just): Export.
* tree-pass.h (TODO_mark_first_instance): New.
(first_pass_instance): Declare.
* cfghooks.c (duplicate_block): Put the block to the original loop
if copy is not specified.
* tree-ssa-dom.c (tree_ssa_dominator_optimize): Preserve loops through
jump threading. Pass may_peel_loop_headers to
thread_through_all_blocks according to first_pass_instance.
* cfgloop.h (create_preheader): Declare.
* tree-flow.h (thread_through_all_blocks): Declaration changed.
* basic-block.h (mfb_keep_just, mfb_kj_edge): Declare.
* passes.c (first_pass_instance): New variable.
(next_pass_1): Set TODO_mark_first_instance.
(execute_todo): Set first_pass_instance.
2007-05-17 Uros Bizjak <ubizjak@gmail.com>
PR tree-optimization/24659
......
......@@ -1173,4 +1173,8 @@ bb_has_eh_pred (basic_block bb)
return false;
}
/* In cfgloopmanip.c. */
extern edge mfb_kj_edge;
bool mfb_keep_just (edge);
#endif /* GCC_BASIC_BLOCK_H */
......@@ -923,9 +923,15 @@ duplicate_block (basic_block bb, edge e, basic_block after)
set_bb_original (new_bb, bb);
set_bb_copy (bb, new_bb);
/* Add the new block to the prescribed loop. */
/* Add the new block to the copy of the loop of BB, or directly to the loop
of BB if the loop is not being copied. */
if (current_loops != NULL)
add_bb_to_loop (new_bb, bb->loop_father->copy);
{
struct loop *cloop = bb->loop_father;
if (cloop->copy)
cloop = cloop->copy;
add_bb_to_loop (new_bb, cloop);
}
return new_bb;
}
......
......@@ -252,6 +252,7 @@ enum
CP_SIMPLE_PREHEADERS = 1
};
basic_block create_preheader (struct loop *, int);
extern void create_preheaders (int);
extern void force_single_succ_latches (void);
......
......@@ -41,7 +41,6 @@ static int find_path (edge, basic_block **);
static void fix_loop_placements (struct loop *, bool *);
static bool fix_bb_placement (basic_block);
static void fix_bb_placements (basic_block, bool *);
static basic_block create_preheader (struct loop *, int);
static void unloop (struct loop *, bool *);
#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
......@@ -1085,8 +1084,8 @@ duplicate_loop_to_header_edge (struct loop *loop, edge e,
MFB_KJ_EDGE to the entry part. E is the edge for that we should decide
whether to redirect it. */
static edge mfb_kj_edge;
static bool
edge mfb_kj_edge;
bool
mfb_keep_just (edge e)
{
return e != mfb_kj_edge;
......@@ -1097,7 +1096,7 @@ mfb_keep_just (edge e)
entry; otherwise we also force preheader block to have only one successor.
The function also updates dominators. */
static basic_block
basic_block
create_preheader (struct loop *loop, int flags)
{
edge e, fallthru;
......
......@@ -105,6 +105,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
/* Global variables used to communicate with passes. */
int dump_flags;
bool in_gimple_form;
bool first_pass_instance;
/* This is called from various places for FUNCTION_DECL, VAR_DECL,
......@@ -392,6 +393,8 @@ next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass)
memcpy (new, pass, sizeof (*new));
new->next = NULL;
new->todo_flags_start &= ~TODO_mark_first_instance;
/* Indicate to register_dump_files that this pass has duplicates,
and so it should rename the dump file. The first instance will
be -1, and be number of duplicates = -static_pass_number - 1.
......@@ -406,6 +409,7 @@ next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass)
}
else
{
pass->todo_flags_start |= TODO_mark_first_instance;
pass->static_pass_number = -1;
*list = pass;
}
......@@ -932,6 +936,9 @@ execute_todo (unsigned int flags)
gcc_assert (flags & TODO_update_ssa_any);
#endif
/* Inform the pass whether it is the first time it is run. */
first_pass_instance = (flags & TODO_mark_first_instance) != 0;
do_per_function (execute_function_todo, (void *)(size_t) flags);
/* Always remove functions just as before inlining: IPA passes might be
......
2007-05-17 Zdenek Dvorak <dvorakz@suse.cz>
* gcc.dg/tree-ssa/ssa-dom-thread-2.c: New test.
* gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-103.c,
gcc.dg/vect/vect-104.c: Use more complex construction to prevent vectorizing.
* gcc.dg/tree-ssa/pr21559.c: Update outcome.
2007-05-17 Uros Bizjak <ubizjak@gmail.com>
PR tree-optimization/24659
......@@ -35,11 +35,9 @@ void foo (void)
/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */
/* Second, we should thread the edge out of the loop via the break
statement. */
/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "vrp1" } } */
/* Now if we were really good, we'd realize that the final bytes == 0
test is totally useless. That's not likely to happen anytime soon. */
statement. We also realize that the final bytes == 0 test is useless,
and thread over it. */
/* { dg-final { scan-tree-dump-times "Threaded jump" 2 "vrp1" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom1-stats" } */
void foo();
void bla();
void bar();
/* In the following two cases, we should be able to thread edge through
the loop header. */
void thread_entry_through_header (void)
{
int i;
for (i = 0; i < 170; i++)
bla ();
}
void thread_latch_through_header (void)
{
int i = 0;
int first = 1;
do
{
if (first)
foo ();
first = 0;
bla ();
} while (i++ < 100);
}
/* This is a TODO -- it is correct to thread both entry and latch edge through
the header, but we do not handle this case yet. */
void dont_thread_1 (void)
{
int i = 0;
int first = 1;
do
{
if (first)
foo ();
else
bar ();
first = 0;
bla ();
} while (i++ < 100);
}
/* Avoid threading in the following two cases, to prevent creating subloops. */
void dont_thread_2 (int first)
{
int i = 0;
do
{
if (first)
foo ();
else
bar ();
first = 0;
bla ();
} while (i++ < 100);
}
void dont_thread_3 (int nfirst)
{
int i = 0;
int first = 0;
do
{
if (first)
foo ();
else
bar ();
first = nfirst;
bla ();
} while (i++ < 100);
}
/* Avoid threading in this case, in order to avoid creating loop with
multiple entries. */
void dont_thread_4 (int a, int nfirst)
{
int i = 0;
int first;
if (a)
first = 0;
else
first = 1;
do
{
if (first)
foo ();
else
bar ();
first = nfirst;
bla ();
} while (i++ < 100);
}
/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp1"} } */
/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp1"} } */
/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 0 "dom1"} } */
/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "dom1"} } */
/* { dg-final { cleanup-tree-dump "dom1" } } */
/* { dg-final { cleanup-tree-dump "vrp1" } } */
......@@ -14,6 +14,7 @@ struct extraction
static int a[N] = {1,2,3,4,5,6,7,8,9};
static int b[N] = {2,3,4,5,6,7,8,9,9};
volatile int foo;
int main1 (int x, int y) {
int i;
......@@ -23,7 +24,7 @@ int main1 (int x, int y) {
for (i = 0; i < N; i++)
{
p->a[i] = a[i];
if (x == 135)
if (foo == 135)
abort (); /* to avoid vectorization */
}
......@@ -46,6 +47,7 @@ int main (void)
{
check_vect ();
foo = 0;
return main1 (0, N);
}
......
......@@ -15,6 +15,7 @@ struct extraction
static int a[N] = {1,2,3,4,5,6,7,8,9};
static int b[N] = {17,24,7,0,2,3,4,31,82};
static int c[N] = {9,17,24,7,0,2,3,4,31};
volatile int foo;
int main1 (int x, int y) {
int i;
......@@ -25,7 +26,7 @@ int main1 (int x, int y) {
{
p->a[i] = a[i];
p->b[i] = b[i];
if (x == 135)
if (foo == 135)
abort (); /* to avoid vectorization */
}
......@@ -48,6 +49,7 @@ int main (void)
{
check_vect ();
foo = 0;
return main1 (0, N);
}
......
......@@ -15,6 +15,7 @@ struct extraction
static int a[N][N] = {{1,2,3},{4,5,6},{7,8,9}};
static int b[N][N] = {{17,24,7},{0,2,3},{4,31,82}};
static int c[N][N] = {{1,2,3},{4,6,8},{8,9,9}};
volatile int foo;
int main1 (int x) {
int i,j;
......@@ -27,7 +28,7 @@ int main1 (int x) {
{
p->a[i][j] = a[i][j];
p->b[i][j] = b[i][j];
if (x == 135)
if (foo == 135)
abort (); /* to avoid vectorization */
}
}
......@@ -57,6 +58,7 @@ int main (void)
{
check_vect ();
foo = 0;
return main1 (N);
}
......
......@@ -1113,7 +1113,7 @@ bool multiplier_allowed_in_address_p (HOST_WIDE_INT, enum machine_mode);
unsigned multiply_by_cost (HOST_WIDE_INT, enum machine_mode);
/* In tree-ssa-threadupdate.c. */
extern bool thread_through_all_blocks (void);
extern bool thread_through_all_blocks (bool);
extern void register_jump_thread (edge, edge);
/* In gimplify.c */
......
......@@ -218,6 +218,9 @@ struct dump_file_info
for the passes that are handed to register_dump_files. */
#define TODO_set_props (1 << 15)
/* Internally used for the first instance of a pass. */
#define TODO_mark_first_instance (1 << 16)
#define TODO_update_ssa_any \
(TODO_update_ssa \
| TODO_update_ssa_no_phi \
......@@ -417,4 +420,13 @@ extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes;
extern void execute_pass_list (struct tree_opt_pass *);
extern void execute_ipa_pass_list (struct tree_opt_pass *);
/* Set to true if the pass is called the first time during compilation of the
current function. Note that using this information in the optimization
passes is considered not to be clean, and it should be avoided if possible.
This flag is currently used to prevent loops from being peeled repeatedly
in jump threading; it will be removed once we preserve loop structures
throughout the compilation -- we will be able to mark the affected loops
directly in jump threading, and avoid peeling them next time. */
extern bool first_pass_instance;
#endif /* GCC_TREE_PASS_H */
......@@ -277,25 +277,17 @@ tree_ssa_dominator_optimize (void)
calculate_dominance_info (CDI_DOMINATORS);
cfg_altered = false;
/* We need to know which edges exit loops so that we can
aggressively thread through loop headers to an exit
edge. */
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
if (current_loops)
{
mark_loop_exit_edges ();
loop_optimizer_finalize ();
}
/* Clean up the CFG so that any forwarder blocks created by loop
canonicalization are removed. */
cleanup_tree_cfg ();
calculate_dominance_info (CDI_DOMINATORS);
/* We need to know loop structures in order to avoid destroying them
in jump threading. Note that we still can e.g. thread through loop
headers to an exit edge, or through loop header to the loop body, assuming
that we update the loop info. */
loop_optimizer_init (LOOPS_HAVE_SIMPLE_LATCHES);
/* We need accurate information regarding back edges in the CFG
for jump threading. */
for jump threading; this may include back edes that are not part of
a single loop. */
mark_dfs_back_edges ();
/* Recursively walk the dominator tree optimizing statements. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
......@@ -319,7 +311,7 @@ tree_ssa_dominator_optimize (void)
free_all_edge_infos ();
/* Thread jumps, creating duplicate blocks as needed. */
cfg_altered |= thread_through_all_blocks ();
cfg_altered |= thread_through_all_blocks (first_pass_instance);
if (cfg_altered)
free_dominance_info (CDI_DOMINATORS);
......@@ -353,6 +345,8 @@ tree_ssa_dominator_optimize (void)
if (dump_file && (dump_flags & TDF_STATS))
dump_dominator_optimization_stats (dump_file);
loop_optimizer_finalize ();
/* Delete our main hashtable. */
htab_delete (avail_exprs);
......
......@@ -5865,13 +5865,7 @@ identify_jump_threads (void)
static void
finalize_jump_threads (void)
{
bool cfg_altered = false;
cfg_altered = thread_through_all_blocks ();
/* If we threaded jumps, then we need to recompute the dominance
information. */
if (cfg_altered)
free_dominance_info (CDI_DOMINATORS);
thread_through_all_blocks (false);
VEC_free (tree, heap, stack);
}
......@@ -5990,22 +5984,19 @@ vrp_finalize (void)
static unsigned int
execute_vrp (void)
{
insert_range_assertions ();
loop_optimizer_init (LOOPS_NORMAL);
loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
if (current_loops)
scev_initialize ();
{
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
scev_initialize ();
}
insert_range_assertions ();
vrp_initialize ();
ssa_propagate (vrp_visit_stmt, vrp_visit_phi_node);
vrp_finalize ();
if (current_loops)
{
scev_finalize ();
loop_optimizer_finalize ();
}
/* ASSERT_EXPRs must be removed before finalizing jump threads
as finalizing jump threads calls the CFG cleanup code which
does not properly handle ASSERT_EXPRs. */
......@@ -6019,6 +6010,12 @@ execute_vrp (void)
update_ssa (TODO_update_ssa);
finalize_jump_threads ();
if (current_loops)
{
scev_finalize ();
loop_optimizer_finalize ();
}
return 0;
}
......
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