* 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
+2013-03-26 Richard Biener <rguenther@suse.de>
+
+ * 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 <jakub@redhat.com>
* Makefile.in (toplev.o): Depend on diagnostic-color.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)
$(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
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)
$(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) \
$(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 \
$(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
#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.
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);
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);
/* 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);
/* Creates place for a new LOOP in loops structure. */
-static void
+void
place_new_loop (struct loop *loop)
{
loop->num = number_of_loops ();
#include "params.h"
#include "gimple-pretty-print.h"
#include "ipa-inline.h"
+#include "cfgloop.h"
/* Per basic block info. */
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. */
}
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);
}
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);
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);
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)
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);
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);
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;
}
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
+2013-03-26 Richard Biener <rguenther@suse.de>
+
+ * 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 <jakub@redhat.com>
* lib/prune.exp: Add -fdiagnostics-color=never to TEST_ALWAYS_FLAGS.
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];
}
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);
}
}
{
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];
/* 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" } } */
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" } } */
/* 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" } } */
fprintf (dump_file, "Scope blocks:\n");
dump_scope_blocks (dump_file, dump_flags);
}
+ cleanup_tree_cfg ();
+ loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
return 0;
}
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 */
}
};
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
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);
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. */
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)
/* 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,
}
/* 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;
}
#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
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. */
#include "value-prof.h"
#include "tree-pass.h"
#include "target.h"
+#include "cfgloop.h"
#include "rtl.h" /* FIXME: For asm_str_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;
}
}
+/* 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. */
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;
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
}
}
+ /* 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);
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;
}
}
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 ();
#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
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);
}
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 */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- 0 /* todo_flags_finish */
+ TODO_verify_flow /* todo_flags_finish */
}
};
#include "insn-config.h"
#include "expr.h"
#include "optabs.h"
+#include "tree-scalar-evolution.h"
#ifndef HAVE_conditional_move
#define HAVE_conditional_move (0)
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. */
#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? */
/* 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)
{
#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? */
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;
}