From f6568ea476aa52a6e23c6db43b3e240cde55783a Mon Sep 17 00:00:00 2001 From: rguenth Date: Fri, 26 Apr 2013 08:01:19 +0000 Subject: [PATCH] 2013-03-26 Richard Biener * tree-cfg.c (execute_build_cfg): Build the loop tree. (pass_build_cfg): Provide PROP_loops. (move_sese_region_to_fn): Remove loops that are outlined into fn for now. * tree-inline.c: Include cfgloop.h. (initialize_cfun): Do not drop PROP_loops. (copy_loops): New function. (copy_cfg_body): Copy loop structure. (tree_function_versioning): Initialize destination loop tree. * tree-ssa-loop.c (pass_tree_loop_init): Do not provide PROP_loops. (pass_parallelize_loops): Do IL verification. * loop-init.c (loop_optimizer_init): Fixup loops if required. * tree-optimize.c (execute_fixup_cfg): If we need to cleanup the CFG make sure we fixup loops as well. * tree-ssa-tail-merge.c: Include cfgloop.h. (replace_block_by): When merging loop latches mark loops for fixup. * lto-streamer-out.c (output_struct_function_base): Drop PROP_loops for now. * tree-ssa-phiopt.c: Include tree-scalar-evolution.h. (tree_ssa_cs_elim): Initialize the loop optimizer and SCEV. * ipa-split.c: Include cfgloop.h. (split_function): Add the new return block to the loop tree root. * tree-cfgcleanup.c (remove_forwarder_block_with_phi): Return whether we have removed the forwarder block. (merge_phi_nodes): If we removed a forwarder mark loops for fixup. * cfgloop.h (place_new_loop): Declare. * cfgloopmanip.c (place_new_loop): Export. * Makefile.in (asan.o): Add $(CFGLOOP_H) dependency. (tree-switch-conversion.o): Likewise. (tree-complex.o): Likewise. (tree-inline.o): Likewise. (tree-ssa-tailmerge.o): Likewise. (ipa-split.o): Likewise. (tree-ssa-phiopt.o): Add $(SCEV_H) dependency. (tree-ssa-copy.o): Likewise. * tree-switch-conversion.c: Include cfgloop.h (process_switch): If we emit a bit-test cascade, schedule loops for fixup. * tree-complex.c: Include cfgloop.h. (expand_complex_div_wide): Properly add new basic-blocks to loops. * asan.c: Include cfgloop.h. (create_cond_insert_point): Properly add new basic-blocks to loops, schedule loop fixup. * cfgloop.c (verify_loop_structure): Check that looks are not marked for fixup. * omp-low.c (expand_parallel_call): Properly add new basic-blocks to loops. (expand_omp_for_generic): Likewise. (expand_omp_sections): Likewise. (expand_omp_atomic_pipeline): Schedule loops for fixup. * tree-ssa-copy.c: Include tree-scalar-evolution.h. (fini_copy_prop): Disable DCE in substitute_and_fold if SCEV is initialized, not when loops are present. * tree-parloops.c (parallelize_loops): Remove checking here. * passes.c (init_optimization_passes): Schedule a copy-propagation pass before complete unrolling of inner loops. * gcc.dg/tree-prof/update-loopch.c: Revert last change. * gcc.dg/graphite/pr33766.c: Fix undefined behavior. * gcc.dg/pr53265.c: Remove XFAILs. * gcc.dg/tree-ssa/loop-38.c: Remove unreliable dump scanning. * gcc.dg/tree-ssa/pr21559.c: Change back to two expected jump threads. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@198333 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 59 +++++++++++++++++++++++++ gcc/Makefile.in | 16 +++---- gcc/asan.c | 6 +++ gcc/cfgloop.c | 6 +++ gcc/cfgloop.h | 1 + gcc/cfgloopmanip.c | 2 +- gcc/ipa-split.c | 3 ++ gcc/loop-init.c | 13 +++++- gcc/lto-streamer-out.c | 5 ++- gcc/omp-low.c | 15 +++++++ gcc/passes.c | 1 + gcc/testsuite/ChangeLog | 8 ++++ gcc/testsuite/gcc.dg/graphite/pr33766.c | 22 +++++----- gcc/testsuite/gcc.dg/pr53265.c | 8 ++-- gcc/testsuite/gcc.dg/tree-prof/update-loopch.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/loop-38.c | 1 - gcc/testsuite/gcc.dg/tree-ssa/pr21559.c | 2 +- gcc/tree-cfg.c | 18 +++++++- gcc/tree-cfgcleanup.c | 22 +++++++--- gcc/tree-complex.c | 6 +++ gcc/tree-inline.c | 61 +++++++++++++++++++++++++- gcc/tree-optimize.c | 4 ++ gcc/tree-parloops.c | 5 --- gcc/tree-ssa-copy.c | 6 +-- gcc/tree-ssa-loop.c | 4 +- gcc/tree-ssa-phiopt.c | 12 ++++- gcc/tree-ssa-tail-merge.c | 12 +++++ gcc/tree-switch-conversion.c | 3 ++ 28 files changed, 273 insertions(+), 50 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 749d2838a0b..e283c3dbff1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,62 @@ +2013-03-26 Richard Biener + + * tree-cfg.c (execute_build_cfg): Build the loop tree. + (pass_build_cfg): Provide PROP_loops. + (move_sese_region_to_fn): Remove loops that are outlined into fn + for now. + * tree-inline.c: Include cfgloop.h. + (initialize_cfun): Do not drop PROP_loops. + (copy_loops): New function. + (copy_cfg_body): Copy loop structure. + (tree_function_versioning): Initialize destination loop tree. + * tree-ssa-loop.c (pass_tree_loop_init): Do not provide PROP_loops. + (pass_parallelize_loops): Do IL verification. + * loop-init.c (loop_optimizer_init): Fixup loops if required. + * tree-optimize.c (execute_fixup_cfg): If we need to cleanup + the CFG make sure we fixup loops as well. + * tree-ssa-tail-merge.c: Include cfgloop.h. + (replace_block_by): When merging loop latches mark loops for fixup. + * lto-streamer-out.c (output_struct_function_base): Drop + PROP_loops for now. + * tree-ssa-phiopt.c: Include tree-scalar-evolution.h. + (tree_ssa_cs_elim): Initialize the loop optimizer and SCEV. + * ipa-split.c: Include cfgloop.h. + (split_function): Add the new return block to the loop tree root. + * tree-cfgcleanup.c (remove_forwarder_block_with_phi): Return + whether we have removed the forwarder block. + (merge_phi_nodes): If we removed a forwarder mark loops for fixup. + * cfgloop.h (place_new_loop): Declare. + * cfgloopmanip.c (place_new_loop): Export. + * Makefile.in (asan.o): Add $(CFGLOOP_H) dependency. + (tree-switch-conversion.o): Likewise. + (tree-complex.o): Likewise. + (tree-inline.o): Likewise. + (tree-ssa-tailmerge.o): Likewise. + (ipa-split.o): Likewise. + (tree-ssa-phiopt.o): Add $(SCEV_H) dependency. + (tree-ssa-copy.o): Likewise. + * tree-switch-conversion.c: Include cfgloop.h + (process_switch): If we emit a bit-test cascade, schedule loops + for fixup. + * tree-complex.c: Include cfgloop.h. + (expand_complex_div_wide): Properly add new basic-blocks to loops. + * asan.c: Include cfgloop.h. + (create_cond_insert_point): Properly add new basic-blocks to + loops, schedule loop fixup. + * cfgloop.c (verify_loop_structure): Check that looks are not + marked for fixup. + * omp-low.c (expand_parallel_call): Properly add new basic-blocks + to loops. + (expand_omp_for_generic): Likewise. + (expand_omp_sections): Likewise. + (expand_omp_atomic_pipeline): Schedule loops for fixup. + * tree-ssa-copy.c: Include tree-scalar-evolution.h. + (fini_copy_prop): Disable DCE in substitute_and_fold if SCEV + is initialized, not when loops are present. + * tree-parloops.c (parallelize_loops): Remove checking here. + * passes.c (init_optimization_passes): Schedule a copy-propagation + pass before complete unrolling of inner loops. + 2013-04-26 Jakub Jelinek * Makefile.in (toplev.o): Depend on diagnostic-color.h. diff --git a/gcc/Makefile.in b/gcc/Makefile.in index f6fe9aa21b6..36b0062a2f6 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2225,7 +2225,7 @@ tree-dump.o: tree-dump.c $(CONFIG_H) $(SYSTEM_H) $(TM_H) $(TREE_H) \ tree-inline.o : tree-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) $(RTL_H) $(FLAGS_H) $(PARAMS_H) $(INPUT_H) insn-config.h \ $(HASHTAB_H) langhooks.h $(TREE_INLINE_H) $(CGRAPH_H) \ - intl.h $(FUNCTION_H) $(GIMPLE_H) \ + intl.h $(FUNCTION_H) $(GIMPLE_H) $(CFGLOOP_H) \ debug.h $(DIAGNOSTIC_H) $(EXCEPT_H) $(TREE_FLOW_H) tree-iterator.h tree-mudflap.h \ $(IPA_PROP_H) value-prof.h $(TREE_PASS_H) $(TARGET_H) \ $(TREE_PRETTY_PRINT_H) @@ -2237,7 +2237,7 @@ stor-layout.o : stor-layout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(GGC_H) $(TM_P_H) $(TARGET_H) langhooks.h $(REGS_H) gt-stor-layout.h \ $(DIAGNOSTIC_CORE_H) $(CGRAPH_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(GIMPLE_H) asan.o : asan.c asan.h $(CONFIG_H) $(SYSTEM_H) $(GIMPLE_H) \ - output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) \ + output.h coretypes.h $(GIMPLE_PRETTY_PRINT_H) $(CFGLOOP_H) \ tree-iterator.h $(TREE_FLOW_H) $(TREE_PASS_H) \ $(TARGET_H) $(EXPR_H) $(OPTABS_H) $(TM_P_H) langhooks.h \ $(HASH_TABLE_H) alloc-pool.h @@ -2250,7 +2250,7 @@ tsan.o : $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TREE_INLINE_H) \ tree-ssa-propagate.h tree-ssa-tail-merge.o: tree-ssa-tail-merge.c \ $(SYSTEM_H) $(CONFIG_H) coretypes.h $(TM_H) $(BITMAP_H) \ - $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) \ + $(FLAGS_H) $(TM_P_H) $(BASIC_BLOCK_H) $(CFGLOOP_H) \ $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) $(TREE_DUMP_H) $(HASH_TABLE_H) \ $(GIMPLE_H) $(FUNCTION_H) tree-ssa-sccvn.h \ $(CGRAPH_H) $(GIMPLE_PRETTY_PRINT_H) $(PARAMS_H) @@ -2314,14 +2314,14 @@ tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TREE_FLOW_H) $(TREE_PASS_H) langhooks.h $(FLAGS_H) \ $(DIAGNOSTIC_H) pointer-set.h domwalk.h $(CFGLOOP_H) \ $(TREE_DATA_REF_H) $(TREE_PRETTY_PRINT_H) $(GIMPLE_PRETTY_PRINT_H) \ - insn-config.h $(EXPR_H) $(OPTABS_H) + insn-config.h $(EXPR_H) $(OPTABS_H) $(SCEV_H) tree-nrv.o : tree-nrv.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TM_H) $(TREE_H) $(FUNCTION_H) $(BASIC_BLOCK_H) $(FLAGS_H) \ $(DIAGNOSTIC_H) $(TREE_FLOW_H) $(TREE_PASS_H) \ langhooks.h $(TREE_PRETTY_PRINT_H) tree-ssa-copy.o : tree-ssa-copy.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(GGC_H) $(DIAGNOSTIC_H) \ - $(FUNCTION_H) $(TM_H) coretypes.h \ + $(FUNCTION_H) $(TM_H) coretypes.h $(SCEV_H) \ $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h tree-ssa-propagate.h \ $(FLAGS_H) $(CFGLOOP_H) $(GIMPLE_PRETTY_PRINT_H) tree-ssa-propagate.o : tree-ssa-propagate.c $(TREE_FLOW_H) $(CONFIG_H) \ @@ -2929,7 +2929,7 @@ ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TREE_INLINE_H) $(PARAMS_H) $(TREE_PRETTY_PRINT_H) $(IPA_INLINE_H) ipa-split.o : ipa-split.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \ $(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \ - $(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \ + $(TREE_PASS_H) $(FLAGS_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) $(CFGLOOP_H) \ $(TREE_INLINE_H) $(PARAMS_H) $(GIMPLE_PRETTY_PRINT_H) $(IPA_INLINE_H) ipa-inline.o : ipa-inline.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(TREE_INLINE_H) $(FLAGS_H) $(CGRAPH_H) intl.h \ @@ -3058,13 +3058,13 @@ tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \ $(DBGCNT_H) $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H) tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \ $(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \ - $(TM_H) coretypes.h $(GIMPLE_H) \ + $(TM_H) coretypes.h $(GIMPLE_H) $(CFGLOOP_H) \ $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \ $(GGC_H) $(OBSTACK_H) $(PARAMS_H) $(CPPLIB_H) $(PARAMS_H) \ $(GIMPLE_PRETTY_PRINT_H) langhooks.h tree-complex.o : tree-complex.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ $(TM_H) $(FLAGS_H) $(TREE_FLOW_H) $(TREE_HASHER_H) $(GIMPLE_H) \ - tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h + $(CFGLOOP_H) tree-iterator.h $(TREE_PASS_H) tree-ssa-propagate.h tree-emutls.o : tree-emutls.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \ $(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H) $(CGRAPH_H) langhooks.h \ $(TARGET_H) $(TARGET_DEF_H) tree-iterator.h diff --git a/gcc/asan.c b/gcc/asan.c index b8acaf77008..c068b8ca0f4 100644 --- a/gcc/asan.c +++ b/gcc/asan.c @@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see #include "langhooks.h" #include "hash-table.h" #include "alloc-pool.h" +#include "cfgloop.h" /* AddressSanitizer finds out-of-bounds and use-after-free bugs with <2x slowdown on average. @@ -1220,6 +1221,11 @@ create_cond_insert_point (gimple_stmt_iterator *iter, basic_block cond_bb = e->src; basic_block fallthru_bb = e->dest; basic_block then_bb = create_empty_bb (cond_bb); + if (current_loops) + { + add_bb_to_loop (then_bb, cond_bb->loop_father); + loops_state_set (LOOPS_NEED_FIXUP); + } /* Set up the newly created 'then block'. */ e = make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); diff --git a/gcc/cfgloop.c b/gcc/cfgloop.c index 54ce2a24c21..568b7a2a13d 100644 --- a/gcc/cfgloop.c +++ b/gcc/cfgloop.c @@ -1329,6 +1329,12 @@ verify_loop_structure (void) bool dom_available = dom_info_available_p (CDI_DOMINATORS); sbitmap visited; + if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) + { + error ("loop verification on loop tree that needs fixup"); + err = 1; + } + /* We need up-to-date dominators, compute or verify them. */ if (!dom_available) calculate_dominance_info (CDI_DOMINATORS); diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 29ac6c44937..948e8056734 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -232,6 +232,7 @@ void rescan_loop_exit (edge, bool, bool); /* Loop data structure manipulation/querying. */ extern void flow_loop_tree_node_add (struct loop *, struct loop *); extern void flow_loop_tree_node_remove (struct loop *); +extern void place_new_loop (struct loop *); extern void add_loop (struct loop *, struct loop *); extern bool flow_loop_nested_p (const struct loop *, const struct loop *); extern bool flow_bb_inside_loop_p (const struct loop *, const_basic_block); diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c index 13efb7515f9..f2d6a3b7050 100644 --- a/gcc/cfgloopmanip.c +++ b/gcc/cfgloopmanip.c @@ -410,7 +410,7 @@ remove_path (edge e) /* Creates place for a new LOOP in loops structure. */ -static void +void place_new_loop (struct loop *loop) { loop->num = number_of_loops (); diff --git a/gcc/ipa-split.c b/gcc/ipa-split.c index e7d469d7442..107c7a90d95 100644 --- a/gcc/ipa-split.c +++ b/gcc/ipa-split.c @@ -90,6 +90,7 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "gimple-pretty-print.h" #include "ipa-inline.h" +#include "cfgloop.h" /* Per basic block info. */ @@ -1131,6 +1132,8 @@ split_function (struct split_point *split_point) e = make_edge (new_return_bb, EXIT_BLOCK_PTR, 0); e->probability = REG_BR_PROB_BASE; e->count = new_return_bb->count; + if (current_loops) + add_bb_to_loop (new_return_bb, current_loops->tree_root); bitmap_set_bit (split_point->split_bbs, new_return_bb->index); } /* When we pass around the value, use existing return block. */ diff --git a/gcc/loop-init.c b/gcc/loop-init.c index 92d621e273c..664ff29dd5b 100644 --- a/gcc/loop-init.c +++ b/gcc/loop-init.c @@ -91,16 +91,27 @@ loop_optimizer_init (unsigned flags) } else { + bool recorded_exits = loops_state_satisfies_p (LOOPS_HAVE_RECORDED_EXITS); + gcc_assert (cfun->curr_properties & PROP_loops); /* Ensure that the dominators are computed, like flow_loops_find does. */ calculate_dominance_info (CDI_DOMINATORS); + if (loops_state_satisfies_p (LOOPS_NEED_FIXUP)) + { + loops_state_clear (~0U); + fix_loop_structure (NULL); + } + #ifdef ENABLE_CHECKING - verify_loop_structure (); + else + verify_loop_structure (); #endif /* Clear all flags. */ + if (recorded_exits) + release_recorded_exits (); loops_state_clear (~0U); } diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index ad620c66d3b..afb73f2b5b1 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -733,8 +733,9 @@ output_struct_function_base (struct output_block *ob, struct function *fn) FOR_EACH_VEC_SAFE_ELT (fn->local_decls, i, t) stream_write_tree (ob, t, true); - /* Output current IL state of the function. */ - streamer_write_uhwi (ob, fn->curr_properties); + /* Output current IL state of the function. + ??? We don't stream loops. */ + streamer_write_uhwi (ob, fn->curr_properties & ~PROP_loops); /* Write all the attributes for FN. */ bp = bitpack_create (ob->main_stream); diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 3e519db79b6..eaeeaa5fe39 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -3056,6 +3056,11 @@ expand_parallel_call (struct omp_region *region, basic_block bb, make_edge (cond_bb, then_bb, EDGE_TRUE_VALUE); make_edge (cond_bb, else_bb, EDGE_FALSE_VALUE); + if (current_loops) + { + add_bb_to_loop (then_bb, cond_bb->loop_father); + add_bb_to_loop (else_bb, cond_bb->loop_father); + } e_then = make_edge (then_bb, bb, EDGE_FALLTHRU); e_else = make_edge (else_bb, bb, EDGE_FALLTHRU); @@ -4011,6 +4016,8 @@ expand_omp_for_generic (struct omp_region *region, tree vtype = TREE_TYPE (fd->loops[i].v); bb = create_empty_bb (last_bb); + if (current_loops) + add_bb_to_loop (bb, last_bb->loop_father); gsi = gsi_start_bb (bb); if (i < fd->collapse - 1) @@ -4114,6 +4121,8 @@ expand_omp_for_generic (struct omp_region *region, remove_edge (e); make_edge (cont_bb, l2_bb, EDGE_FALSE_VALUE); + if (current_loops) + add_bb_to_loop (l2_bb, cont_bb->loop_father); if (fd->collapse > 1) { e = find_edge (cont_bb, l1_bb); @@ -4902,6 +4911,8 @@ expand_omp_sections (struct omp_region *region) t = gimple_block_label (default_bb); u = build_case_label (NULL, NULL, t); make_edge (l0_bb, default_bb, 0); + if (current_loops) + add_bb_to_loop (default_bb, l0_bb->loop_father); stmt = gimple_build_switch (vmain, u, label_vec); gsi_insert_after (&switch_si, stmt, GSI_SAME_STMT); @@ -5438,6 +5449,10 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb, if (gimple_in_ssa_p (cfun)) update_ssa (TODO_update_ssa_no_phi); + /* ??? The above could use loop construction primitives. */ + if (current_loops) + loops_state_set (LOOPS_NEED_FIXUP); + return true; } diff --git a/gcc/passes.c b/gcc/passes.c index 45e79ccc166..fd67ee6128a 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1397,6 +1397,7 @@ init_optimization_passes (void) They ensure memory accesses are not indirect wherever possible. */ NEXT_PASS (pass_strip_predict_hints); NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_complete_unrolli); NEXT_PASS (pass_ccp); /* After CCP we rewrite no longer addressed locals into SSA diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5e568fb8dc3..737ef4a926f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2013-03-26 Richard Biener + + * gcc.dg/tree-prof/update-loopch.c: Revert last change. + * gcc.dg/graphite/pr33766.c: Fix undefined behavior. + * gcc.dg/pr53265.c: Remove XFAILs. + * gcc.dg/tree-ssa/loop-38.c: Remove unreliable dump scanning. + * gcc.dg/tree-ssa/pr21559.c: Change back to two expected jump threads. + 2013-04-26 Jakub Jelinek * lib/prune.exp: Add -fdiagnostics-color=never to TEST_ALWAYS_FLAGS. diff --git a/gcc/testsuite/gcc.dg/graphite/pr33766.c b/gcc/testsuite/gcc.dg/graphite/pr33766.c index f6bb50615a0..47d3dd40d67 100644 --- a/gcc/testsuite/gcc.dg/graphite/pr33766.c +++ b/gcc/testsuite/gcc.dg/graphite/pr33766.c @@ -4,16 +4,16 @@ float fxt1_quantize_ALPHA1() { - int j1; - int i; - float *tv; - for (j1 = 1; j1; j1++) { - float e; - for (i = 1; i; i++) - e = tv[i]; - if (e) - i = j1; - } - return tv[i]; + int j1; + int i; + float *tv; + for (j1 = 1; j1 < 2048; j1++) { + float e; + for (i = 1; i < 2048; i++) + e = tv[i]; + if (e) + i = j1; + } + return tv[i]; } diff --git a/gcc/testsuite/gcc.dg/pr53265.c b/gcc/testsuite/gcc.dg/pr53265.c index c60a736a927..70164466b10 100644 --- a/gcc/testsuite/gcc.dg/pr53265.c +++ b/gcc/testsuite/gcc.dg/pr53265.c @@ -49,9 +49,9 @@ fn4 (void) unsigned int *a[32], *o, i; bar (a); - for (i = 0; i <= sizeof (a) / sizeof (a[0]); i++) /* { dg-message "note: containing loop" "" { xfail *-*-* } } */ + for (i = 0; i <= sizeof (a) / sizeof (a[0]); i++) /* { dg-message "note: containing loop" "" } */ { - o = a[i]; /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */ + o = a[i]; /* { dg-warning "invokes undefined behavior" "" } */ bar (o); } } @@ -85,11 +85,11 @@ fn7 (void) { int a[16], b, c; bar (a); - for (b = a[c = 0]; c < 16; b = a[++c]) /* { dg-warning "invokes undefined behavior" "" { xfail *-*-* } } */ + for (b = a[c = 0]; c < 16; b = a[++c]) /* { dg-warning "invokes undefined behavior" "" } */ baz (b); } -/* { dg-message "note: containing loop" "" { xfail *-*-* } 88 } */ +/* { dg-message "note: containing loop" "" { target *-*-* } 88 } */ const void *va, *vb, *vc, *vd, *ve; const void *vf[4]; diff --git a/gcc/testsuite/gcc.dg/tree-prof/update-loopch.c b/gcc/testsuite/gcc.dg/tree-prof/update-loopch.c index e2656a30645..cc06ea7396b 100644 --- a/gcc/testsuite/gcc.dg/tree-prof/update-loopch.c +++ b/gcc/testsuite/gcc.dg/tree-prof/update-loopch.c @@ -14,7 +14,7 @@ main () /* Loop header copying will peel away the initial conditional, so the loop body is once reached directly from entry point of function, rest via loopback edge. */ -/* { dg-final-use { scan-ipa-dump "loop depth 0, count 33334" "profile"} } */ +/* { dg-final-use { scan-ipa-dump "loop depth 1, count 33334" "profile"} } */ /* { dg-final-use { scan-tree-dump "loop depth 1, count 33332" "optimized"} } */ /* { dg-final-use { scan-tree-dump-not "Invalid sum" "optimized"} } */ /* { dg-final-use { cleanup-ipa-dump "profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-38.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-38.c index 7f2303124ad..714696e87ad 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/loop-38.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-38.c @@ -13,6 +13,5 @@ t(int n) sum+=b[i]; return sum; } -/* { dg-final { scan-tree-dump "Found better loop bound 11" "cunrolli" } } */ /* { dg-final { scan-tree-dump "Loop 1 iterates at most 11 times" "cunrolli" } } */ /* { dg-final { cleanup-tree-dump "cunrolli" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c index 34f4a01db00..402c102d259 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -37,7 +37,7 @@ void foo (void) /* Second, we should thread the edge out of the loop via the break statement. We also realize that the final bytes == 0 test is useless, and thread over it. */ -/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 2 "vrp1" } } */ /* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c index c5c25a742bc..cbbc5c76bae 100644 --- a/gcc/tree-cfg.c +++ b/gcc/tree-cfg.c @@ -247,6 +247,8 @@ execute_build_cfg (void) fprintf (dump_file, "Scope blocks:\n"); dump_scope_blocks (dump_file, dump_flags); } + cleanup_tree_cfg (); + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); return 0; } @@ -263,10 +265,10 @@ struct gimple_opt_pass pass_build_cfg = 0, /* static_pass_number */ TV_TREE_CFG, /* tv_id */ PROP_gimple_leh, /* properties_required */ - PROP_cfg, /* properties_provided */ + PROP_cfg | PROP_loops, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_verify_stmts | TODO_cleanup_cfg /* todo_flags_finish */ + TODO_verify_stmts /* todo_flags_finish */ } }; @@ -6713,6 +6715,18 @@ move_sese_region_to_fn (struct function *dest_cfun, basic_block entry_bb, d.eh_map = eh_map; d.remap_decls_p = true; + /* Cancel all loops inside the SESE region. + ??? We rely on loop fixup because loop structure is not 100% + up-to-date when called from OMP lowering and thus cancel_loop_tree + will not work. + ??? Properly move loops to the outlined function. */ + FOR_EACH_VEC_ELT (bbs, i, bb) + if (bb->loop_father->header == bb) + { + bb->loop_father->header = NULL; + bb->loop_father->latch = NULL; + loops_state_set (LOOPS_NEED_FIXUP); + } FOR_EACH_VEC_ELT (bbs, i, bb) { /* No need to update edge counts on the last block. It has diff --git a/gcc/tree-cfgcleanup.c b/gcc/tree-cfgcleanup.c index b355a8607d5..3c69a7df23d 100644 --- a/gcc/tree-cfgcleanup.c +++ b/gcc/tree-cfgcleanup.c @@ -748,9 +748,10 @@ cleanup_tree_cfg (void) return changed; } -/* Merge the PHI nodes at BB into those at BB's sole successor. */ +/* Tries to merge the PHI nodes at BB into those at BB's sole successor. + Returns true if successful. */ -static void +static bool remove_forwarder_block_with_phi (basic_block bb) { edge succ = single_succ_edge (bb); @@ -762,7 +763,7 @@ remove_forwarder_block_with_phi (basic_block bb) However it may happen that the infinite loop is created afterwards due to removal of forwarders. */ if (dest == bb) - return; + return false; /* If the destination block consists of a nonlocal label, do not merge it. */ @@ -770,7 +771,7 @@ remove_forwarder_block_with_phi (basic_block bb) if (label && gimple_code (label) == GIMPLE_LABEL && DECL_NONLOCAL (gimple_label_label (label))) - return; + return false; /* Redirect each incoming edge to BB to DEST. */ while (EDGE_COUNT (bb->preds) > 0) @@ -859,6 +860,8 @@ remove_forwarder_block_with_phi (basic_block bb) /* Remove BB since all of BB's incoming edges have been redirected to DEST. */ delete_basic_block (bb); + + return true; } /* This pass merges PHI nodes if one feeds into another. For example, @@ -960,13 +963,20 @@ merge_phi_nodes (void) } /* Now let's drain WORKLIST. */ + bool changed = false; while (current != worklist) { bb = *--current; - remove_forwarder_block_with_phi (bb); + changed |= remove_forwarder_block_with_phi (bb); } - free (worklist); + + /* Removing forwarder blocks can cause formerly irreducible loops + to become reducible if we merged two entry blocks. */ + if (changed + && current_loops) + loops_state_set (LOOPS_NEED_FIXUP); + return 0; } diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c index ee545682f98..d43172be3bf 100644 --- a/gcc/tree-complex.c +++ b/gcc/tree-complex.c @@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-pass.h" #include "tree-ssa-propagate.h" #include "tree-hasher.h" +#include "cfgloop.h" /* For each complex ssa name, a lattice value. We're interested in finding @@ -1139,6 +1140,11 @@ expand_complex_div_wide (gimple_stmt_iterator *gsi, tree inner_type, make_edge (bb_cond, bb_false, EDGE_FALSE_VALUE); make_edge (bb_true, bb_join, EDGE_FALLTHRU); make_edge (bb_false, bb_join, EDGE_FALLTHRU); + if (current_loops) + { + add_bb_to_loop (bb_true, bb_cond->loop_father); + add_bb_to_loop (bb_false, bb_cond->loop_father); + } /* Update dominance info. Note that bb_join's data was updated by split_block. */ diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 7fa0245d16c..c358cbef2a7 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -47,6 +47,7 @@ along with GCC; see the file COPYING3. If not see #include "value-prof.h" #include "tree-pass.h" #include "target.h" +#include "cfgloop.h" #include "rtl.h" /* FIXME: For asm_str_count. */ @@ -2088,7 +2089,7 @@ initialize_cfun (tree new_fndecl, tree callee_fndecl, gcov_type count) cfun->static_chain_decl = src_cfun->static_chain_decl; cfun->nonlocal_goto_save_area = src_cfun->nonlocal_goto_save_area; cfun->function_end_locus = src_cfun->function_end_locus; - cfun->curr_properties = src_cfun->curr_properties & ~PROP_loops; + cfun->curr_properties = src_cfun->curr_properties; cfun->last_verified = src_cfun->last_verified; cfun->va_list_gpr_size = src_cfun->va_list_gpr_size; cfun->va_list_fpr_size = src_cfun->va_list_fpr_size; @@ -2193,6 +2194,45 @@ maybe_move_debug_stmts_to_successors (copy_body_data *id, basic_block new_bb) } } +/* Make a copy of the sub-loops of SRC_PARENT and place them + as siblings of DEST_PARENT. */ + +static void +copy_loops (bitmap blocks_to_copy, + struct loop *dest_parent, struct loop *src_parent) +{ + struct loop *src_loop = src_parent->inner; + while (src_loop) + { + if (!blocks_to_copy + || bitmap_bit_p (blocks_to_copy, src_loop->header->index)) + { + struct loop *dest_loop = alloc_loop (); + + /* Assign the new loop its header and latch and associate + those with the new loop. */ + dest_loop->header = (basic_block)src_loop->header->aux; + dest_loop->header->loop_father = dest_loop; + if (src_loop->latch != NULL) + { + dest_loop->latch = (basic_block)src_loop->latch->aux; + dest_loop->latch->loop_father = dest_loop; + } + + /* Copy loop meta-data. */ + copy_loop_info (src_loop, dest_loop); + + /* Finally place it into the loop array and the loop tree. */ + place_new_loop (dest_loop); + flow_loop_tree_node_add (dest_parent, dest_loop); + + /* Recurse. */ + copy_loops (blocks_to_copy, dest_loop, src_loop); + } + src_loop = src_loop->next; + } +} + /* Make a copy of the body of FN so that it can be inserted inline in another function. Walks FN via CFG, returns new fndecl. */ @@ -2270,6 +2310,7 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale, basic_block new_bb = copy_bb (id, bb, frequency_scale, count_scale); bb->aux = new_bb; new_bb->aux = bb; + new_bb->loop_father = entry_block_map->loop_father; } last = last_basic_block; @@ -2290,6 +2331,16 @@ copy_cfg_body (copy_body_data * id, gcov_type count, int frequency_scale, e->count = incoming_count; } + /* Duplicate the loop tree, if available and wanted. */ + if (id->src_cfun->x_current_loops != NULL + && current_loops != NULL) + { + copy_loops (blocks_to_copy, entry_block_map->loop_father, + id->src_cfun->x_current_loops->tree_root); + /* Defer to cfgcleanup to update loop-father fields of basic-blocks. */ + loops_state_set (LOOPS_NEED_FIXUP); + } + if (gimple_in_ssa_p (cfun)) FOR_ALL_BB_FN (bb, cfun_to_copy) if (!blocks_to_copy @@ -5147,6 +5198,14 @@ tree_function_versioning (tree old_decl, tree new_decl, } } + /* Set up the destination functions loop tree. */ + if (DECL_STRUCT_FUNCTION (old_decl)->x_current_loops) + { + cfun->curr_properties &= ~PROP_loops; + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + cfun->curr_properties |= PROP_loops; + } + /* Copy the Function's body. */ copy_body (&id, old_entry_block->count, REG_BR_PROB_BASE, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, blocks_to_copy, new_entry); diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index a72369eb59e..d399d8a98c6 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -204,6 +204,10 @@ execute_fixup_cfg (void) if (dump_file) gimple_dump_cfg (dump_file, dump_flags); + if (current_loops + && (todo & TODO_cleanup_cfg)) + loops_state_set (LOOPS_NEED_FIXUP); + return todo; } diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c index 088fc462970..4a4b02b161c 100644 --- a/gcc/tree-parloops.c +++ b/gcc/tree-parloops.c @@ -2216,11 +2216,6 @@ parallelize_loops (void) } gen_parallel_loop (loop, reduction_list, n_threads, &niter_desc); -#ifdef ENABLE_CHECKING - verify_flow_info (); - verify_loop_structure (); - verify_loop_closed_ssa (true); -#endif } free_stmt_vec_info_vec (); diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c index d16756cb79a..f58f7b3a0ec 100644 --- a/gcc/tree-ssa-copy.c +++ b/gcc/tree-ssa-copy.c @@ -32,6 +32,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-ssa-propagate.h" #include "langhooks.h" #include "cfgloop.h" +#include "tree-scalar-evolution.h" /* This file implements the copy propagation pass and provides a handful of interfaces for performing const/copy propagation and @@ -771,9 +772,8 @@ fini_copy_prop (void) duplicate_ssa_name_ptr_info (copy_of[i].value, SSA_NAME_PTR_INFO (var)); } - /* Don't do DCE if we have loops. That's the simplest way to not - destroy the scev cache. */ - substitute_and_fold (get_value, NULL, !current_loops); + /* Don't do DCE if SCEV is initialized. It would destroy the scev cache. */ + substitute_and_fold (get_value, NULL, !scev_initialized_p ()); free (copy_of); } diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index fef6883a13d..ae5b500d1ca 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -93,7 +93,7 @@ struct gimple_opt_pass pass_tree_loop_init = 0, /* static_pass_number */ TV_NONE, /* tv_id */ PROP_cfg, /* properties_required */ - PROP_loops, /* properties_provided */ + 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ 0 /* todo_flags_finish */ @@ -577,7 +577,7 @@ struct gimple_opt_pass pass_parallelize_loops = 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ + TODO_verify_flow /* todo_flags_finish */ } }; diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c index 739e48e432b..5e99678ac01 100644 --- a/gcc/tree-ssa-phiopt.c +++ b/gcc/tree-ssa-phiopt.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "insn-config.h" #include "expr.h" #include "optabs.h" +#include "tree-scalar-evolution.h" #ifndef HAVE_conditional_move #define HAVE_conditional_move (0) @@ -242,7 +243,16 @@ tree_ssa_phiopt (void) static unsigned int tree_ssa_cs_elim (void) { - return tree_ssa_phiopt_worker (true, false); + unsigned todo; + /* ??? We are not interested in loop related info, but the following + will create it, ICEing as we didn't init loops with pre-headers. + An interfacing issue of find_data_references_in_bb. */ + loop_optimizer_init (LOOPS_NORMAL); + scev_initialize (); + todo = tree_ssa_phiopt_worker (true, false); + scev_finalize (); + loop_optimizer_finalize (); + return todo; } /* Return the singleton PHI in the SEQ of PHIs for edges E0 and E1. */ diff --git a/gcc/tree-ssa-tail-merge.c b/gcc/tree-ssa-tail-merge.c index b20d3067d66..f2ab744403a 100644 --- a/gcc/tree-ssa-tail-merge.c +++ b/gcc/tree-ssa-tail-merge.c @@ -197,6 +197,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "tree-ssa-sccvn.h" #include "tree-dump.h" +#include "cfgloop.h" /* ??? This currently runs as part of tree-ssa-pre. Why is this not a stand-alone GIMPLE pass? */ @@ -1459,6 +1460,17 @@ replace_block_by (basic_block bb1, basic_block bb2) /* Mark the basic block as deleted. */ mark_basic_block_deleted (bb1); + /* ??? If we merge the loop preheader with the loop latch we are creating + additional entries into the loop, eventually rotating it. + Mark loops for fixup in this case. + ??? This is a completely unwanted transform and will wreck most + loops at this point - but with just not considering loop latches as + merge candidates we fail to commonize the two loops in gcc.dg/pr50763.c. + A better fix to avoid that regression is needed. */ + if (current_loops + && bb2->loop_father->latch == bb2) + loops_state_set (LOOPS_NEED_FIXUP); + /* Redirect the incoming edges of bb1 to bb2. */ for (i = EDGE_COUNT (bb1->preds); i > 0 ; --i) { diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 3fffdf7e6cd..9ad7daf0689 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -36,6 +36,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tree-ssa-operands.h" #include "tree-pass.h" #include "gimple-pretty-print.h" +#include "cfgloop.h" /* ??? For lang_hooks.types.type_for_mode, but is there a word_mode type in the GIMPLE type system that is language-independent? */ @@ -1351,6 +1352,8 @@ process_switch (gimple swtch) fputs (" expanding as bit test is preferable\n", dump_file); emit_case_bit_tests (swtch, info.index_expr, info.range_min, info.range_size); + if (current_loops) + loops_state_set (LOOPS_NEED_FIXUP); return NULL; } -- 2.11.4.GIT