Hi, > Seems that use info is not updated. >
You should put a TODO_update_ssa in the flags of prefetching pass. With the attached patch I don't see an error. Also, why don't you use trunk for your developments? Sebastian
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h index 1d2e69a..1320b5a 100644 --- a/gcc/tree-flow.h +++ b/gcc/tree-flow.h @@ -782,6 +782,7 @@ bool gimple_duplicate_loop_to_header_edge (struct loop *, edge, edge, VEC (edge, heap) **, int); struct loop *slpeel_tree_duplicate_loop_to_edge_cfg (struct loop *, edge); +void slpeel_update_phis_for_duplicate_loop (struct loop *, struct loop *, bool); void rename_variables_in_loop (struct loop *); void rename_variables_in_bb (basic_block bb); struct loop *tree_ssa_loop_version (struct loop *, tree, diff --git a/gcc/tree-ssa-loop-manip.c b/gcc/tree-ssa-loop-manip.c index e43c0bc..2f536df 100644 --- a/gcc/tree-ssa-loop-manip.c +++ b/gcc/tree-ssa-loop-manip.c @@ -1104,6 +1104,44 @@ tree_unroll_loop (struct loop *loop, unsigned factor, NULL, NULL); } +/* Peel off the first or last few iterations of the loop. */ + +struct loop * +tree_peel_loop (struct loop *loop, unsigned num, + edge e, struct tree_niter_desc *desc) +{ + struct loop *new_loop, *first_loop, *second_loop; + tree first_niters; + edge exit_e = single_exit (loop); + + if (!slpeel_can_duplicate_loop_p (loop, e)) + return NULL; + + new_loop = slpeel_tree_duplicate_loop_to_edge_cfg (loop, e); + + if (e == exit_e) + { + /* NEW_LOOP was placed after LOOP. */ + first_loop = loop; + second_loop = new_loop; + } + else + { + /* NEW_LOOP was placed before LOOP. */ + first_loop = new_loop; + second_loop = loop; + } + + slpeel_update_phis_for_duplicate_loop (loop, new_loop, e == exit_e); + rename_variables_in_loop (new_loop); + + first_niters = build_int_cst (integer_type_node, num); + + slpeel_make_loop_iterate_ntimes (first_loop, first_niters); + + return new_loop; +} + /* Rewrite the phi node at position PSI in function of the main induction variable MAIN_IV and insert the generated code at GSI. */ diff --git a/gcc/tree-ssa-loop-prefetch.c b/gcc/tree-ssa-loop-prefetch.c index b479707..36f2402 100644 --- a/gcc/tree-ssa-loop-prefetch.c +++ b/gcc/tree-ssa-loop-prefetch.c @@ -1548,7 +1548,7 @@ loop_prefetch_arrays (struct loop *loop) unsigned ahead, ninsns, time, unroll_factor; HOST_WIDE_INT est_niter; struct tree_niter_desc desc; - bool unrolled = false, no_other_refs; + bool unrolled_or_peeled = false, no_other_refs; unsigned prefetch_count; unsigned mem_ref_count; @@ -1599,13 +1599,20 @@ loop_prefetch_arrays (struct loop *loop) if (!schedule_prefetches (refs, unroll_factor, ahead)) goto fail; - /* Step 5: unroll the loop. TODO -- peeling of first and last few + /* step 5: peel off the last few iterations. */ + if (ahead > 0) + { + if (tree_peel_loop (loop, ahead, single_exit (loop), &desc) != NULL) + unrolled_or_peeled = true; + } + + /* Step 6: unroll the loop. TODO -- peeling of first and last few iterations so that we do not issue superfluous prefetches. */ if (unroll_factor != 1) { tree_unroll_loop (loop, unroll_factor, single_dom_exit (loop), &desc); - unrolled = true; + unrolled_or_peeled = true; } /* Step 6: issue the prefetches. */ @@ -1613,7 +1620,7 @@ loop_prefetch_arrays (struct loop *loop) fail: release_mem_refs (refs); - return unrolled; + return unrolled_or_peeled; } /* Issue prefetch instructions for array references in loops. */ diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index 8f7047f..6adbb7b 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -626,7 +626,8 @@ struct gimple_opt_pass pass_loop_prefetch = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func | TODO_verify_loops /* todo_flags_finish */ + TODO_dump_func | TODO_verify_loops + | TODO_update_ssa /* todo_flags_finish */ } }; diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c index c0b15cd..c1d7564 100644 --- a/gcc/tree-vect-loop-manip.c +++ b/gcc/tree-vect-loop-manip.c @@ -121,7 +121,7 @@ rename_variables_in_loop (struct loop *loop) AFTER is true if NEW_LOOP executes after ORIG_LOOP, and false if it executes before it. */ -static void +void slpeel_update_phis_for_duplicate_loop (struct loop *orig_loop, struct loop *new_loop, bool after) {