summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/Makefile.in63
-rw-r--r--gcc/bb-reorder.c1
-rw-r--r--gcc/cfgcleanup.c2
-rw-r--r--gcc/cfghooks.c121
-rw-r--r--gcc/cfghooks.h12
-rw-r--r--gcc/cfglayout.c1498
-rw-r--r--gcc/cfglayout.h38
-rw-r--r--gcc/cfgloopmanip.c2
-rw-r--r--gcc/cfgrtl.c983
-rw-r--r--gcc/config/alpha/alpha.c1
-rw-r--r--gcc/config/bfin/bfin.c1
-rw-r--r--gcc/config/c6x/c6x.c1
-rw-r--r--gcc/config/ia64/ia64.c1
-rw-r--r--gcc/config/mips/mips.c1
-rw-r--r--gcc/config/rs6000/rs6000.c1
-rw-r--r--gcc/config/rs6000/t-rs60002
-rw-r--r--gcc/config/score/score.c1
-rw-r--r--gcc/config/sh/sh.c1
-rw-r--r--gcc/config/sparc/sparc.c1
-rw-r--r--gcc/config/sparc/t-sparc2
-rw-r--r--gcc/config/spu/spu.c1
-rw-r--r--gcc/config/spu/t-spu-elf2
-rw-r--r--gcc/ddg.c1
-rw-r--r--gcc/dwarf2out.c1
-rw-r--r--gcc/emit-rtl.c256
-rw-r--r--gcc/final.c109
-rw-r--r--gcc/function.c5
-rw-r--r--gcc/function.h4
-rw-r--r--gcc/gengtype.c2
-rw-r--r--gcc/hw-doloop.c1
-rw-r--r--gcc/loop-init.c1
-rw-r--r--gcc/loop-unroll.c1
-rw-r--r--gcc/loop-unswitch.c1
-rw-r--r--gcc/modulo-sched.c2
-rw-r--r--gcc/profile.c1
-rw-r--r--gcc/rtl.h5
-rw-r--r--gcc/sched-ebb.c1
-rw-r--r--gcc/sched-rgn.c1
-rw-r--r--gcc/tracer.c1
-rw-r--r--gcc/tree-cfg.c1
-rw-r--r--gcc/tree-flow.h5
-rw-r--r--gcc/tree-vect-loop-manip.c1
-rw-r--r--gcc/tree.h6
43 files changed, 1499 insertions, 1643 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 0a0e8f1c249..156a6b1f668 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -896,7 +896,6 @@ SCHED_INT_H = sched-int.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) $(DF_H) \
SEL_SCHED_IR_H = sel-sched-ir.h $(INSN_ATTR_H) $(BASIC_BLOCK_H) $(RTL_H) \
$(GGC_H) $(BITMAP_H) vecprim.h $(SCHED_INT_H) $(CFGLOOP_H) $(REGSET_H)
SEL_SCHED_DUMP_H = sel-sched-dump.h $(SEL_SCHED_IR_H)
-CFGLAYOUT_H = cfglayout.h $(BASIC_BLOCK_H)
CFGLOOP_H = cfgloop.h $(BASIC_BLOCK_H) vecprim.h double-int.h \
$(BITMAP_H) sbitmap.h
IPA_UTILS_H = ipa-utils.h $(TREE_H) $(CGRAPH_H)
@@ -1186,7 +1185,6 @@ OBJS = \
cfgcleanup.o \
cfgexpand.o \
cfghooks.o \
- cfglayout.o \
cfgloop.o \
cfgloopanal.o \
cfgloopmanip.o \
@@ -2172,7 +2170,7 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(INPUT_H) $(TREE_H) $(RTL_H) $(FUNCTION_H) insn-config.h $(EXPR_H) \
hard-reg-set.h $(BASIC_BLOCK_H) cselib.h $(INSN_ADDR_H) $(OPTABS_H) \
$(LIBFUNCS_H) debug.h $(GGC_H) $(CGRAPH_H) $(TREE_FLOW_H) reload.h \
- $(CPP_ID_DATA_H) tree-chrec.h $(CFGLAYOUT_H) $(EXCEPT_H) output.h \
+ $(CPP_ID_DATA_H) tree-chrec.h $(EXCEPT_H) output.h \
$(CFGLOOP_H) $(TARGET_H) $(IPA_PROP_H) $(LTO_STREAMER_H) \
target-globals.h
@@ -2443,7 +2441,7 @@ tree-cfg.o : tree-cfg.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(TM_P_H) $(GGC_H) $(FLAGS_H) \
$(DIAGNOSTIC_CORE_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) $(EXCEPT_H) langhooks.h $(CFGLOOP_H) $(TREE_PASS_H) \
- $(CFGLAYOUT_H) $(BASIC_BLOCK_H) \
+ $(BASIC_BLOCK_H) \
value-prof.h tree-ssa-propagate.h $(TREE_INLINE_H) $(GIMPLE_PRETTY_PRINT_H)
tree-cfgcleanup.o : tree-cfgcleanup.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(TM_P_H) $(GGC_H) $(FLAGS_H) \
@@ -2652,7 +2650,7 @@ tree-vect-loop.o: tree-vect-loop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(GIMPLE_PRETTY_PRINT_H) $(TARGET_H) $(TREE_DATA_REF_H)
tree-vect-loop-manip.o: tree-vect-loop-manip.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(GGC_H) $(TREE_H) $(BASIC_BLOCK_H) \
- $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(CFGLAYOUT_H) $(DIAGNOSTIC_CORE_H) \
+ $(TREE_FLOW_H) $(TREE_DUMP_H) $(CFGLOOP_H) $(DIAGNOSTIC_CORE_H) \
$(SCEV_H) $(TREE_VECTORIZER_H) langhooks.h $(GIMPLE_PRETTY_PRINT_H)
tree-vect-patterns.o: tree-vect-patterns.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(GGC_H) $(TREE_H) $(TARGET_H) $(BASIC_BLOCK_H) \
@@ -2756,7 +2754,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(RECOG_H) Makefile toplev.h $(DWARF2OUT_H) sdbout.h dbxout.h $(EXPR_H) \
hard-reg-set.h $(BASIC_BLOCK_H) graph.h $(EXCEPT_H) $(REGS_H) $(TIMEVAR_H) \
value-prof.h $(PARAMS_H) $(TM_P_H) reload.h ira.h dwarf2asm.h $(TARGET_H) \
- langhooks.h insn-flags.h $(CFGLAYOUT_H) $(CFGLOOP_H) hosthooks.h \
+ langhooks.h insn-flags.h $(CFGLOOP_H) hosthooks.h \
$(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) \
$(OPTS_H) params.def tree-mudflap.h $(TREE_PASS_H) $(GIMPLE_H) \
tree-ssa-alias.h $(PLUGIN_H) realmpfr.h tree-diagnostic.h \
@@ -2807,7 +2805,7 @@ varasm.o : varasm.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(CGRAPH_H) $(TARGET_DEF_H) tree-mudflap.h \
pointer-set.h $(COMMON_TARGET_H)
function.o : function.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
- $(TREE_H) $(CFGLAYOUT_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
+ $(TREE_H) $(GIMPLE_H) $(FLAGS_H) $(FUNCTION_H) $(EXPR_H) \
$(OPTABS_H) $(LIBFUNCS_H) $(REGS_H) hard-reg-set.h insn-config.h $(RECOG_H) \
output.h $(EXCEPT_H) $(HASHTAB_H) $(GGC_H) $(TM_P_H) langhooks.h \
gt-function.h $(TARGET_H) $(BASIC_BLOCK_H) $(PREDICT_H) \
@@ -2880,7 +2878,7 @@ dwarf2out.o : dwarf2out.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(LIBFUNCS_H) toplev.h $(DIAGNOSTIC_CORE_H) $(DWARF2OUT_H) reload.h \
$(GGC_H) $(EXCEPT_H) dwarf2asm.h $(TM_P_H) langhooks.h $(HASHTAB_H) \
gt-dwarf2out.h $(TARGET_H) $(CGRAPH_H) $(MD5_H) $(INPUT_H) $(FUNCTION_H) \
- $(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H) $(CFGLAYOUT_H) \
+ $(GIMPLE_H) $(TREE_PASS_H) $(TREE_FLOW_H) \
$(TREE_PRETTY_PRINT_H) $(COMMON_TARGET_H) $(OPTS_H)
dwarf2cfi.o : dwarf2cfi.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
version.h $(RTL_H) $(EXPR_H) $(REGS_H) $(FUNCTION_H) output.h \
@@ -2897,10 +2895,10 @@ xcoffout.o : xcoffout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
godump.o : godump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(DIAGNOSTIC_CORE_H) \
$(TREE_H) $(GGC_H) pointer-set.h $(OBSTACK_H) debug.h gt-godump.h
emit-rtl.o : emit-rtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) \
+ $(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) insn-config.h $(RECOG_H) vecprim.h \
$(GGC_H) $(EXPR_H) hard-reg-set.h $(BITMAP_H) $(DIAGNOSTIC_CORE_H) $(BASIC_BLOCK_H) \
$(HASHTAB_H) $(TM_P_H) debug.h langhooks.h $(TREE_PASS_H) gt-emit-rtl.h \
- $(DF_H) $(PARAMS_H) $(TARGET_H) $(TREE_FLOW_H)
+ $(DF_H) $(PARAMS_H) $(TARGET_H)
real.o : real.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(DIAGNOSTIC_CORE_H) $(TM_P_H) $(REAL_H) dfp.h realmpfr.h
realmpfr.o : realmpfr.c realmpfr.h $(CONFIG_H) $(SYSTEM_H) $(REAL_H) $(TREE_H)
@@ -3135,7 +3133,7 @@ var-tracking.o : var-tracking.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
pointer-set.h $(RECOG_H) $(TM_P_H) $(TREE_PRETTY_PRINT_H) $(ALIAS_H)
profile.o : profile.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(REGS_H) $(EXPR_H) $(FUNCTION_H) $(BASIC_BLOCK_H) \
- $(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h cfghooks.h \
+ $(DIAGNOSTIC_CORE_H) $(COVERAGE_H) $(TREE_FLOW_H) value-prof.h \
$(CFGLOOP_H) $(TIMEVAR_H) $(TREE_PASS_H) profile.h
mcf.o : mcf.c profile.h $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h \
$(BASIC_BLOCK_H) langhooks.h $(GCOV_IO_H) $(TREE_H)
@@ -3174,8 +3172,8 @@ cfgrtl.o : cfgrtl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
$(FLAGS_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
$(FUNCTION_H) $(EXCEPT_H) $(TM_P_H) $(INSN_ATTR_H) \
insn-config.h $(EXPR_H) \
- $(CFGLAYOUT_H) $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
- $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H)
+ $(CFGLOOP_H) $(OBSTACK_H) $(TARGET_H) $(TREE_H) \
+ $(TREE_PASS_H) $(DF_H) $(GGC_H) $(COMMON_TARGET_H) gt-cfgrtl.h
cfganal.o : cfganal.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(BASIC_BLOCK_H) hard-reg-set.h insn-config.h $(RECOG_H) $(TM_P_H) \
$(TIMEVAR_H) $(OBSTACK_H) $(DIAGNOSTIC_CORE_H) vecprim.h sbitmap.h \
@@ -3186,7 +3184,7 @@ cfgbuild.o : cfgbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
cfgcleanup.o : cfgcleanup.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(TIMEVAR_H) hard-reg-set.h $(FLAGS_H) $(RECOG_H) \
$(DIAGNOSTIC_CORE_H) insn-config.h cselib.h $(TARGET_H) $(TM_P_H) $(PARAMS_H) \
- $(REGS_H) $(EMIT_RTL_H) $(CFGLAYOUT_H) $(TREE_PASS_H) $(CFGLOOP_H) $(EXPR_H) \
+ $(REGS_H) $(EMIT_RTL_H) $(FUNCTION_H) $(TREE_PASS_H) $(CFGLOOP_H) $(EXPR_H) \
$(DF_H) $(DBGCNT_H) dce.h
cfgloop.o : cfgloop.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) coretypes.h $(TM_H) \
$(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(FLAGS_H) $(FUNCTION_H) \
@@ -3205,17 +3203,17 @@ loop-invariant.o : loop-invariant.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
coretypes.h $(TM_H) $(TM_P_H) $(FUNCTION_H) $(FLAGS_H) $(DF_H) \
$(OBSTACK_H) $(HASHTAB_H) $(EXCEPT_H) $(PARAMS_H) $(REGS_H) ira.h
cfgloopmanip.o : cfgloopmanip.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) \
- coretypes.h $(TM_H) cfghooks.h $(OBSTACK_H) $(TREE_FLOW_H)
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) \
+ coretypes.h $(TM_H) $(OBSTACK_H) $(TREE_FLOW_H)
loop-init.o : loop-init.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(GGC_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) \
coretypes.h $(TM_H) $(OBSTACK_H) $(TREE_PASS_H) $(TIMEVAR_H) $(FLAGS_H) \
$(DF_H)
loop-unswitch.o : loop-unswitch.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(PARAMS_H) \
$(EXPR_H) coretypes.h $(TM_H) $(OBSTACK_H)
loop-unroll.o: loop-unroll.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TM_H) \
- $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(CFGLAYOUT_H) $(PARAMS_H) \
+ $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLOOP_H) $(PARAMS_H) \
$(EXPR_H) coretypes.h $(TM_H) $(HASHTAB_H) $(RECOG_H) \
$(OBSTACK_H)
dominance.o : dominance.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
@@ -3328,13 +3326,13 @@ compare-elim.o : compare-elim.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ddg.o : ddg.c $(DDG_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) \
$(DIAGNOSTIC_CORE_H) $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
$(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
- $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(BITMAP_H) \
+ $(SCHED_INT_H) $(CFGLOOP_H) $(EXPR_H) $(BITMAP_H) \
hard-reg-set.h sbitmap.h $(TM_H)
modulo-sched.o : modulo-sched.c $(DDG_H) $(CONFIG_H) $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TARGET_H) $(DIAGNOSTIC_CORE_H) $(RTL_H) $(TM_P_H) $(REGS_H) $(FUNCTION_H) \
$(FLAGS_H) insn-config.h $(INSN_ATTR_H) $(EXCEPT_H) $(RECOG_H) \
- $(SCHED_INT_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
- cfghooks.h $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) \
+ $(SCHED_INT_H) $(CFGLOOP_H) $(EXPR_H) $(PARAMS_H) \
+ $(GCOV_IO_H) hard-reg-set.h $(TM_H) $(TIMEVAR_H) $(TREE_PASS_H) \
$(DF_H) $(DBGCNT_H)
haifa-sched.o : haifa-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h $(FUNCTION_H) \
@@ -3348,12 +3346,12 @@ sched-deps.o : sched-deps.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
sched-rgn.o : sched-rgn.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
$(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) sel-sched.h $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) $(TREE_PASS_H) \
+ $(TM_P_H) sel-sched.h $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) \
$(DBGCNT_H)
sched-ebb.o : sched-ebb.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(SCHED_INT_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
$(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(TM_P_H) \
- $(PARAMS_H) $(CFGLAYOUT_H) $(TARGET_H)
+ $(PARAMS_H) $(TARGET_H)
sched-vis.o : sched-vis.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(SCHED_INT_H) hard-reg-set.h $(BASIC_BLOCK_H) $(OBSTACK_H) \
$(TREE_PASS_H) $(INSN_ATTR_H)
@@ -3366,7 +3364,7 @@ sel-sched.o : sel-sched.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
sel-sched-dump.o : sel-sched-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) insn-config.h \
$(FUNCTION_H) $(INSN_ATTR_H) $(DIAGNOSTIC_CORE_H) $(RECOG_H) $(EXCEPT_H) $(PARAMS_H) \
- $(TM_P_H) $(TARGET_H) $(CFGLAYOUT_H) $(TIMEVAR_H) $(TREE_PASS_H) \
+ $(TM_P_H) $(TARGET_H) $(TIMEVAR_H) $(TREE_PASS_H) \
$(SEL_SCHED_DUMP_H) $(GGC_H) $(TREE_H) $(LANGHOOKS_DEF_H) $(SEL_SCHED_IR_H) \
$(BASIC_BLOCK_H) cselib.h
sel-sched-ir.o : sel-sched-ir.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
@@ -3380,7 +3378,7 @@ final.o : final.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
insn-config.h $(INSN_ATTR_H) $(FUNCTION_H) output.h hard-reg-set.h \
$(EXCEPT_H) debug.h xcoffout.h toplev.h $(DIAGNOSTIC_CORE_H) reload.h $(DWARF2OUT_H) \
$(TREE_PASS_H) $(BASIC_BLOCK_H) $(TM_P_H) $(TARGET_H) $(EXPR_H) \
- $(CFGLAYOUT_H) dbxout.h $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) \
+ dbxout.h $(TIMEVAR_H) $(CGRAPH_H) $(COVERAGE_H) \
$(DF_H) vecprim.h $(GGC_H) $(CFGLOOP_H) $(PARAMS_H) $(TREE_FLOW_H) \
$(TARGET_DEF_H) $(TREE_PRETTY_PRINT_H)
recog.o : recog.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_ERROR_H) \
@@ -3403,19 +3401,14 @@ predict.o: predict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
lists.o: lists.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(DIAGNOSTIC_CORE_H) \
$(RTL_H) $(GGC_H) gt-lists.h
bb-reorder.o : bb-reorder.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(CFGLAYOUT_H) $(FIBHEAP_H) \
+ $(RTL_H) $(FLAGS_H) $(TIMEVAR_H) output.h $(FIBHEAP_H) \
$(TARGET_H) $(FUNCTION_H) $(TM_P_H) $(OBSTACK_H) $(EXPR_H) $(REGS_H) \
$(PARAMS_H) toplev.h $(DIAGNOSTIC_CORE_H) $(TREE_PASS_H) $(DF_H) \
$(EXCEPT_H) bb-reorder.h
tracer.o : tracer.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
- $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h $(CFGLAYOUT_H) \
+ $(TREE_H) $(BASIC_BLOCK_H) hard-reg-set.h \
$(FLAGS_H) $(TIMEVAR_H) $(PARAMS_H) $(COVERAGE_H) $(FIBHEAP_H) \
$(TREE_PASS_H) $(TREE_FLOW_H) $(TREE_INLINE_H) $(CFGLOOP_H)
-cfglayout.o : cfglayout.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(RTL_H) $(TREE_H) insn-config.h $(BASIC_BLOCK_H) hard-reg-set.h \
- $(FUNCTION_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(TARGET_H) gt-cfglayout.h \
- $(GGC_H) alloc-pool.h $(FLAGS_H) $(OBSTACK_H) $(TREE_PASS_H) vecprim.h \
- $(DF_H) $(EMIT_RTL_H) $(COMMON_TARGET_H)
timevar.o : timevar.c $(CONFIG_H) $(SYSTEM_H) $(TIMEVAR_H)
regcprop.o : regcprop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) insn-config.h $(BASIC_BLOCK_H) $(REGS_H) hard-reg-set.h \
@@ -3451,7 +3444,7 @@ target-globals.o : target-globals.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
lower-subreg.h
hw-doloop.o : hw-doloop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) $(FLAGS_H) $(EXPR_H) hard-reg-set.h $(BASIC_BLOCK_H) $(TM_P_H) \
- $(DF_H) $(CFGLAYOUT_H) $(CFGLOOP_H) $(RECOG_H) $(TARGET_H) \
+ $(DF_H) $(CFGLOOP_H) $(RECOG_H) $(TARGET_H) \
$(REGS_H) hw-doloop.h
$(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
$(RTL_H) $(REGS_H) hard-reg-set.h insn-config.h conditions.h \
@@ -3741,7 +3734,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
$(srcdir)/gcse.c $(srcdir)/godump.c \
$(srcdir)/lists.c $(srcdir)/optabs.c \
$(srcdir)/profile.c $(srcdir)/mcf.c \
- $(srcdir)/reg-stack.c $(srcdir)/cfglayout.c $(srcdir)/cfglayout.h \
+ $(srcdir)/reg-stack.c $(srcdir)/cfgrtl.c \
$(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
$(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
$(srcdir)/gimple.h $(srcdir)/gimple.c \
diff --git a/gcc/bb-reorder.c b/gcc/bb-reorder.c
index 89431cc32c0..143bdd0c168 100644
--- a/gcc/bb-reorder.c
+++ b/gcc/bb-reorder.c
@@ -74,7 +74,6 @@
#include "flags.h"
#include "timevar.h"
#include "output.h"
-#include "cfglayout.h"
#include "fibheap.h"
#include "target.h"
#include "function.h"
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 1aa4cbb7eae..909d3462d74 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -47,7 +47,7 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "tm_p.h"
#include "target.h"
-#include "cfglayout.h"
+#include "function.h" /* For inline functions in emit-rtl.h they need crtl. */
#include "emit-rtl.h"
#include "tree-pass.h"
#include "cfgloop.h"
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index bc1b7a2f582..5b49d64f090 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -1161,3 +1161,124 @@ lv_add_condition_to_bb (basic_block first, basic_block second,
gcc_assert (cfg_hooks->lv_add_condition_to_bb);
cfg_hooks->lv_add_condition_to_bb (first, second, new_block, cond);
}
+
+/* Checks whether all N blocks in BBS array can be copied. */
+bool
+can_copy_bbs_p (basic_block *bbs, unsigned n)
+{
+ unsigned i;
+ edge e;
+ int ret = true;
+
+ for (i = 0; i < n; i++)
+ bbs[i]->flags |= BB_DUPLICATED;
+
+ for (i = 0; i < n; i++)
+ {
+ /* In case we should redirect abnormal edge during duplication, fail. */
+ edge_iterator ei;
+ FOR_EACH_EDGE (e, ei, bbs[i]->succs)
+ if ((e->flags & EDGE_ABNORMAL)
+ && (e->dest->flags & BB_DUPLICATED))
+ {
+ ret = false;
+ goto end;
+ }
+
+ if (!can_duplicate_block_p (bbs[i]))
+ {
+ ret = false;
+ break;
+ }
+ }
+
+end:
+ for (i = 0; i < n; i++)
+ bbs[i]->flags &= ~BB_DUPLICATED;
+
+ return ret;
+}
+
+/* Duplicates N basic blocks stored in array BBS. Newly created basic blocks
+ are placed into array NEW_BBS in the same order. Edges from basic blocks
+ in BBS are also duplicated and copies of those of them
+ that lead into BBS are redirected to appropriate newly created block. The
+ function assigns bbs into loops (copy of basic block bb is assigned to
+ bb->loop_father->copy loop, so this must be set up correctly in advance)
+ and updates dominators locally (LOOPS structure that contains the information
+ about dominators is passed to enable this).
+
+ BASE is the superloop to that basic block belongs; if its header or latch
+ is copied, we do not set the new blocks as header or latch.
+
+ Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
+ also in the same order.
+
+ Newly created basic blocks are put after the basic block AFTER in the
+ instruction stream, and the order of the blocks in BBS array is preserved. */
+
+void
+copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
+ edge *edges, unsigned num_edges, edge *new_edges,
+ struct loop *base, basic_block after)
+{
+ unsigned i, j;
+ basic_block bb, new_bb, dom_bb;
+ edge e;
+
+ /* Duplicate bbs, update dominators, assign bbs to loops. */
+ for (i = 0; i < n; i++)
+ {
+ /* Duplicate. */
+ bb = bbs[i];
+ new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
+ after = new_bb;
+ bb->flags |= BB_DUPLICATED;
+ /* Possibly set loop header. */
+ if (bb->loop_father->header == bb && bb->loop_father != base)
+ new_bb->loop_father->header = new_bb;
+ /* Or latch. */
+ if (bb->loop_father->latch == bb && bb->loop_father != base)
+ new_bb->loop_father->latch = new_bb;
+ }
+
+ /* Set dominators. */
+ for (i = 0; i < n; i++)
+ {
+ bb = bbs[i];
+ new_bb = new_bbs[i];
+
+ dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
+ if (dom_bb->flags & BB_DUPLICATED)
+ {
+ dom_bb = get_bb_copy (dom_bb);
+ set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb);
+ }
+ }
+
+ /* Redirect edges. */
+ for (j = 0; j < num_edges; j++)
+ new_edges[j] = NULL;
+ for (i = 0; i < n; i++)
+ {
+ edge_iterator ei;
+ new_bb = new_bbs[i];
+ bb = bbs[i];
+
+ FOR_EACH_EDGE (e, ei, new_bb->succs)
+ {
+ for (j = 0; j < num_edges; j++)
+ if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
+ new_edges[j] = e;
+
+ if (!(e->dest->flags & BB_DUPLICATED))
+ continue;
+ redirect_edge_and_branch_force (e, get_bb_copy (e->dest));
+ }
+ }
+
+ /* Clear information about duplicates. */
+ for (i = 0; i < n; i++)
+ bbs[i]->flags &= ~BB_DUPLICATED;
+}
+
diff --git a/gcc/cfghooks.h b/gcc/cfghooks.h
index 9fd81acb0d3..adf6a893b00 100644
--- a/gcc/cfghooks.h
+++ b/gcc/cfghooks.h
@@ -19,8 +19,7 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-#ifndef GCC_CFGHOOKS_H
-#define GCC_CFGHOOKS_H
+/* Only basic-block.h includes this. */
struct cfg_hooks
{
@@ -185,6 +184,14 @@ extern void lv_adjust_loop_header_phi (basic_block, basic_block, basic_block,
extern void lv_add_condition_to_bb (basic_block, basic_block, basic_block,
void *);
+extern bool can_copy_bbs_p (basic_block *, unsigned);
+extern void copy_bbs (basic_block *, unsigned, basic_block *,
+ edge *, unsigned, edge *, struct loop *,
+ basic_block);
+
+extern void cfg_layout_initialize (unsigned int);
+extern void cfg_layout_finalize (void);
+
/* Hooks containers. */
extern struct cfg_hooks gimple_cfg_hooks;
extern struct cfg_hooks rtl_cfg_hooks;
@@ -198,4 +205,3 @@ extern void gimple_register_cfg_hooks (void);
extern struct cfg_hooks get_cfg_hooks (void);
extern void set_cfg_hooks (struct cfg_hooks);
-#endif /* GCC_CFGHOOKS_H */
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
deleted file mode 100644
index 3ab0ec0a138..00000000000
--- a/gcc/cfglayout.c
+++ /dev/null
@@ -1,1498 +0,0 @@
-/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000, 2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
- 2011 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-#include "config.h"
-#include "system.h"
-#include "coretypes.h"
-#include "tm.h"
-#include "tree.h"
-#include "rtl.h"
-#include "hard-reg-set.h"
-#include "obstack.h"
-#include "basic-block.h"
-#include "insn-config.h"
-#include "function.h"
-#include "cfglayout.h"
-#include "cfgloop.h"
-#include "target.h"
-#include "common/common-target.h"
-#include "ggc.h"
-#include "alloc-pool.h"
-#include "flags.h"
-#include "tree-pass.h"
-#include "df.h"
-#include "vecprim.h"
-#include "emit-rtl.h"
-
-/* Holds the interesting trailing notes for the function. */
-rtx cfg_layout_function_footer;
-rtx cfg_layout_function_header;
-
-static rtx skip_insns_after_block (basic_block);
-static void record_effective_endpoints (void);
-static rtx label_for_bb (basic_block);
-static void fixup_reorder_chain (void);
-
-static void change_scope (rtx, tree, tree);
-
-void verify_insn_chain (void);
-static void fixup_fallthru_exit_predecessor (void);
-
-rtx
-unlink_insn_chain (rtx first, rtx last)
-{
- rtx prevfirst = PREV_INSN (first);
- rtx nextlast = NEXT_INSN (last);
-
- PREV_INSN (first) = NULL;
- NEXT_INSN (last) = NULL;
- if (prevfirst)
- NEXT_INSN (prevfirst) = nextlast;
- if (nextlast)
- PREV_INSN (nextlast) = prevfirst;
- else
- set_last_insn (prevfirst);
- if (!prevfirst)
- set_first_insn (nextlast);
- return first;
-}
-
-/* Skip over inter-block insns occurring after BB which are typically
- associated with BB (e.g., barriers). If there are any such insns,
- we return the last one. Otherwise, we return the end of BB. */
-
-static rtx
-skip_insns_after_block (basic_block bb)
-{
- rtx insn, last_insn, next_head, prev;
-
- next_head = NULL_RTX;
- if (bb->next_bb != EXIT_BLOCK_PTR)
- next_head = BB_HEAD (bb->next_bb);
-
- for (last_insn = insn = BB_END (bb); (insn = NEXT_INSN (insn)) != 0; )
- {
- if (insn == next_head)
- break;
-
- switch (GET_CODE (insn))
- {
- case BARRIER:
- last_insn = insn;
- continue;
-
- case NOTE:
- switch (NOTE_KIND (insn))
- {
- case NOTE_INSN_BLOCK_END:
- gcc_unreachable ();
- continue;
- default:
- continue;
- break;
- }
- break;
-
- case CODE_LABEL:
- if (NEXT_INSN (insn)
- && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
- {
- insn = NEXT_INSN (insn);
- last_insn = insn;
- continue;
- }
- break;
-
- default:
- break;
- }
-
- break;
- }
-
- /* It is possible to hit contradictory sequence. For instance:
-
- jump_insn
- NOTE_INSN_BLOCK_BEG
- barrier
-
- Where barrier belongs to jump_insn, but the note does not. This can be
- created by removing the basic block originally following
- NOTE_INSN_BLOCK_BEG. In such case reorder the notes. */
-
- for (insn = last_insn; insn != BB_END (bb); insn = prev)
- {
- prev = PREV_INSN (insn);
- if (NOTE_P (insn))
- switch (NOTE_KIND (insn))
- {
- case NOTE_INSN_BLOCK_END:
- gcc_unreachable ();
- break;
- case NOTE_INSN_DELETED:
- case NOTE_INSN_DELETED_LABEL:
- case NOTE_INSN_DELETED_DEBUG_LABEL:
- continue;
- default:
- reorder_insns (insn, insn, last_insn);
- }
- }
-
- return last_insn;
-}
-
-/* Locate or create a label for a given basic block. */
-
-static rtx
-label_for_bb (basic_block bb)
-{
- rtx label = BB_HEAD (bb);
-
- if (!LABEL_P (label))
- {
- if (dump_file)
- fprintf (dump_file, "Emitting label for block %d\n", bb->index);
-
- label = block_label (bb);
- }
-
- return label;
-}
-
-/* Locate the effective beginning and end of the insn chain for each
- block, as defined by skip_insns_after_block above. */
-
-static void
-record_effective_endpoints (void)
-{
- rtx next_insn;
- basic_block bb;
- rtx insn;
-
- for (insn = get_insns ();
- insn
- && NOTE_P (insn)
- && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK;
- insn = NEXT_INSN (insn))
- continue;
- /* No basic blocks at all? */
- gcc_assert (insn);
-
- if (PREV_INSN (insn))
- cfg_layout_function_header =
- unlink_insn_chain (get_insns (), PREV_INSN (insn));
- else
- cfg_layout_function_header = NULL_RTX;
-
- next_insn = get_insns ();
- FOR_EACH_BB (bb)
- {
- rtx end;
-
- if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
- BB_HEADER (bb) = unlink_insn_chain (next_insn,
- PREV_INSN (BB_HEAD (bb)));
- end = skip_insns_after_block (bb);
- if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
- BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
- next_insn = NEXT_INSN (BB_END (bb));
- }
-
- cfg_layout_function_footer = next_insn;
- if (cfg_layout_function_footer)
- cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
-}
-
-/* Data structures representing mapping of INSN_LOCATOR into scope blocks, line
- numbers and files. In order to be GGC friendly we need to use separate
- varrays. This also slightly improve the memory locality in binary search.
- The _locs array contains locators where the given property change. The
- block_locators_blocks contains the scope block that is used for all insn
- locator greater than corresponding block_locators_locs value and smaller
- than the following one. Similarly for the other properties. */
-static VEC(int,heap) *block_locators_locs;
-static GTY(()) VEC(tree,gc) *block_locators_blocks;
-static VEC(int,heap) *locations_locators_locs;
-DEF_VEC_O(location_t);
-DEF_VEC_ALLOC_O(location_t,heap);
-static VEC(location_t,heap) *locations_locators_vals;
-int prologue_locator;
-int epilogue_locator;
-
-/* Hold current location information and last location information, so the
- datastructures are built lazily only when some instructions in given
- place are needed. */
-static location_t curr_location, last_location;
-static tree curr_block, last_block;
-static int curr_rtl_loc = -1;
-
-/* Allocate insn locator datastructure. */
-void
-insn_locators_alloc (void)
-{
- prologue_locator = epilogue_locator = 0;
-
- block_locators_locs = VEC_alloc (int, heap, 32);
- block_locators_blocks = VEC_alloc (tree, gc, 32);
- locations_locators_locs = VEC_alloc (int, heap, 32);
- locations_locators_vals = VEC_alloc (location_t, heap, 32);
-
- curr_location = UNKNOWN_LOCATION;
- last_location = UNKNOWN_LOCATION;
- curr_block = NULL;
- last_block = NULL;
- curr_rtl_loc = 0;
-}
-
-/* At the end of emit stage, clear current location. */
-void
-insn_locators_finalize (void)
-{
- if (curr_rtl_loc >= 0)
- epilogue_locator = curr_insn_locator ();
- curr_rtl_loc = -1;
-}
-
-/* Allocate insn locator datastructure. */
-void
-insn_locators_free (void)
-{
- prologue_locator = epilogue_locator = 0;
-
- VEC_free (int, heap, block_locators_locs);
- VEC_free (tree,gc, block_locators_blocks);
- VEC_free (int, heap, locations_locators_locs);
- VEC_free (location_t, heap, locations_locators_vals);
-}
-
-
-/* Set current location. */
-void
-set_curr_insn_source_location (location_t location)
-{
- /* IV opts calls into RTL expansion to compute costs of operations. At this
- time locators are not initialized. */
- if (curr_rtl_loc == -1)
- return;
- curr_location = location;
-}
-
-/* Get current location. */
-location_t
-get_curr_insn_source_location (void)
-{
- return curr_location;
-}
-
-/* Set current scope block. */
-void
-set_curr_insn_block (tree b)
-{
- /* IV opts calls into RTL expansion to compute costs of operations. At this
- time locators are not initialized. */
- if (curr_rtl_loc == -1)
- return;
- if (b)
- curr_block = b;
-}
-
-/* Get current scope block. */
-tree
-get_curr_insn_block (void)
-{
- return curr_block;
-}
-
-/* Return current insn locator. */
-int
-curr_insn_locator (void)
-{
- if (curr_rtl_loc == -1 || curr_location == UNKNOWN_LOCATION)
- return 0;
- if (last_block != curr_block)
- {
- curr_rtl_loc++;
- VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc);
- VEC_safe_push (tree, gc, block_locators_blocks, curr_block);
- last_block = curr_block;
- }
- if (last_location != curr_location)
- {
- curr_rtl_loc++;
- VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc);
- VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location);
- last_location = curr_location;
- }
- return curr_rtl_loc;
-}
-
-static unsigned int
-into_cfg_layout_mode (void)
-{
- cfg_layout_initialize (0);
- return 0;
-}
-
-static unsigned int
-outof_cfg_layout_mode (void)
-{
- basic_block bb;
-
- FOR_EACH_BB (bb)
- if (bb->next_bb != EXIT_BLOCK_PTR)
- bb->aux = bb->next_bb;
-
- cfg_layout_finalize ();
-
- return 0;
-}
-
-struct rtl_opt_pass pass_into_cfg_layout_mode =
-{
- {
- RTL_PASS,
- "into_cfglayout", /* name */
- NULL, /* gate */
- into_cfg_layout_mode, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_CFG, /* tv_id */
- 0, /* properties_required */
- PROP_cfglayout, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
-};
-
-struct rtl_opt_pass pass_outof_cfg_layout_mode =
-{
- {
- RTL_PASS,
- "outof_cfglayout", /* name */
- NULL, /* gate */
- outof_cfg_layout_mode, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- TV_CFG, /* tv_id */
- 0, /* properties_required */
- 0, /* properties_provided */
- PROP_cfglayout, /* properties_destroyed */
- 0, /* todo_flags_start */
- 0 /* todo_flags_finish */
- }
-};
-
-/* Return scope resulting from combination of S1 and S2. */
-static tree
-choose_inner_scope (tree s1, tree s2)
-{
- if (!s1)
- return s2;
- if (!s2)
- return s1;
- if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
- return s1;
- return s2;
-}
-
-/* Emit lexical block notes needed to change scope from S1 to S2. */
-
-static void
-change_scope (rtx orig_insn, tree s1, tree s2)
-{
- rtx insn = orig_insn;
- tree com = NULL_TREE;
- tree ts1 = s1, ts2 = s2;
- tree s;
-
- while (ts1 != ts2)
- {
- gcc_assert (ts1 && ts2);
- if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
- ts1 = BLOCK_SUPERCONTEXT (ts1);
- else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
- ts2 = BLOCK_SUPERCONTEXT (ts2);
- else
- {
- ts1 = BLOCK_SUPERCONTEXT (ts1);
- ts2 = BLOCK_SUPERCONTEXT (ts2);
- }
- }
- com = ts1;
-
- /* Close scopes. */
- s = s1;
- while (s != com)
- {
- rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
- NOTE_BLOCK (note) = s;
- s = BLOCK_SUPERCONTEXT (s);
- }
-
- /* Open scopes. */
- s = s2;
- while (s != com)
- {
- insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
- NOTE_BLOCK (insn) = s;
- s = BLOCK_SUPERCONTEXT (s);
- }
-}
-
-/* Return lexical scope block locator belongs to. */
-static tree
-locator_scope (int loc)
-{
- int max = VEC_length (int, block_locators_locs);
- int min = 0;
-
- /* When block_locators_locs was initialized, the pro- and epilogue
- insns didn't exist yet and can therefore not be found this way.
- But we know that they belong to the outer most block of the
- current function.
- Without this test, the prologue would be put inside the block of
- the first valid instruction in the function and when that first
- insn is part of an inlined function then the low_pc of that
- inlined function is messed up. Likewise for the epilogue and
- the last valid instruction. */
- if (loc == prologue_locator || loc == epilogue_locator)
- return DECL_INITIAL (cfun->decl);
-
- if (!max || !loc)
- return NULL;
- while (1)
- {
- int pos = (min + max) / 2;
- int tmp = VEC_index (int, block_locators_locs, pos);
-
- if (tmp <= loc && min != pos)
- min = pos;
- else if (tmp > loc && max != pos)
- max = pos;
- else
- {
- min = pos;
- break;
- }
- }
- return VEC_index (tree, block_locators_blocks, min);
-}
-
-/* Return lexical scope block insn belongs to. */
-tree
-insn_scope (const_rtx insn)
-{
- return locator_scope (INSN_LOCATOR (insn));
-}
-
-/* Return line number of the statement specified by the locator. */
-location_t
-locator_location (int loc)
-{
- int max = VEC_length (int, locations_locators_locs);
- int min = 0;
-
- while (1)
- {
- int pos = (min + max) / 2;
- int tmp = VEC_index (int, locations_locators_locs, pos);
-
- if (tmp <= loc && min != pos)
- min = pos;
- else if (tmp > loc && max != pos)
- max = pos;
- else
- {
- min = pos;
- break;
- }
- }
- return *VEC_index (location_t, locations_locators_vals, min);
-}
-
-/* Return source line of the statement that produced this insn. */
-int
-locator_line (int loc)
-{
- expanded_location xloc;
- if (!loc)
- return 0;
- else
- xloc = expand_location (locator_location (loc));
- return xloc.line;
-}
-
-/* Return line number of the statement that produced this insn. */
-int
-insn_line (const_rtx insn)
-{
- return locator_line (INSN_LOCATOR (insn));
-}
-
-/* Return source file of the statement specified by LOC. */
-const char *
-locator_file (int loc)
-{
- expanded_location xloc;
- if (!loc)
- return 0;
- else
- xloc = expand_location (locator_location (loc));
- return xloc.file;
-}
-
-/* Return source file of the statement that produced this insn. */
-const char *
-insn_file (const_rtx insn)
-{
- return locator_file (INSN_LOCATOR (insn));
-}
-
-/* Return true if LOC1 and LOC2 locators have the same location and scope. */
-bool
-locator_eq (int loc1, int loc2)
-{
- if (loc1 == loc2)
- return true;
- if (locator_location (loc1) != locator_location (loc2))
- return false;
- return locator_scope (loc1) == locator_scope (loc2);
-}
-
-/* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
- on the scope tree and the newly reordered instructions. */
-
-void
-reemit_insn_block_notes (void)
-{
- tree cur_block = DECL_INITIAL (cfun->decl);
- rtx insn, note;
-
- insn = get_insns ();
- if (!active_insn_p (insn))
- insn = next_active_insn (insn);
- for (; insn; insn = next_active_insn (insn))
- {
- tree this_block;
-
- /* Avoid putting scope notes between jump table and its label. */
- if (JUMP_TABLE_DATA_P (insn))
- continue;
-
- this_block = insn_scope (insn);
- /* For sequences compute scope resulting from merging all scopes
- of instructions nested inside. */
- if (GET_CODE (PATTERN (insn)) == SEQUENCE)
- {
- int i;
- rtx body = PATTERN (insn);
-
- this_block = NULL;
- for (i = 0; i < XVECLEN (body, 0); i++)
- this_block = choose_inner_scope (this_block,
- insn_scope (XVECEXP (body, 0, i)));
- }
- if (! this_block)
- continue;
-
- if (this_block != cur_block)
- {
- change_scope (insn, cur_block, this_block);
- cur_block = this_block;
- }
- }
-
- /* change_scope emits before the insn, not after. */
- note = emit_note (NOTE_INSN_DELETED);
- change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
- delete_insn (note);
-
- reorder_blocks ();
-}
-
-
-/* Link the basic blocks in the correct order, compacting the basic
- block queue while at it. If STAY_IN_CFGLAYOUT_MODE is false, this
- function also clears the basic block header and footer fields.
-
- This function is usually called after a pass (e.g. tracer) finishes
- some transformations while in cfglayout mode. The required sequence
- of the basic blocks is in a linked list along the bb->aux field.
- This functions re-links the basic block prev_bb and next_bb pointers
- accordingly, and it compacts and renumbers the blocks. */
-
-void
-relink_block_chain (bool stay_in_cfglayout_mode)
-{
- basic_block bb, prev_bb;
- int index;
-
- /* Maybe dump the re-ordered sequence. */
- if (dump_file)
- {
- fprintf (dump_file, "Reordered sequence:\n");
- for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
- bb;
- bb = (basic_block) bb->aux, index++)
- {
- fprintf (dump_file, " %i ", index);
- if (get_bb_original (bb))
- fprintf (dump_file, "duplicate of %i ",
- get_bb_original (bb)->index);
- else if (forwarder_block_p (bb)
- && !LABEL_P (BB_HEAD (bb)))
- fprintf (dump_file, "compensation ");
- else
- fprintf (dump_file, "bb %i ", bb->index);
- fprintf (dump_file, " [%i]\n", bb->frequency);
- }
- }
-
- /* Now reorder the blocks. */
- prev_bb = ENTRY_BLOCK_PTR;
- bb = ENTRY_BLOCK_PTR->next_bb;
- for (; bb; prev_bb = bb, bb = (basic_block) bb->aux)
- {
- bb->prev_bb = prev_bb;
- prev_bb->next_bb = bb;
- }
- prev_bb->next_bb = EXIT_BLOCK_PTR;
- EXIT_BLOCK_PTR->prev_bb = prev_bb;
-
- /* Then, clean up the aux fields. */
- FOR_ALL_BB (bb)
- {
- bb->aux = NULL;
- if (!stay_in_cfglayout_mode)
- BB_HEADER (bb) = BB_FOOTER (bb) = NULL;
- }
-
- /* Maybe reset the original copy tables, they are not valid anymore
- when we renumber the basic blocks in compact_blocks. If we are
- are going out of cfglayout mode, don't re-allocate the tables. */
- free_original_copy_tables ();
- if (stay_in_cfglayout_mode)
- initialize_original_copy_tables ();
-
- /* Finally, put basic_block_info in the new order. */
- compact_blocks ();
-}
-
-
-/* Given a reorder chain, rearrange the code to match. */
-
-static void
-fixup_reorder_chain (void)
-{
- basic_block bb;
- rtx insn = NULL;
-
- if (cfg_layout_function_header)
- {
- set_first_insn (cfg_layout_function_header);
- insn = cfg_layout_function_header;
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- }
-
- /* First do the bulk reordering -- rechain the blocks without regard to
- the needed changes to jumps and labels. */
-
- for (bb = ENTRY_BLOCK_PTR->next_bb; bb; bb = (basic_block) bb->aux)
- {
- if (BB_HEADER (bb))
- {
- if (insn)
- NEXT_INSN (insn) = BB_HEADER (bb);
- else
- set_first_insn (BB_HEADER (bb));
- PREV_INSN (BB_HEADER (bb)) = insn;
- insn = BB_HEADER (bb);
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- }
- if (insn)
- NEXT_INSN (insn) = BB_HEAD (bb);
- else
- set_first_insn (BB_HEAD (bb));
- PREV_INSN (BB_HEAD (bb)) = insn;
- insn = BB_END (bb);
- if (BB_FOOTER (bb))
- {
- NEXT_INSN (insn) = BB_FOOTER (bb);
- PREV_INSN (BB_FOOTER (bb)) = insn;
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- }
- }
-
- NEXT_INSN (insn) = cfg_layout_function_footer;
- if (cfg_layout_function_footer)
- PREV_INSN (cfg_layout_function_footer) = insn;
-
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
-
- set_last_insn (insn);
-#ifdef ENABLE_CHECKING
- verify_insn_chain ();
-#endif
-
- /* Now add jumps and labels as needed to match the blocks new
- outgoing edges. */
-
- for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux)
- {
- edge e_fall, e_taken, e;
- rtx bb_end_insn;
- rtx ret_label = NULL_RTX;
- basic_block nb, src_bb;
- edge_iterator ei;
-
- if (EDGE_COUNT (bb->succs) == 0)
- continue;
-
- /* Find the old fallthru edge, and another non-EH edge for
- a taken jump. */
- e_taken = e_fall = NULL;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (e->flags & EDGE_FALLTHRU)
- e_fall = e;
- else if (! (e->flags & EDGE_EH))
- e_taken = e;
-
- bb_end_insn = BB_END (bb);
- if (JUMP_P (bb_end_insn))
- {
- ret_label = JUMP_LABEL (bb_end_insn);
- if (any_condjump_p (bb_end_insn))
- {
- /* This might happen if the conditional jump has side
- effects and could therefore not be optimized away.
- Make the basic block to end with a barrier in order
- to prevent rtl_verify_flow_info from complaining. */
- if (!e_fall)
- {
- gcc_assert (!onlyjump_p (bb_end_insn)
- || returnjump_p (bb_end_insn));
- BB_FOOTER (bb) = emit_barrier_after (bb_end_insn);
- continue;
- }
-
- /* If the old fallthru is still next, nothing to do. */
- if (bb->aux == e_fall->dest
- || e_fall->dest == EXIT_BLOCK_PTR)
- continue;
-
- /* The degenerated case of conditional jump jumping to the next
- instruction can happen for jumps with side effects. We need
- to construct a forwarder block and this will be done just
- fine by force_nonfallthru below. */
- if (!e_taken)
- ;
-
- /* There is another special case: if *neither* block is next,
- such as happens at the very end of a function, then we'll
- need to add a new unconditional jump. Choose the taken
- edge based on known or assumed probability. */
- else if (bb->aux != e_taken->dest)
- {
- rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
-
- if (note
- && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
- && invert_jump (bb_end_insn,
- (e_fall->dest == EXIT_BLOCK_PTR
- ? NULL_RTX
- : label_for_bb (e_fall->dest)), 0))
- {
- e_fall->flags &= ~EDGE_FALLTHRU;
- gcc_checking_assert (could_fall_through
- (e_taken->src, e_taken->dest));
- e_taken->flags |= EDGE_FALLTHRU;
- update_br_prob_note (bb);
- e = e_fall, e_fall = e_taken, e_taken = e;
- }
- }
-
- /* If the "jumping" edge is a crossing edge, and the fall
- through edge is non-crossing, leave things as they are. */
- else if ((e_taken->flags & EDGE_CROSSING)
- && !(e_fall->flags & EDGE_CROSSING))
- continue;
-
- /* Otherwise we can try to invert the jump. This will
- basically never fail, however, keep up the pretense. */
- else if (invert_jump (bb_end_insn,
- (e_fall->dest == EXIT_BLOCK_PTR
- ? NULL_RTX
- : label_for_bb (e_fall->dest)), 0))
- {
- e_fall->flags &= ~EDGE_FALLTHRU;
- gcc_checking_assert (could_fall_through
- (e_taken->src, e_taken->dest));
- e_taken->flags |= EDGE_FALLTHRU;
- update_br_prob_note (bb);
- if (LABEL_NUSES (ret_label) == 0
- && single_pred_p (e_taken->dest))
- delete_insn (ret_label);
- continue;
- }
- }
- else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL)
- {
- /* If the old fallthru is still next or if
- asm goto doesn't have a fallthru (e.g. when followed by
- __builtin_unreachable ()), nothing to do. */
- if (! e_fall
- || bb->aux == e_fall->dest
- || e_fall->dest == EXIT_BLOCK_PTR)
- continue;
-
- /* Otherwise we'll have to use the fallthru fixup below. */
- }
- else
- {
- /* Otherwise we have some return, switch or computed
- jump. In the 99% case, there should not have been a
- fallthru edge. */
- gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
- continue;
- }
- }
- else
- {
- /* No fallthru implies a noreturn function with EH edges, or
- something similarly bizarre. In any case, we don't need to
- do anything. */
- if (! e_fall)
- continue;
-
- /* If the fallthru block is still next, nothing to do. */
- if (bb->aux == e_fall->dest)
- continue;
-
- /* A fallthru to exit block. */
- if (e_fall->dest == EXIT_BLOCK_PTR)
- continue;
- }
-
- /* We got here if we need to add a new jump insn.
- Note force_nonfallthru can delete E_FALL and thus we have to
- save E_FALL->src prior to the call to force_nonfallthru. */
- src_bb = e_fall->src;
- nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
- if (nb)
- {
- nb->aux = bb->aux;
- bb->aux = nb;
- /* Don't process this new block. */
- bb = nb;
-
- /* Make sure new bb is tagged for correct section (same as
- fall-thru source, since you cannot fall-thru across
- section boundaries). */
- BB_COPY_PARTITION (src_bb, single_pred (bb));
- if (flag_reorder_blocks_and_partition
- && targetm_common.have_named_sections
- && JUMP_P (BB_END (bb))
- && !any_condjump_p (BB_END (bb))
- && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
- add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX);
- }
- }
-
- relink_block_chain (/*stay_in_cfglayout_mode=*/false);
-
- /* Annoying special case - jump around dead jumptables left in the code. */
- FOR_EACH_BB (bb)
- {
- edge e = find_fallthru_edge (bb->succs);
-
- if (e && !can_fallthru (e->src, e->dest))
- force_nonfallthru (e);
- }
-
- /* Ensure goto_locus from edges has some instructions with that locus
- in RTL. */
- if (!optimize)
- FOR_EACH_BB (bb)
- {
- edge e;
- edge_iterator ei;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
- {
- edge e2;
- edge_iterator ei2;
- basic_block dest, nb;
- rtx end;
-
- insn = BB_END (e->src);
- end = PREV_INSN (BB_HEAD (e->src));
- while (insn != end
- && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
- insn = PREV_INSN (insn);
- if (insn != end
- && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
- continue;
- if (simplejump_p (BB_END (e->src))
- && INSN_LOCATOR (BB_END (e->src)) == 0)
- {
- INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
- continue;
- }
- dest = e->dest;
- if (dest == EXIT_BLOCK_PTR)
- {
- /* Non-fallthru edges to the exit block cannot be split. */
- if (!(e->flags & EDGE_FALLTHRU))
- continue;
- }
- else
- {
- insn = BB_HEAD (dest);
- end = NEXT_INSN (BB_END (dest));
- while (insn != end && !NONDEBUG_INSN_P (insn))
- insn = NEXT_INSN (insn);
- if (insn != end && INSN_LOCATOR (insn)
- && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
- continue;
- }
- nb = split_edge (e);
- if (!INSN_P (BB_END (nb)))
- BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
- nb);
- INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
-
- /* If there are other incoming edges to the destination block
- with the same goto locus, redirect them to the new block as
- well, this can prevent other such blocks from being created
- in subsequent iterations of the loop. */
- for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); )
- if (e2->goto_locus
- && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
- && locator_eq (e->goto_locus, e2->goto_locus))
- redirect_edge_and_branch (e2, nb);
- else
- ei_next (&ei2);
- }
- }
-}
-
-/* Perform sanity checks on the insn chain.
- 1. Check that next/prev pointers are consistent in both the forward and
- reverse direction.
- 2. Count insns in chain, going both directions, and check if equal.
- 3. Check that get_last_insn () returns the actual end of chain. */
-
-DEBUG_FUNCTION void
-verify_insn_chain (void)
-{
- rtx x, prevx, nextx;
- int insn_cnt1, insn_cnt2;
-
- for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
- x != 0;
- prevx = x, insn_cnt1++, x = NEXT_INSN (x))
- gcc_assert (PREV_INSN (x) == prevx);
-
- gcc_assert (prevx == get_last_insn ());
-
- for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
- x != 0;
- nextx = x, insn_cnt2++, x = PREV_INSN (x))
- gcc_assert (NEXT_INSN (x) == nextx);
-
- gcc_assert (insn_cnt1 == insn_cnt2);
-}
-
-/* If we have assembler epilogues, the block falling through to exit must
- be the last one in the reordered chain when we reach final. Ensure
- that this condition is met. */
-static void
-fixup_fallthru_exit_predecessor (void)
-{
- edge e;
- basic_block bb = NULL;
-
- /* This transformation is not valid before reload, because we might
- separate a call from the instruction that copies the return
- value. */
- gcc_assert (reload_completed);
-
- e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
- if (e)
- bb = e->src;
-
- if (bb && bb->aux)
- {
- basic_block c = ENTRY_BLOCK_PTR->next_bb;
-
- /* If the very first block is the one with the fall-through exit
- edge, we have to split that block. */
- if (c == bb)
- {
- bb = split_block (bb, NULL)->dest;
- bb->aux = c->aux;
- c->aux = bb;
- BB_FOOTER (bb) = BB_FOOTER (c);
- BB_FOOTER (c) = NULL;
- }
-
- while (c->aux != bb)
- c = (basic_block) c->aux;
-
- c->aux = bb->aux;
- while (c->aux)
- c = (basic_block) c->aux;
-
- c->aux = bb;
- bb->aux = NULL;
- }
-}
-
-/* In case there are more than one fallthru predecessors of exit, force that
- there is only one. */
-
-static void
-force_one_exit_fallthru (void)
-{
- edge e, predecessor = NULL;
- bool more = false;
- edge_iterator ei;
- basic_block forwarder, bb;
-
- FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
- if (e->flags & EDGE_FALLTHRU)
- {
- if (predecessor == NULL)
- predecessor = e;
- else
- {
- more = true;
- break;
- }
- }
-
- if (!more)
- return;
-
- /* Exit has several fallthru predecessors. Create a forwarder block for
- them. */
- forwarder = split_edge (predecessor);
- for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
- {
- if (e->src == forwarder
- || !(e->flags & EDGE_FALLTHRU))
- ei_next (&ei);
- else
- redirect_edge_and_branch_force (e, forwarder);
- }
-
- /* Fix up the chain of blocks -- make FORWARDER immediately precede the
- exit block. */
- FOR_EACH_BB (bb)
- {
- if (bb->aux == NULL && bb != forwarder)
- {
- bb->aux = forwarder;
- break;
- }
- }
-}
-
-/* Return true in case it is possible to duplicate the basic block BB. */
-
-/* We do not want to declare the function in a header file, since it should
- only be used through the cfghooks interface, and we do not want to move
- it to cfgrtl.c since it would require also moving quite a lot of related
- code. */
-extern bool cfg_layout_can_duplicate_bb_p (const_basic_block);
-
-bool
-cfg_layout_can_duplicate_bb_p (const_basic_block bb)
-{
- /* Do not attempt to duplicate tablejumps, as we need to unshare
- the dispatch table. This is difficult to do, as the instructions
- computing jump destination may be hoisted outside the basic block. */
- if (tablejump_p (BB_END (bb), NULL, NULL))
- return false;
-
- /* Do not duplicate blocks containing insns that can't be copied. */
- if (targetm.cannot_copy_insn_p)
- {
- rtx insn = BB_HEAD (bb);
- while (1)
- {
- if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
- return false;
- if (insn == BB_END (bb))
- break;
- insn = NEXT_INSN (insn);
- }
- }
-
- return true;
-}
-
-rtx
-duplicate_insn_chain (rtx from, rtx to)
-{
- rtx insn, last, copy;
-
- /* Avoid updating of boundaries of previous basic block. The
- note will get removed from insn stream in fixup. */
- last = emit_note (NOTE_INSN_DELETED);
-
- /* Create copy at the end of INSN chain. The chain will
- be reordered later. */
- for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
- {
- switch (GET_CODE (insn))
- {
- case DEBUG_INSN:
- /* Don't duplicate label debug insns. */
- if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
- break;
- /* FALLTHRU */
- case INSN:
- case CALL_INSN:
- case JUMP_INSN:
- /* Avoid copying of dispatch tables. We never duplicate
- tablejumps, so this can hit only in case the table got
- moved far from original jump. */
- if (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
- {
- /* Avoid copying following barrier as well if any
- (and debug insns in between). */
- rtx next;
-
- for (next = NEXT_INSN (insn);
- next != NEXT_INSN (to);
- next = NEXT_INSN (next))
- if (!DEBUG_INSN_P (next))
- break;
- if (next != NEXT_INSN (to) && BARRIER_P (next))
- insn = next;
- break;
- }
- copy = emit_copy_of_insn_after (insn, get_last_insn ());
- if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
- && ANY_RETURN_P (JUMP_LABEL (insn)))
- JUMP_LABEL (copy) = JUMP_LABEL (insn);
- maybe_copy_prologue_epilogue_insn (insn, copy);
- break;
-
- case CODE_LABEL:
- break;
-
- case BARRIER:
- emit_barrier ();
- break;
-
- case NOTE:
- switch (NOTE_KIND (insn))
- {
- /* In case prologue is empty and function contain label
- in first BB, we may want to copy the block. */
- case NOTE_INSN_PROLOGUE_END:
-
- case NOTE_INSN_DELETED:
- case NOTE_INSN_DELETED_LABEL:
- case NOTE_INSN_DELETED_DEBUG_LABEL:
- /* No problem to strip these. */
- case NOTE_INSN_FUNCTION_BEG:
- /* There is always just single entry to function. */
- case NOTE_INSN_BASIC_BLOCK:
- break;
-
- case NOTE_INSN_EPILOGUE_BEG:
- case NOTE_INSN_SWITCH_TEXT_SECTIONS:
- emit_note_copy (insn);
- break;
-
- default:
- /* All other notes should have already been eliminated. */
- gcc_unreachable ();
- }
- break;
- default:
- gcc_unreachable ();
- }
- }
- insn = NEXT_INSN (last);
- delete_insn (last);
- return insn;
-}
-/* Create a duplicate of the basic block BB. */
-
-/* We do not want to declare the function in a header file, since it should
- only be used through the cfghooks interface, and we do not want to move
- it to cfgrtl.c since it would require also moving quite a lot of related
- code. */
-extern basic_block cfg_layout_duplicate_bb (basic_block);
-
-basic_block
-cfg_layout_duplicate_bb (basic_block bb)
-{
- rtx insn;
- basic_block new_bb;
-
- insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb));
- new_bb = create_basic_block (insn,
- insn ? get_last_insn () : NULL,
- EXIT_BLOCK_PTR->prev_bb);
-
- BB_COPY_PARTITION (new_bb, bb);
- if (BB_HEADER (bb))
- {
- insn = BB_HEADER (bb);
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- insn = duplicate_insn_chain (BB_HEADER (bb), insn);
- if (insn)
- BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
- }
-
- if (BB_FOOTER (bb))
- {
- insn = BB_FOOTER (bb);
- while (NEXT_INSN (insn))
- insn = NEXT_INSN (insn);
- insn = duplicate_insn_chain (BB_FOOTER (bb), insn);
- if (insn)
- BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
- }
-
- return new_bb;
-}
-
-
-/* Main entry point to this module - initialize the datastructures for
- CFG layout changes. It keeps LOOPS up-to-date if not null.
-
- FLAGS is a set of additional flags to pass to cleanup_cfg(). */
-
-void
-cfg_layout_initialize (unsigned int flags)
-{
- rtx x;
- basic_block bb;
-
- initialize_original_copy_tables ();
-
- cfg_layout_rtl_register_cfg_hooks ();
-
- record_effective_endpoints ();
-
- /* Make sure that the targets of non local gotos are marked. */
- for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
- {
- bb = BLOCK_FOR_INSN (XEXP (x, 0));
- bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
- }
-
- cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
-}
-
-/* Splits superblocks. */
-void
-break_superblocks (void)
-{
- sbitmap superblocks;
- bool need = false;
- basic_block bb;
-
- superblocks = sbitmap_alloc (last_basic_block);
- sbitmap_zero (superblocks);
-
- FOR_EACH_BB (bb)
- if (bb->flags & BB_SUPERBLOCK)
- {
- bb->flags &= ~BB_SUPERBLOCK;
- SET_BIT (superblocks, bb->index);
- need = true;
- }
-
- if (need)
- {
- rebuild_jump_labels (get_insns ());
- find_many_sub_basic_blocks (superblocks);
- }
-
- free (superblocks);
-}
-
-/* Finalize the changes: reorder insn list according to the sequence specified
- by aux pointers, enter compensation code, rebuild scope forest. */
-
-void
-cfg_layout_finalize (void)
-{
-#ifdef ENABLE_CHECKING
- verify_flow_info ();
-#endif
- force_one_exit_fallthru ();
- rtl_register_cfg_hooks ();
- if (reload_completed
-#ifdef HAVE_epilogue
- && !HAVE_epilogue
-#endif
- )
- fixup_fallthru_exit_predecessor ();
- fixup_reorder_chain ();
-
- rebuild_jump_labels (get_insns ());
- delete_dead_jumptables ();
-
-#ifdef ENABLE_CHECKING
- verify_insn_chain ();
- verify_flow_info ();
-#endif
-}
-
-/* Checks whether all N blocks in BBS array can be copied. */
-bool
-can_copy_bbs_p (basic_block *bbs, unsigned n)
-{
- unsigned i;
- edge e;
- int ret = true;
-
- for (i = 0; i < n; i++)
- bbs[i]->flags |= BB_DUPLICATED;
-
- for (i = 0; i < n; i++)
- {
- /* In case we should redirect abnormal edge during duplication, fail. */
- edge_iterator ei;
- FOR_EACH_EDGE (e, ei, bbs[i]->succs)
- if ((e->flags & EDGE_ABNORMAL)
- && (e->dest->flags & BB_DUPLICATED))
- {
- ret = false;
- goto end;
- }
-
- if (!can_duplicate_block_p (bbs[i]))
- {
- ret = false;
- break;
- }
- }
-
-end:
- for (i = 0; i < n; i++)
- bbs[i]->flags &= ~BB_DUPLICATED;
-
- return ret;
-}
-
-/* Duplicates N basic blocks stored in array BBS. Newly created basic blocks
- are placed into array NEW_BBS in the same order. Edges from basic blocks
- in BBS are also duplicated and copies of those of them
- that lead into BBS are redirected to appropriate newly created block. The
- function assigns bbs into loops (copy of basic block bb is assigned to
- bb->loop_father->copy loop, so this must be set up correctly in advance)
- and updates dominators locally (LOOPS structure that contains the information
- about dominators is passed to enable this).
-
- BASE is the superloop to that basic block belongs; if its header or latch
- is copied, we do not set the new blocks as header or latch.
-
- Created copies of N_EDGES edges in array EDGES are stored in array NEW_EDGES,
- also in the same order.
-
- Newly created basic blocks are put after the basic block AFTER in the
- instruction stream, and the order of the blocks in BBS array is preserved. */
-
-void
-copy_bbs (basic_block *bbs, unsigned n, basic_block *new_bbs,
- edge *edges, unsigned num_edges, edge *new_edges,
- struct loop *base, basic_block after)
-{
- unsigned i, j;
- basic_block bb, new_bb, dom_bb;
- edge e;
-
- /* Duplicate bbs, update dominators, assign bbs to loops. */
- for (i = 0; i < n; i++)
- {
- /* Duplicate. */
- bb = bbs[i];
- new_bb = new_bbs[i] = duplicate_block (bb, NULL, after);
- after = new_bb;
- bb->flags |= BB_DUPLICATED;
- /* Possibly set loop header. */
- if (bb->loop_father->header == bb && bb->loop_father != base)
- new_bb->loop_father->header = new_bb;
- /* Or latch. */
- if (bb->loop_father->latch == bb && bb->loop_father != base)
- new_bb->loop_father->latch = new_bb;
- }
-
- /* Set dominators. */
- for (i = 0; i < n; i++)
- {
- bb = bbs[i];
- new_bb = new_bbs[i];
-
- dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
- if (dom_bb->flags & BB_DUPLICATED)
- {
- dom_bb = get_bb_copy (dom_bb);
- set_immediate_dominator (CDI_DOMINATORS, new_bb, dom_bb);
- }
- }
-
- /* Redirect edges. */
- for (j = 0; j < num_edges; j++)
- new_edges[j] = NULL;
- for (i = 0; i < n; i++)
- {
- edge_iterator ei;
- new_bb = new_bbs[i];
- bb = bbs[i];
-
- FOR_EACH_EDGE (e, ei, new_bb->succs)
- {
- for (j = 0; j < num_edges; j++)
- if (edges[j] && edges[j]->src == bb && edges[j]->dest == e->dest)
- new_edges[j] = e;
-
- if (!(e->dest->flags & BB_DUPLICATED))
- continue;
- redirect_edge_and_branch_force (e, get_bb_copy (e->dest));
- }
- }
-
- /* Clear information about duplicates. */
- for (i = 0; i < n; i++)
- bbs[i]->flags &= ~BB_DUPLICATED;
-}
-
-#include "gt-cfglayout.h"
diff --git a/gcc/cfglayout.h b/gcc/cfglayout.h
deleted file mode 100644
index deb985646a3..00000000000
--- a/gcc/cfglayout.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Basic block reordering routines for the GNU compiler.
- Copyright (C) 2000, 2003, 2004, 2007, 2011 Free Software Foundation, Inc.
-
- This file is part of GCC.
-
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING3. If not see
- <http://www.gnu.org/licenses/>. */
-
-#ifndef GCC_CFGLAYOUT_H
-#define GCC_CFGLAYOUT_H
-
-#include "basic-block.h"
-
-extern GTY(()) rtx cfg_layout_function_footer;
-extern GTY(()) rtx cfg_layout_function_header;
-
-extern void cfg_layout_initialize (unsigned int);
-extern void cfg_layout_finalize (void);
-extern tree insn_scope (const_rtx);
-extern void reemit_insn_block_notes (void);
-extern bool can_copy_bbs_p (basic_block *, unsigned);
-extern void copy_bbs (basic_block *, unsigned, basic_block *,
- edge *, unsigned, edge *, struct loop *,
- basic_block);
-extern rtx duplicate_insn_chain (rtx, rtx);
-
-#endif /* GCC_CFGLAYOUT_H */
diff --git a/gcc/cfgloopmanip.c b/gcc/cfgloopmanip.c
index 0454603d158..75d721d6956 100644
--- a/gcc/cfgloopmanip.c
+++ b/gcc/cfgloopmanip.c
@@ -27,8 +27,6 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "basic-block.h"
#include "cfgloop.h"
-#include "cfglayout.h"
-#include "cfghooks.h"
#include "tree-flow.h"
static void copy_loops_to (struct loop **, int,
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 3e4b65ec95b..69cf86dc954 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -55,7 +55,6 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "insn-attr.h"
#include "insn-config.h"
-#include "cfglayout.h"
#include "expr.h"
#include "target.h"
#include "common/common-target.h"
@@ -64,6 +63,18 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "df.h"
+/* Holds the interesting leading and trailing notes for the function.
+ Only applicable if the CFG is in cfglayout mode. */
+static GTY(()) rtx cfg_layout_function_footer;
+static GTY(()) rtx cfg_layout_function_header;
+
+static rtx skip_insns_after_block (basic_block);
+static void record_effective_endpoints (void);
+static rtx label_for_bb (basic_block);
+static void fixup_reorder_chain (void);
+
+void verify_insn_chain (void);
+static void fixup_fallthru_exit_predecessor (void);
static int can_delete_note_p (const_rtx);
static int can_delete_label_p (const_rtx);
static basic_block rtl_split_edge (edge);
@@ -2646,6 +2657,967 @@ fixup_abnormal_edges (void)
return inserted;
}
+
+/* Cut the insns from FIRST to LAST out of the insns stream. */
+
+rtx
+unlink_insn_chain (rtx first, rtx last)
+{
+ rtx prevfirst = PREV_INSN (first);
+ rtx nextlast = NEXT_INSN (last);
+
+ PREV_INSN (first) = NULL;
+ NEXT_INSN (last) = NULL;
+ if (prevfirst)
+ NEXT_INSN (prevfirst) = nextlast;
+ if (nextlast)
+ PREV_INSN (nextlast) = prevfirst;
+ else
+ set_last_insn (prevfirst);
+ if (!prevfirst)
+ set_first_insn (nextlast);
+ return first;
+}
+
+/* Skip over inter-block insns occurring after BB which are typically
+ associated with BB (e.g., barriers). If there are any such insns,
+ we return the last one. Otherwise, we return the end of BB. */
+
+static rtx
+skip_insns_after_block (basic_block bb)
+{
+ rtx insn, last_insn, next_head, prev;
+
+ next_head = NULL_RTX;
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ next_head = BB_HEAD (bb->next_bb);
+
+ for (last_insn = insn = BB_END (bb); (insn = NEXT_INSN (insn)) != 0; )
+ {
+ if (insn == next_head)
+ break;
+
+ switch (GET_CODE (insn))
+ {
+ case BARRIER:
+ last_insn = insn;
+ continue;
+
+ case NOTE:
+ switch (NOTE_KIND (insn))
+ {
+ case NOTE_INSN_BLOCK_END:
+ gcc_unreachable ();
+ continue;
+ default:
+ continue;
+ break;
+ }
+ break;
+
+ case CODE_LABEL:
+ if (NEXT_INSN (insn)
+ && JUMP_TABLE_DATA_P (NEXT_INSN (insn)))
+ {
+ insn = NEXT_INSN (insn);
+ last_insn = insn;
+ continue;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ break;
+ }
+
+ /* It is possible to hit contradictory sequence. For instance:
+
+ jump_insn
+ NOTE_INSN_BLOCK_BEG
+ barrier
+
+ Where barrier belongs to jump_insn, but the note does not. This can be
+ created by removing the basic block originally following
+ NOTE_INSN_BLOCK_BEG. In such case reorder the notes. */
+
+ for (insn = last_insn; insn != BB_END (bb); insn = prev)
+ {
+ prev = PREV_INSN (insn);
+ if (NOTE_P (insn))
+ switch (NOTE_KIND (insn))
+ {
+ case NOTE_INSN_BLOCK_END:
+ gcc_unreachable ();
+ break;
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
+ case NOTE_INSN_DELETED_DEBUG_LABEL:
+ continue;
+ default:
+ reorder_insns (insn, insn, last_insn);
+ }
+ }
+
+ return last_insn;
+}
+
+/* Locate or create a label for a given basic block. */
+
+static rtx
+label_for_bb (basic_block bb)
+{
+ rtx label = BB_HEAD (bb);
+
+ if (!LABEL_P (label))
+ {
+ if (dump_file)
+ fprintf (dump_file, "Emitting label for block %d\n", bb->index);
+
+ label = block_label (bb);
+ }
+
+ return label;
+}
+
+/* Locate the effective beginning and end of the insn chain for each
+ block, as defined by skip_insns_after_block above. */
+
+static void
+record_effective_endpoints (void)
+{
+ rtx next_insn;
+ basic_block bb;
+ rtx insn;
+
+ for (insn = get_insns ();
+ insn
+ && NOTE_P (insn)
+ && NOTE_KIND (insn) != NOTE_INSN_BASIC_BLOCK;
+ insn = NEXT_INSN (insn))
+ continue;
+ /* No basic blocks at all? */
+ gcc_assert (insn);
+
+ if (PREV_INSN (insn))
+ cfg_layout_function_header =
+ unlink_insn_chain (get_insns (), PREV_INSN (insn));
+ else
+ cfg_layout_function_header = NULL_RTX;
+
+ next_insn = get_insns ();
+ FOR_EACH_BB (bb)
+ {
+ rtx end;
+
+ if (PREV_INSN (BB_HEAD (bb)) && next_insn != BB_HEAD (bb))
+ BB_HEADER (bb) = unlink_insn_chain (next_insn,
+ PREV_INSN (BB_HEAD (bb)));
+ end = skip_insns_after_block (bb);
+ if (NEXT_INSN (BB_END (bb)) && BB_END (bb) != end)
+ BB_FOOTER (bb) = unlink_insn_chain (NEXT_INSN (BB_END (bb)), end);
+ next_insn = NEXT_INSN (BB_END (bb));
+ }
+
+ cfg_layout_function_footer = next_insn;
+ if (cfg_layout_function_footer)
+ cfg_layout_function_footer = unlink_insn_chain (cfg_layout_function_footer, get_last_insn ());
+}
+
+static unsigned int
+into_cfg_layout_mode (void)
+{
+ cfg_layout_initialize (0);
+ return 0;
+}
+
+static unsigned int
+outof_cfg_layout_mode (void)
+{
+ basic_block bb;
+
+ FOR_EACH_BB (bb)
+ if (bb->next_bb != EXIT_BLOCK_PTR)
+ bb->aux = bb->next_bb;
+
+ cfg_layout_finalize ();
+
+ return 0;
+}
+
+struct rtl_opt_pass pass_into_cfg_layout_mode =
+{
+ {
+ RTL_PASS,
+ "into_cfglayout", /* name */
+ NULL, /* gate */
+ into_cfg_layout_mode, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_CFG, /* tv_id */
+ 0, /* properties_required */
+ PROP_cfglayout, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+ }
+};
+
+struct rtl_opt_pass pass_outof_cfg_layout_mode =
+{
+ {
+ RTL_PASS,
+ "outof_cfglayout", /* name */
+ NULL, /* gate */
+ outof_cfg_layout_mode, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_CFG, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ PROP_cfglayout, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0 /* todo_flags_finish */
+ }
+};
+
+
+/* Link the basic blocks in the correct order, compacting the basic
+ block queue while at it. If STAY_IN_CFGLAYOUT_MODE is false, this
+ function also clears the basic block header and footer fields.
+
+ This function is usually called after a pass (e.g. tracer) finishes
+ some transformations while in cfglayout mode. The required sequence
+ of the basic blocks is in a linked list along the bb->aux field.
+ This functions re-links the basic block prev_bb and next_bb pointers
+ accordingly, and it compacts and renumbers the blocks. */
+
+void
+relink_block_chain (bool stay_in_cfglayout_mode)
+{
+ basic_block bb, prev_bb;
+ int index;
+
+ /* Maybe dump the re-ordered sequence. */
+ if (dump_file)
+ {
+ fprintf (dump_file, "Reordered sequence:\n");
+ for (bb = ENTRY_BLOCK_PTR->next_bb, index = NUM_FIXED_BLOCKS;
+ bb;
+ bb = (basic_block) bb->aux, index++)
+ {
+ fprintf (dump_file, " %i ", index);
+ if (get_bb_original (bb))
+ fprintf (dump_file, "duplicate of %i ",
+ get_bb_original (bb)->index);
+ else if (forwarder_block_p (bb)
+ && !LABEL_P (BB_HEAD (bb)))
+ fprintf (dump_file, "compensation ");
+ else
+ fprintf (dump_file, "bb %i ", bb->index);
+ fprintf (dump_file, " [%i]\n", bb->frequency);
+ }
+ }
+
+ /* Now reorder the blocks. */
+ prev_bb = ENTRY_BLOCK_PTR;
+ bb = ENTRY_BLOCK_PTR->next_bb;
+ for (; bb; prev_bb = bb, bb = (basic_block) bb->aux)
+ {
+ bb->prev_bb = prev_bb;
+ prev_bb->next_bb = bb;
+ }
+ prev_bb->next_bb = EXIT_BLOCK_PTR;
+ EXIT_BLOCK_PTR->prev_bb = prev_bb;
+
+ /* Then, clean up the aux fields. */
+ FOR_ALL_BB (bb)
+ {
+ bb->aux = NULL;
+ if (!stay_in_cfglayout_mode)
+ BB_HEADER (bb) = BB_FOOTER (bb) = NULL;
+ }
+
+ /* Maybe reset the original copy tables, they are not valid anymore
+ when we renumber the basic blocks in compact_blocks. If we are
+ are going out of cfglayout mode, don't re-allocate the tables. */
+ free_original_copy_tables ();
+ if (stay_in_cfglayout_mode)
+ initialize_original_copy_tables ();
+
+ /* Finally, put basic_block_info in the new order. */
+ compact_blocks ();
+}
+
+
+/* Given a reorder chain, rearrange the code to match. */
+
+static void
+fixup_reorder_chain (void)
+{
+ basic_block bb;
+ rtx insn = NULL;
+
+ if (cfg_layout_function_header)
+ {
+ set_first_insn (cfg_layout_function_header);
+ insn = cfg_layout_function_header;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
+
+ /* First do the bulk reordering -- rechain the blocks without regard to
+ the needed changes to jumps and labels. */
+
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb; bb = (basic_block) bb->aux)
+ {
+ if (BB_HEADER (bb))
+ {
+ if (insn)
+ NEXT_INSN (insn) = BB_HEADER (bb);
+ else
+ set_first_insn (BB_HEADER (bb));
+ PREV_INSN (BB_HEADER (bb)) = insn;
+ insn = BB_HEADER (bb);
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
+ if (insn)
+ NEXT_INSN (insn) = BB_HEAD (bb);
+ else
+ set_first_insn (BB_HEAD (bb));
+ PREV_INSN (BB_HEAD (bb)) = insn;
+ insn = BB_END (bb);
+ if (BB_FOOTER (bb))
+ {
+ NEXT_INSN (insn) = BB_FOOTER (bb);
+ PREV_INSN (BB_FOOTER (bb)) = insn;
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ }
+ }
+
+ NEXT_INSN (insn) = cfg_layout_function_footer;
+ if (cfg_layout_function_footer)
+ PREV_INSN (cfg_layout_function_footer) = insn;
+
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+
+ set_last_insn (insn);
+#ifdef ENABLE_CHECKING
+ verify_insn_chain ();
+#endif
+
+ /* Now add jumps and labels as needed to match the blocks new
+ outgoing edges. */
+
+ for (bb = ENTRY_BLOCK_PTR->next_bb; bb ; bb = (basic_block) bb->aux)
+ {
+ edge e_fall, e_taken, e;
+ rtx bb_end_insn;
+ rtx ret_label = NULL_RTX;
+ basic_block nb, src_bb;
+ edge_iterator ei;
+
+ if (EDGE_COUNT (bb->succs) == 0)
+ continue;
+
+ /* Find the old fallthru edge, and another non-EH edge for
+ a taken jump. */
+ e_taken = e_fall = NULL;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->flags & EDGE_FALLTHRU)
+ e_fall = e;
+ else if (! (e->flags & EDGE_EH))
+ e_taken = e;
+
+ bb_end_insn = BB_END (bb);
+ if (JUMP_P (bb_end_insn))
+ {
+ ret_label = JUMP_LABEL (bb_end_insn);
+ if (any_condjump_p (bb_end_insn))
+ {
+ /* This might happen if the conditional jump has side
+ effects and could therefore not be optimized away.
+ Make the basic block to end with a barrier in order
+ to prevent rtl_verify_flow_info from complaining. */
+ if (!e_fall)
+ {
+ gcc_assert (!onlyjump_p (bb_end_insn)
+ || returnjump_p (bb_end_insn));
+ BB_FOOTER (bb) = emit_barrier_after (bb_end_insn);
+ continue;
+ }
+
+ /* If the old fallthru is still next, nothing to do. */
+ if (bb->aux == e_fall->dest
+ || e_fall->dest == EXIT_BLOCK_PTR)
+ continue;
+
+ /* The degenerated case of conditional jump jumping to the next
+ instruction can happen for jumps with side effects. We need
+ to construct a forwarder block and this will be done just
+ fine by force_nonfallthru below. */
+ if (!e_taken)
+ ;
+
+ /* There is another special case: if *neither* block is next,
+ such as happens at the very end of a function, then we'll
+ need to add a new unconditional jump. Choose the taken
+ edge based on known or assumed probability. */
+ else if (bb->aux != e_taken->dest)
+ {
+ rtx note = find_reg_note (bb_end_insn, REG_BR_PROB, 0);
+
+ if (note
+ && INTVAL (XEXP (note, 0)) < REG_BR_PROB_BASE / 2
+ && invert_jump (bb_end_insn,
+ (e_fall->dest == EXIT_BLOCK_PTR
+ ? NULL_RTX
+ : label_for_bb (e_fall->dest)), 0))
+ {
+ e_fall->flags &= ~EDGE_FALLTHRU;
+ gcc_checking_assert (could_fall_through
+ (e_taken->src, e_taken->dest));
+ e_taken->flags |= EDGE_FALLTHRU;
+ update_br_prob_note (bb);
+ e = e_fall, e_fall = e_taken, e_taken = e;
+ }
+ }
+
+ /* If the "jumping" edge is a crossing edge, and the fall
+ through edge is non-crossing, leave things as they are. */
+ else if ((e_taken->flags & EDGE_CROSSING)
+ && !(e_fall->flags & EDGE_CROSSING))
+ continue;
+
+ /* Otherwise we can try to invert the jump. This will
+ basically never fail, however, keep up the pretense. */
+ else if (invert_jump (bb_end_insn,
+ (e_fall->dest == EXIT_BLOCK_PTR
+ ? NULL_RTX
+ : label_for_bb (e_fall->dest)), 0))
+ {
+ e_fall->flags &= ~EDGE_FALLTHRU;
+ gcc_checking_assert (could_fall_through
+ (e_taken->src, e_taken->dest));
+ e_taken->flags |= EDGE_FALLTHRU;
+ update_br_prob_note (bb);
+ if (LABEL_NUSES (ret_label) == 0
+ && single_pred_p (e_taken->dest))
+ delete_insn (ret_label);
+ continue;
+ }
+ }
+ else if (extract_asm_operands (PATTERN (bb_end_insn)) != NULL)
+ {
+ /* If the old fallthru is still next or if
+ asm goto doesn't have a fallthru (e.g. when followed by
+ __builtin_unreachable ()), nothing to do. */
+ if (! e_fall
+ || bb->aux == e_fall->dest
+ || e_fall->dest == EXIT_BLOCK_PTR)
+ continue;
+
+ /* Otherwise we'll have to use the fallthru fixup below. */
+ }
+ else
+ {
+ /* Otherwise we have some return, switch or computed
+ jump. In the 99% case, there should not have been a
+ fallthru edge. */
+ gcc_assert (returnjump_p (bb_end_insn) || !e_fall);
+ continue;
+ }
+ }
+ else
+ {
+ /* No fallthru implies a noreturn function with EH edges, or
+ something similarly bizarre. In any case, we don't need to
+ do anything. */
+ if (! e_fall)
+ continue;
+
+ /* If the fallthru block is still next, nothing to do. */
+ if (bb->aux == e_fall->dest)
+ continue;
+
+ /* A fallthru to exit block. */
+ if (e_fall->dest == EXIT_BLOCK_PTR)
+ continue;
+ }
+
+ /* We got here if we need to add a new jump insn.
+ Note force_nonfallthru can delete E_FALL and thus we have to
+ save E_FALL->src prior to the call to force_nonfallthru. */
+ src_bb = e_fall->src;
+ nb = force_nonfallthru_and_redirect (e_fall, e_fall->dest, ret_label);
+ if (nb)
+ {
+ nb->aux = bb->aux;
+ bb->aux = nb;
+ /* Don't process this new block. */
+ bb = nb;
+
+ /* Make sure new bb is tagged for correct section (same as
+ fall-thru source, since you cannot fall-thru across
+ section boundaries). */
+ BB_COPY_PARTITION (src_bb, single_pred (bb));
+ if (flag_reorder_blocks_and_partition
+ && targetm_common.have_named_sections
+ && JUMP_P (BB_END (bb))
+ && !any_condjump_p (BB_END (bb))
+ && (EDGE_SUCC (bb, 0)->flags & EDGE_CROSSING))
+ add_reg_note (BB_END (bb), REG_CROSSING_JUMP, NULL_RTX);
+ }
+ }
+
+ relink_block_chain (/*stay_in_cfglayout_mode=*/false);
+
+ /* Annoying special case - jump around dead jumptables left in the code. */
+ FOR_EACH_BB (bb)
+ {
+ edge e = find_fallthru_edge (bb->succs);
+
+ if (e && !can_fallthru (e->src, e->dest))
+ force_nonfallthru (e);
+ }
+
+ /* Ensure goto_locus from edges has some instructions with that locus
+ in RTL. */
+ if (!optimize)
+ FOR_EACH_BB (bb)
+ {
+ edge e;
+ edge_iterator ei;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (e->goto_locus && !(e->flags & EDGE_ABNORMAL))
+ {
+ edge e2;
+ edge_iterator ei2;
+ basic_block dest, nb;
+ rtx end;
+
+ insn = BB_END (e->src);
+ end = PREV_INSN (BB_HEAD (e->src));
+ while (insn != end
+ && (!NONDEBUG_INSN_P (insn) || INSN_LOCATOR (insn) == 0))
+ insn = PREV_INSN (insn);
+ if (insn != end
+ && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
+ continue;
+ if (simplejump_p (BB_END (e->src))
+ && INSN_LOCATOR (BB_END (e->src)) == 0)
+ {
+ INSN_LOCATOR (BB_END (e->src)) = e->goto_locus;
+ continue;
+ }
+ dest = e->dest;
+ if (dest == EXIT_BLOCK_PTR)
+ {
+ /* Non-fallthru edges to the exit block cannot be split. */
+ if (!(e->flags & EDGE_FALLTHRU))
+ continue;
+ }
+ else
+ {
+ insn = BB_HEAD (dest);
+ end = NEXT_INSN (BB_END (dest));
+ while (insn != end && !NONDEBUG_INSN_P (insn))
+ insn = NEXT_INSN (insn);
+ if (insn != end && INSN_LOCATOR (insn)
+ && locator_eq (INSN_LOCATOR (insn), (int) e->goto_locus))
+ continue;
+ }
+ nb = split_edge (e);
+ if (!INSN_P (BB_END (nb)))
+ BB_END (nb) = emit_insn_after_noloc (gen_nop (), BB_END (nb),
+ nb);
+ INSN_LOCATOR (BB_END (nb)) = e->goto_locus;
+
+ /* If there are other incoming edges to the destination block
+ with the same goto locus, redirect them to the new block as
+ well, this can prevent other such blocks from being created
+ in subsequent iterations of the loop. */
+ for (ei2 = ei_start (dest->preds); (e2 = ei_safe_edge (ei2)); )
+ if (e2->goto_locus
+ && !(e2->flags & (EDGE_ABNORMAL | EDGE_FALLTHRU))
+ && locator_eq (e->goto_locus, e2->goto_locus))
+ redirect_edge_and_branch (e2, nb);
+ else
+ ei_next (&ei2);
+ }
+ }
+}
+
+/* Perform sanity checks on the insn chain.
+ 1. Check that next/prev pointers are consistent in both the forward and
+ reverse direction.
+ 2. Count insns in chain, going both directions, and check if equal.
+ 3. Check that get_last_insn () returns the actual end of chain. */
+
+DEBUG_FUNCTION void
+verify_insn_chain (void)
+{
+ rtx x, prevx, nextx;
+ int insn_cnt1, insn_cnt2;
+
+ for (prevx = NULL, insn_cnt1 = 1, x = get_insns ();
+ x != 0;
+ prevx = x, insn_cnt1++, x = NEXT_INSN (x))
+ gcc_assert (PREV_INSN (x) == prevx);
+
+ gcc_assert (prevx == get_last_insn ());
+
+ for (nextx = NULL, insn_cnt2 = 1, x = get_last_insn ();
+ x != 0;
+ nextx = x, insn_cnt2++, x = PREV_INSN (x))
+ gcc_assert (NEXT_INSN (x) == nextx);
+
+ gcc_assert (insn_cnt1 == insn_cnt2);
+}
+
+/* If we have assembler epilogues, the block falling through to exit must
+ be the last one in the reordered chain when we reach final. Ensure
+ that this condition is met. */
+static void
+fixup_fallthru_exit_predecessor (void)
+{
+ edge e;
+ basic_block bb = NULL;
+
+ /* This transformation is not valid before reload, because we might
+ separate a call from the instruction that copies the return
+ value. */
+ gcc_assert (reload_completed);
+
+ e = find_fallthru_edge (EXIT_BLOCK_PTR->preds);
+ if (e)
+ bb = e->src;
+
+ if (bb && bb->aux)
+ {
+ basic_block c = ENTRY_BLOCK_PTR->next_bb;
+
+ /* If the very first block is the one with the fall-through exit
+ edge, we have to split that block. */
+ if (c == bb)
+ {
+ bb = split_block (bb, NULL)->dest;
+ bb->aux = c->aux;
+ c->aux = bb;
+ BB_FOOTER (bb) = BB_FOOTER (c);
+ BB_FOOTER (c) = NULL;
+ }
+
+ while (c->aux != bb)
+ c = (basic_block) c->aux;
+
+ c->aux = bb->aux;
+ while (c->aux)
+ c = (basic_block) c->aux;
+
+ c->aux = bb;
+ bb->aux = NULL;
+ }
+}
+
+/* In case there are more than one fallthru predecessors of exit, force that
+ there is only one. */
+
+static void
+force_one_exit_fallthru (void)
+{
+ edge e, predecessor = NULL;
+ bool more = false;
+ edge_iterator ei;
+ basic_block forwarder, bb;
+
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ if (predecessor == NULL)
+ predecessor = e;
+ else
+ {
+ more = true;
+ break;
+ }
+ }
+
+ if (!more)
+ return;
+
+ /* Exit has several fallthru predecessors. Create a forwarder block for
+ them. */
+ forwarder = split_edge (predecessor);
+ for (ei = ei_start (EXIT_BLOCK_PTR->preds); (e = ei_safe_edge (ei)); )
+ {
+ if (e->src == forwarder
+ || !(e->flags & EDGE_FALLTHRU))
+ ei_next (&ei);
+ else
+ redirect_edge_and_branch_force (e, forwarder);
+ }
+
+ /* Fix up the chain of blocks -- make FORWARDER immediately precede the
+ exit block. */
+ FOR_EACH_BB (bb)
+ {
+ if (bb->aux == NULL && bb != forwarder)
+ {
+ bb->aux = forwarder;
+ break;
+ }
+ }
+}
+
+/* Return true in case it is possible to duplicate the basic block BB. */
+
+static bool
+cfg_layout_can_duplicate_bb_p (const_basic_block bb)
+{
+ /* Do not attempt to duplicate tablejumps, as we need to unshare
+ the dispatch table. This is difficult to do, as the instructions
+ computing jump destination may be hoisted outside the basic block. */
+ if (tablejump_p (BB_END (bb), NULL, NULL))
+ return false;
+
+ /* Do not duplicate blocks containing insns that can't be copied. */
+ if (targetm.cannot_copy_insn_p)
+ {
+ rtx insn = BB_HEAD (bb);
+ while (1)
+ {
+ if (INSN_P (insn) && targetm.cannot_copy_insn_p (insn))
+ return false;
+ if (insn == BB_END (bb))
+ break;
+ insn = NEXT_INSN (insn);
+ }
+ }
+
+ return true;
+}
+
+rtx
+duplicate_insn_chain (rtx from, rtx to)
+{
+ rtx insn, last, copy;
+
+ /* Avoid updating of boundaries of previous basic block. The
+ note will get removed from insn stream in fixup. */
+ last = emit_note (NOTE_INSN_DELETED);
+
+ /* Create copy at the end of INSN chain. The chain will
+ be reordered later. */
+ for (insn = from; insn != NEXT_INSN (to); insn = NEXT_INSN (insn))
+ {
+ switch (GET_CODE (insn))
+ {
+ case DEBUG_INSN:
+ /* Don't duplicate label debug insns. */
+ if (TREE_CODE (INSN_VAR_LOCATION_DECL (insn)) == LABEL_DECL)
+ break;
+ /* FALLTHRU */
+ case INSN:
+ case CALL_INSN:
+ case JUMP_INSN:
+ /* Avoid copying of dispatch tables. We never duplicate
+ tablejumps, so this can hit only in case the table got
+ moved far from original jump. */
+ if (GET_CODE (PATTERN (insn)) == ADDR_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
+ {
+ /* Avoid copying following barrier as well if any
+ (and debug insns in between). */
+ rtx next;
+
+ for (next = NEXT_INSN (insn);
+ next != NEXT_INSN (to);
+ next = NEXT_INSN (next))
+ if (!DEBUG_INSN_P (next))
+ break;
+ if (next != NEXT_INSN (to) && BARRIER_P (next))
+ insn = next;
+ break;
+ }
+ copy = emit_copy_of_insn_after (insn, get_last_insn ());
+ if (JUMP_P (insn) && JUMP_LABEL (insn) != NULL_RTX
+ && ANY_RETURN_P (JUMP_LABEL (insn)))
+ JUMP_LABEL (copy) = JUMP_LABEL (insn);
+ maybe_copy_prologue_epilogue_insn (insn, copy);
+ break;
+
+ case CODE_LABEL:
+ break;
+
+ case BARRIER:
+ emit_barrier ();
+ break;
+
+ case NOTE:
+ switch (NOTE_KIND (insn))
+ {
+ /* In case prologue is empty and function contain label
+ in first BB, we may want to copy the block. */
+ case NOTE_INSN_PROLOGUE_END:
+
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_DELETED_LABEL:
+ case NOTE_INSN_DELETED_DEBUG_LABEL:
+ /* No problem to strip these. */
+ case NOTE_INSN_FUNCTION_BEG:
+ /* There is always just single entry to function. */
+ case NOTE_INSN_BASIC_BLOCK:
+ break;
+
+ case NOTE_INSN_EPILOGUE_BEG:
+ case NOTE_INSN_SWITCH_TEXT_SECTIONS:
+ emit_note_copy (insn);
+ break;
+
+ default:
+ /* All other notes should have already been eliminated. */
+ gcc_unreachable ();
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ insn = NEXT_INSN (last);
+ delete_insn (last);
+ return insn;
+}
+
+/* Create a duplicate of the basic block BB. */
+
+static basic_block
+cfg_layout_duplicate_bb (basic_block bb)
+{
+ rtx insn;
+ basic_block new_bb;
+
+ insn = duplicate_insn_chain (BB_HEAD (bb), BB_END (bb));
+ new_bb = create_basic_block (insn,
+ insn ? get_last_insn () : NULL,
+ EXIT_BLOCK_PTR->prev_bb);
+
+ BB_COPY_PARTITION (new_bb, bb);
+ if (BB_HEADER (bb))
+ {
+ insn = BB_HEADER (bb);
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ insn = duplicate_insn_chain (BB_HEADER (bb), insn);
+ if (insn)
+ BB_HEADER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+ }
+
+ if (BB_FOOTER (bb))
+ {
+ insn = BB_FOOTER (bb);
+ while (NEXT_INSN (insn))
+ insn = NEXT_INSN (insn);
+ insn = duplicate_insn_chain (BB_FOOTER (bb), insn);
+ if (insn)
+ BB_FOOTER (new_bb) = unlink_insn_chain (insn, get_last_insn ());
+ }
+
+ return new_bb;
+}
+
+
+/* Main entry point to this module - initialize the datastructures for
+ CFG layout changes. It keeps LOOPS up-to-date if not null.
+
+ FLAGS is a set of additional flags to pass to cleanup_cfg(). */
+
+void
+cfg_layout_initialize (unsigned int flags)
+{
+ rtx x;
+ basic_block bb;
+
+ initialize_original_copy_tables ();
+
+ cfg_layout_rtl_register_cfg_hooks ();
+
+ record_effective_endpoints ();
+
+ /* Make sure that the targets of non local gotos are marked. */
+ for (x = nonlocal_goto_handler_labels; x; x = XEXP (x, 1))
+ {
+ bb = BLOCK_FOR_INSN (XEXP (x, 0));
+ bb->flags |= BB_NON_LOCAL_GOTO_TARGET;
+ }
+
+ cleanup_cfg (CLEANUP_CFGLAYOUT | flags);
+}
+
+/* Splits superblocks. */
+void
+break_superblocks (void)
+{
+ sbitmap superblocks;
+ bool need = false;
+ basic_block bb;
+
+ superblocks = sbitmap_alloc (last_basic_block);
+ sbitmap_zero (superblocks);
+
+ FOR_EACH_BB (bb)
+ if (bb->flags & BB_SUPERBLOCK)
+ {
+ bb->flags &= ~BB_SUPERBLOCK;
+ SET_BIT (superblocks, bb->index);
+ need = true;
+ }
+
+ if (need)
+ {
+ rebuild_jump_labels (get_insns ());
+ find_many_sub_basic_blocks (superblocks);
+ }
+
+ free (superblocks);
+}
+
+/* Finalize the changes: reorder insn list according to the sequence specified
+ by aux pointers, enter compensation code, rebuild scope forest. */
+
+void
+cfg_layout_finalize (void)
+{
+#ifdef ENABLE_CHECKING
+ verify_flow_info ();
+#endif
+ force_one_exit_fallthru ();
+ rtl_register_cfg_hooks ();
+ if (reload_completed
+#ifdef HAVE_epilogue
+ && !HAVE_epilogue
+#endif
+ )
+ fixup_fallthru_exit_predecessor ();
+ fixup_reorder_chain ();
+
+ rebuild_jump_labels (get_insns ());
+ delete_dead_jumptables ();
+
+#ifdef ENABLE_CHECKING
+ verify_insn_chain ();
+ verify_flow_info ();
+#endif
+}
+
/* Same as split_block but update cfg_layout structures. */
@@ -3283,13 +4255,6 @@ rtl_can_remove_branch_p (const_edge e)
return true;
}
-/* We do not want to declare these functions in a header file, since they
- should only be used through the cfghooks interface, and we do not want to
- move them here since it would require also moving quite a lot of related
- code. They are in cfglayout.c. */
-extern bool cfg_layout_can_duplicate_bb_p (const_basic_block);
-extern basic_block cfg_layout_duplicate_bb (basic_block);
-
static basic_block
rtl_duplicate_bb (basic_block bb)
{
@@ -3369,3 +4334,5 @@ struct cfg_hooks cfg_layout_rtl_cfg_hooks = {
rtl_extract_cond_bb_edges, /* extract_cond_bb_edges */
NULL /* flush_pending_stmts */
};
+
+#include "gt-cfgrtl.h"
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 36f7306bae4..7892bf08877 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -50,7 +50,6 @@ along with GCC; see the file COPYING3. If not see
#include "debug.h"
#include "langhooks.h"
#include "splay-tree.h"
-#include "cfglayout.h"
#include "gimple.h"
#include "tree-flow.h"
#include "tree-stdarg.h"
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 3cef847c952..a24ba9006a1 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -51,7 +51,6 @@
#include "tm-constrs.h"
#include "gt-bfin.h"
#include "basic-block.h"
-#include "cfglayout.h"
#include "timevar.h"
#include "df.h"
#include "sel-sched.h"
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 978d0cba82b..6f16c6920f1 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -43,7 +43,6 @@
#include "function.h"
#include "diagnostic-core.h"
#include "cgraph.h"
-#include "cfglayout.h"
#include "langhooks.h"
#include "target.h"
#include "target-def.h"
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index e49ee2c74da..108050708bd 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -51,7 +51,6 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "hashtab.h"
#include "langhooks.h"
-#include "cfglayout.h"
#include "gimple.h"
#include "intl.h"
#include "df.h"
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 5bcb7a884ba..6e0f39c1d1c 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -51,7 +51,6 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "target-def.h"
#include "langhooks.h"
-#include "cfglayout.h"
#include "sched-int.h"
#include "gimple.h"
#include "bitmap.h"
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index ad9d4389d9b..0f23cd053d6 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -52,7 +52,6 @@
#include "common/common-target.h"
#include "langhooks.h"
#include "reload.h"
-#include "cfglayout.h"
#include "cfgloop.h"
#include "sched-int.h"
#include "gimple.h"
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index f912e54f218..100dccc7075 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -27,7 +27,7 @@ rs6000.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(OBSTACK_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) except.h function.h \
output.h dbxout.h $(BASIC_BLOCK_H) toplev.h $(GGC_H) $(HASHTAB_H) \
$(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h gt-rs6000.h \
- cfglayout.h cfgloop.h $(OPTS_H) $(COMMON_TARGET_H)
+ cfgloop.h $(OPTS_H) $(COMMON_TARGET_H)
rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
$(srcdir)/config/rs6000/rs6000-protos.h \
diff --git a/gcc/config/score/score.c b/gcc/config/score/score.c
index 9c68e19ed30..3d7bf49f081 100644
--- a/gcc/config/score/score.c
+++ b/gcc/config/score/score.c
@@ -46,7 +46,6 @@
#include "target.h"
#include "target-def.h"
#include "langhooks.h"
-#include "cfglayout.h"
#include "df.h"
#include "opts.h"
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index cdfd7b6bce8..49a69abe04a 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -46,7 +46,6 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "basic-block.h"
#include "df.h"
-#include "cfglayout.h"
#include "intl.h"
#include "sched-int.h"
#include "params.h"
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 7b1899d661c..08c9cc891b0 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -49,7 +49,6 @@ along with GCC; see the file COPYING3. If not see
#include "target.h"
#include "target-def.h"
#include "common/common-target.h"
-#include "cfglayout.h"
#include "gimple.h"
#include "langhooks.h"
#include "reload.h"
diff --git a/gcc/config/sparc/t-sparc b/gcc/config/sparc/t-sparc
index ea9d0e824e2..b7d4dacdcb6 100644
--- a/gcc/config/sparc/t-sparc
+++ b/gcc/config/sparc/t-sparc
@@ -23,7 +23,7 @@ sparc.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
insn-codes.h conditions.h output.h $(INSN_ATTR_H) $(FLAGS_H) \
$(FUNCTION_H) $(EXCEPT_H) $(EXPR_H) $(OPTABS_H) $(RECOG_H) \
$(DIAGNOSTIC_CORE_H) $(GGC_H) $(TM_P_H) debug.h $(TARGET_H) \
- $(TARGET_DEF_H) $(COMMON_TARGET_H) $(CFGLAYOUT_H) $(GIMPLE_H) \
+ $(TARGET_DEF_H) $(COMMON_TARGET_H) $(GIMPLE_H) \
langhooks.h reload.h $(PARAMS_H) $(DF_H) dwarf2out.h $(OPTS_H) \
gt-sparc.h
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index 5310ba7f2f0..0aa5cf4da1a 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -43,7 +43,6 @@
#include "target-def.h"
#include "langhooks.h"
#include "reload.h"
-#include "cfglayout.h"
#include "sched-int.h"
#include "params.h"
#include "machmode.h"
diff --git a/gcc/config/spu/t-spu-elf b/gcc/config/spu/t-spu-elf
index 84fbbb28ad2..0a0f7714a7d 100644
--- a/gcc/config/spu/t-spu-elf
+++ b/gcc/config/spu/t-spu-elf
@@ -23,7 +23,7 @@ spu.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
real.h insn-config.h conditions.h insn-attr.h flags.h $(RECOG_H) \
$(OBSTACK_H) $(TREE_H) $(EXPR_H) $(OPTABS_H) except.h function.h \
output.h $(BASIC_BLOCK_H) $(GGC_H) $(HASHTAB_H) \
- $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h cfglayout.h \
+ $(TM_P_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h reload.h \
$(srcdir)/config/spu/spu-protos.h \
$(srcdir)/config/spu/spu-builtins.def
diff --git a/gcc/ddg.c b/gcc/ddg.c
index a5158827638..853f5ea9184 100644
--- a/gcc/ddg.c
+++ b/gcc/ddg.c
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "sched-int.h"
#include "target.h"
-#include "cfglayout.h"
#include "cfgloop.h"
#include "sbitmap.h"
#include "expr.h"
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index e77fecf8808..56730e31d28 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -93,7 +93,6 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h"
#include "tree-pass.h"
#include "tree-flow.h"
-#include "cfglayout.h" /* for insn_scope. */
#include "opts.h"
static void dwarf2out_source_line (unsigned int, const char *, int, bool);
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 09be139dbd3..c82bd61c7e1 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -45,6 +45,7 @@ along with GCC; see the file COPYING3. If not see
#include "flags.h"
#include "function.h"
#include "expr.h"
+#include "vecprim.h"
#include "regs.h"
#include "hard-reg-set.h"
#include "hashtab.h"
@@ -59,7 +60,6 @@ along with GCC; see the file COPYING3. If not see
#include "df.h"
#include "params.h"
#include "target.h"
-#include "tree-flow.h"
struct target_rtl default_target_rtl;
#if SWITCHABLE_TARGET
@@ -147,7 +147,6 @@ static GTY ((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
#define cur_insn_uid (crtl->emit.x_cur_insn_uid)
#define cur_debug_insn_uid (crtl->emit.x_cur_debug_insn_uid)
-#define last_location (crtl->emit.x_last_location)
#define first_label_num (crtl->emit.x_first_label_num)
static rtx make_call_insn_raw (rtx);
@@ -4927,15 +4926,6 @@ gen_use (rtx x)
return seq;
}
-/* Cause next statement to emit a line note even if the line number
- has not changed. */
-
-void
-force_next_line_note (void)
-{
- last_location = -1;
-}
-
/* Place a note of KIND on insn INSN with DATUM as the datum. If a
note of this type already exists, remove it first. */
@@ -5404,7 +5394,6 @@ init_emit (void)
cur_insn_uid = 1;
cur_debug_insn_uid = 1;
reg_rtx_no = LAST_VIRTUAL_REGISTER + 1;
- last_location = UNKNOWN_LOCATION;
first_label_num = label_num;
seq_stack = NULL;
@@ -5929,4 +5918,247 @@ gen_hard_reg_clobber (enum machine_mode mode, unsigned int regno)
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (mode, regno)));
}
+/* Data structures representing mapping of INSN_LOCATOR into scope blocks, line
+ numbers and files. In order to be GGC friendly we need to use separate
+ varrays. This also slightly improve the memory locality in binary search.
+ The _locs array contains locators where the given property change. The
+ block_locators_blocks contains the scope block that is used for all insn
+ locator greater than corresponding block_locators_locs value and smaller
+ than the following one. Similarly for the other properties. */
+static VEC(int,heap) *block_locators_locs;
+static GTY(()) VEC(tree,gc) *block_locators_blocks;
+static VEC(int,heap) *locations_locators_locs;
+DEF_VEC_O(location_t);
+DEF_VEC_ALLOC_O(location_t,heap);
+static VEC(location_t,heap) *locations_locators_vals;
+int prologue_locator;
+int epilogue_locator;
+
+/* Hold current location information and last location information, so the
+ datastructures are built lazily only when some instructions in given
+ place are needed. */
+static location_t curr_location, last_location;
+static tree curr_block, last_block;
+static int curr_rtl_loc = -1;
+
+/* Allocate insn locator datastructure. */
+void
+insn_locators_alloc (void)
+{
+ prologue_locator = epilogue_locator = 0;
+
+ block_locators_locs = VEC_alloc (int, heap, 32);
+ block_locators_blocks = VEC_alloc (tree, gc, 32);
+ locations_locators_locs = VEC_alloc (int, heap, 32);
+ locations_locators_vals = VEC_alloc (location_t, heap, 32);
+
+ curr_location = UNKNOWN_LOCATION;
+ last_location = UNKNOWN_LOCATION;
+ curr_block = NULL;
+ last_block = NULL;
+ curr_rtl_loc = 0;
+}
+
+/* At the end of emit stage, clear current location. */
+void
+insn_locators_finalize (void)
+{
+ if (curr_rtl_loc >= 0)
+ epilogue_locator = curr_insn_locator ();
+ curr_rtl_loc = -1;
+}
+
+/* Allocate insn locator datastructure. */
+void
+insn_locators_free (void)
+{
+ prologue_locator = epilogue_locator = 0;
+
+ VEC_free (int, heap, block_locators_locs);
+ VEC_free (tree,gc, block_locators_blocks);
+ VEC_free (int, heap, locations_locators_locs);
+ VEC_free (location_t, heap, locations_locators_vals);
+}
+
+/* Set current location. */
+void
+set_curr_insn_source_location (location_t location)
+{
+ /* IV opts calls into RTL expansion to compute costs of operations. At this
+ time locators are not initialized. */
+ if (curr_rtl_loc == -1)
+ return;
+ curr_location = location;
+}
+
+/* Get current location. */
+location_t
+get_curr_insn_source_location (void)
+{
+ return curr_location;
+}
+
+/* Set current scope block. */
+void
+set_curr_insn_block (tree b)
+{
+ /* IV opts calls into RTL expansion to compute costs of operations. At this
+ time locators are not initialized. */
+ if (curr_rtl_loc == -1)
+ return;
+ if (b)
+ curr_block = b;
+}
+
+/* Get current scope block. */
+tree
+get_curr_insn_block (void)
+{
+ return curr_block;
+}
+
+/* Return current insn locator. */
+int
+curr_insn_locator (void)
+{
+ if (curr_rtl_loc == -1 || curr_location == UNKNOWN_LOCATION)
+ return 0;
+ if (last_block != curr_block)
+ {
+ curr_rtl_loc++;
+ VEC_safe_push (int, heap, block_locators_locs, curr_rtl_loc);
+ VEC_safe_push (tree, gc, block_locators_blocks, curr_block);
+ last_block = curr_block;
+ }
+ if (last_location != curr_location)
+ {
+ curr_rtl_loc++;
+ VEC_safe_push (int, heap, locations_locators_locs, curr_rtl_loc);
+ VEC_safe_push (location_t, heap, locations_locators_vals, &curr_location);
+ last_location = curr_location;
+ }
+ return curr_rtl_loc;
+}
+
+
+/* Return lexical scope block locator belongs to. */
+static tree
+locator_scope (int loc)
+{
+ int max = VEC_length (int, block_locators_locs);
+ int min = 0;
+
+ /* When block_locators_locs was initialized, the pro- and epilogue
+ insns didn't exist yet and can therefore not be found this way.
+ But we know that they belong to the outer most block of the
+ current function.
+ Without this test, the prologue would be put inside the block of
+ the first valid instruction in the function and when that first
+ insn is part of an inlined function then the low_pc of that
+ inlined function is messed up. Likewise for the epilogue and
+ the last valid instruction. */
+ if (loc == prologue_locator || loc == epilogue_locator)
+ return DECL_INITIAL (cfun->decl);
+
+ if (!max || !loc)
+ return NULL;
+ while (1)
+ {
+ int pos = (min + max) / 2;
+ int tmp = VEC_index (int, block_locators_locs, pos);
+
+ if (tmp <= loc && min != pos)
+ min = pos;
+ else if (tmp > loc && max != pos)
+ max = pos;
+ else
+ {
+ min = pos;
+ break;
+ }
+ }
+ return VEC_index (tree, block_locators_blocks, min);
+}
+
+/* Return lexical scope block insn belongs to. */
+tree
+insn_scope (const_rtx insn)
+{
+ return locator_scope (INSN_LOCATOR (insn));
+}
+
+/* Return line number of the statement specified by the locator. */
+location_t
+locator_location (int loc)
+{
+ int max = VEC_length (int, locations_locators_locs);
+ int min = 0;
+
+ while (1)
+ {
+ int pos = (min + max) / 2;
+ int tmp = VEC_index (int, locations_locators_locs, pos);
+
+ if (tmp <= loc && min != pos)
+ min = pos;
+ else if (tmp > loc && max != pos)
+ max = pos;
+ else
+ {
+ min = pos;
+ break;
+ }
+ }
+ return *VEC_index (location_t, locations_locators_vals, min);
+}
+
+/* Return source line of the statement that produced this insn. */
+int
+locator_line (int loc)
+{
+ expanded_location xloc;
+ if (!loc)
+ return 0;
+ else
+ xloc = expand_location (locator_location (loc));
+ return xloc.line;
+}
+
+/* Return line number of the statement that produced this insn. */
+int
+insn_line (const_rtx insn)
+{
+ return locator_line (INSN_LOCATOR (insn));
+}
+
+/* Return source file of the statement specified by LOC. */
+const char *
+locator_file (int loc)
+{
+ expanded_location xloc;
+ if (!loc)
+ return 0;
+ else
+ xloc = expand_location (locator_location (loc));
+ return xloc.file;
+}
+
+/* Return source file of the statement that produced this insn. */
+const char *
+insn_file (const_rtx insn)
+{
+ return locator_file (INSN_LOCATOR (insn));
+}
+
+/* Return true if LOC1 and LOC2 locators have the same location and scope. */
+bool
+locator_eq (int loc1, int loc2)
+{
+ if (loc1 == loc2)
+ return true;
+ if (locator_location (loc1) != locator_location (loc2))
+ return false;
+ return locator_scope (loc1) == locator_scope (loc2);
+}
+
#include "gt-emit-rtl.h"
diff --git a/gcc/final.c b/gcc/final.c
index fe1add226cb..f940b641bc1 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -72,7 +72,6 @@ along with GCC; see the file COPYING3. If not see
#include "targhooks.h"
#include "debug.h"
#include "expr.h"
-#include "cfglayout.h" /* for reemit_insn_block_notes */
#include "tree-pass.h"
#include "tree-flow.h"
#include "timevar.h"
@@ -1515,6 +1514,114 @@ dwarf2_debug_info_emitted_p (tree decl)
return true;
}
+/* Return scope resulting from combination of S1 and S2. */
+static tree
+choose_inner_scope (tree s1, tree s2)
+{
+ if (!s1)
+ return s2;
+ if (!s2)
+ return s1;
+ if (BLOCK_NUMBER (s1) > BLOCK_NUMBER (s2))
+ return s1;
+ return s2;
+}
+
+/* Emit lexical block notes needed to change scope from S1 to S2. */
+
+static void
+change_scope (rtx orig_insn, tree s1, tree s2)
+{
+ rtx insn = orig_insn;
+ tree com = NULL_TREE;
+ tree ts1 = s1, ts2 = s2;
+ tree s;
+
+ while (ts1 != ts2)
+ {
+ gcc_assert (ts1 && ts2);
+ if (BLOCK_NUMBER (ts1) > BLOCK_NUMBER (ts2))
+ ts1 = BLOCK_SUPERCONTEXT (ts1);
+ else if (BLOCK_NUMBER (ts1) < BLOCK_NUMBER (ts2))
+ ts2 = BLOCK_SUPERCONTEXT (ts2);
+ else
+ {
+ ts1 = BLOCK_SUPERCONTEXT (ts1);
+ ts2 = BLOCK_SUPERCONTEXT (ts2);
+ }
+ }
+ com = ts1;
+
+ /* Close scopes. */
+ s = s1;
+ while (s != com)
+ {
+ rtx note = emit_note_before (NOTE_INSN_BLOCK_END, insn);
+ NOTE_BLOCK (note) = s;
+ s = BLOCK_SUPERCONTEXT (s);
+ }
+
+ /* Open scopes. */
+ s = s2;
+ while (s != com)
+ {
+ insn = emit_note_before (NOTE_INSN_BLOCK_BEG, insn);
+ NOTE_BLOCK (insn) = s;
+ s = BLOCK_SUPERCONTEXT (s);
+ }
+}
+
+/* Rebuild all the NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes based
+ on the scope tree and the newly reordered instructions. */
+
+static void
+reemit_insn_block_notes (void)
+{
+ tree cur_block = DECL_INITIAL (cfun->decl);
+ rtx insn, note;
+
+ insn = get_insns ();
+ if (!active_insn_p (insn))
+ insn = next_active_insn (insn);
+ for (; insn; insn = next_active_insn (insn))
+ {
+ tree this_block;
+
+ /* Avoid putting scope notes between jump table and its label. */
+ if (JUMP_TABLE_DATA_P (insn))
+ continue;
+
+ this_block = insn_scope (insn);
+ /* For sequences compute scope resulting from merging all scopes
+ of instructions nested inside. */
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ {
+ int i;
+ rtx body = PATTERN (insn);
+
+ this_block = NULL;
+ for (i = 0; i < XVECLEN (body, 0); i++)
+ this_block = choose_inner_scope (this_block,
+ insn_scope (XVECEXP (body, 0, i)));
+ }
+ if (! this_block)
+ continue;
+
+ if (this_block != cur_block)
+ {
+ change_scope (insn, cur_block, this_block);
+ cur_block = this_block;
+ }
+ }
+
+ /* change_scope emits before the insn, not after. */
+ note = emit_note (NOTE_INSN_DELETED);
+ change_scope (note, cur_block, DECL_INITIAL (cfun->decl));
+ delete_insn (note);
+
+ reorder_blocks ();
+}
+
/* Output assembler code for the start of a function,
and initialize some of the variables in this file
for the new function. The label for the function and associated
diff --git a/gcc/function.c b/gcc/function.c
index 5f510f0bfed..41305c8518b 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -57,7 +57,6 @@ along with GCC; see the file COPYING3. If not see
#include "langhooks.h"
#include "target.h"
#include "common/common-target.h"
-#include "cfglayout.h"
#include "gimple.h"
#include "tree-pass.h"
#include "predict.h"
@@ -4852,9 +4851,6 @@ expand_function_start (tree subr)
/* If we are doing generic stack checking, the probe should go here. */
if (flag_stack_check == GENERIC_STACK_CHECK)
stack_check_probe_note = emit_note (NOTE_INSN_DELETED);
-
- /* Make sure there is a line number after the function entry setup code. */
- force_next_line_note ();
}
/* Undo the effects of init_dummy_function_start. */
@@ -4999,7 +4995,6 @@ expand_function_end (void)
/* Output a linenumber for the end of the function.
SDB depends on this. */
- force_next_line_note ();
set_curr_insn_source_location (input_location);
/* Before the return label (if any), clobber the return
diff --git a/gcc/function.h b/gcc/function.h
index f2fb099ea01..1c471d24071 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -70,10 +70,6 @@ struct GTY(()) emit_status {
--param min-nondebug-insn-uid=<value> is given with nonzero value. */
int x_cur_debug_insn_uid;
- /* Location the last line-number NOTE emitted.
- This is used to avoid generating duplicates. */
- location_t x_last_location;
-
/* The length of the regno_pointer_align, regno_decl, and x_regno_reg_rtx
vectors. Since these vectors are needed during the expansion phase when
the total number of registers in the function is not yet known, the
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 584712a2a7e..cd1a32c27e7 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1563,7 +1563,7 @@ open_base_files (void)
"hard-reg-set.h", "basic-block.h", "cselib.h", "insn-addr.h",
"optabs.h", "libfuncs.h", "debug.h", "ggc.h", "cgraph.h",
"tree-flow.h", "reload.h", "cpp-id-data.h", "tree-chrec.h",
- "cfglayout.h", "except.h", "output.h", "gimple.h", "cfgloop.h",
+ "except.h", "output.h", "gimple.h", "cfgloop.h",
"target.h", "ipa-prop.h", "lto-streamer.h", "target-globals.h",
"ipa-inline.h", "dwarf2out.h", NULL
};
diff --git a/gcc/hw-doloop.c b/gcc/hw-doloop.c
index dabcdcce495..ec1bedd4e4c 100644
--- a/gcc/hw-doloop.c
+++ b/gcc/hw-doloop.c
@@ -30,7 +30,6 @@ along with GCC; see the file COPYING3. If not see
#include "basic-block.h"
#include "tm_p.h"
#include "df.h"
-#include "cfglayout.h"
#include "cfgloop.h"
#include "recog.h"
#include "target.h"
diff --git a/gcc/loop-init.c b/gcc/loop-init.c
index 03f8f610c97..ee3d80c9479 100644
--- a/gcc/loop-init.c
+++ b/gcc/loop-init.c
@@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "basic-block.h"
#include "cfgloop.h"
-#include "cfglayout.h"
#include "tree-pass.h"
#include "timevar.h"
#include "flags.h"
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index 13f41cf19f4..139ccee6702 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "basic-block.h"
#include "cfgloop.h"
-#include "cfglayout.h"
#include "params.h"
#include "expr.h"
#include "hashtab.h"
diff --git a/gcc/loop-unswitch.c b/gcc/loop-unswitch.c
index 700dbfeb816..041a117df37 100644
--- a/gcc/loop-unswitch.c
+++ b/gcc/loop-unswitch.c
@@ -27,7 +27,6 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "basic-block.h"
#include "cfgloop.h"
-#include "cfglayout.h"
#include "params.h"
#include "expr.h"
diff --git a/gcc/modulo-sched.c b/gcc/modulo-sched.c
index 3dc87294bb6..953b78d763e 100644
--- a/gcc/modulo-sched.c
+++ b/gcc/modulo-sched.c
@@ -37,9 +37,7 @@ along with GCC; see the file COPYING3. If not see
#include "recog.h"
#include "sched-int.h"
#include "target.h"
-#include "cfglayout.h"
#include "cfgloop.h"
-#include "cfghooks.h"
#include "expr.h"
#include "params.h"
#include "gcov-io.h"
diff --git a/gcc/profile.c b/gcc/profile.c
index 927257b447f..ad3a2c31746 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -63,7 +63,6 @@ along with GCC; see the file COPYING3. If not see
#include "coverage.h"
#include "value-prof.h"
#include "tree.h"
-#include "cfghooks.h"
#include "tree-flow.h"
#include "timevar.h"
#include "cfgloop.h"
diff --git a/gcc/rtl.h b/gcc/rtl.h
index f9864cb4847..4acc23b3c45 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1799,7 +1799,7 @@ extern rtx skip_consecutive_labels (rtx);
extern rtx next_cc0_user (rtx);
extern rtx prev_cc0_setter (rtx);
-/* In cfglayout.c */
+/* In emit-rtl.c */
extern int insn_line (const_rtx);
extern const char * insn_file (const_rtx);
extern location_t locator_location (int);
@@ -1807,6 +1807,7 @@ extern int locator_line (int);
extern const char * locator_file (int);
extern bool locator_eq (int, int);
extern int prologue_locator, epilogue_locator;
+extern tree insn_scope (const_rtx);
/* In jump.c */
extern enum rtx_code reverse_condition (enum rtx_code);
@@ -2420,7 +2421,6 @@ extern void reorder_insns (rtx, rtx, rtx);
extern void reorder_insns_nobb (rtx, rtx, rtx);
extern int get_max_insn_count (void);
extern int in_sequence_p (void);
-extern void force_next_line_note (void);
extern void init_emit (void);
extern void init_emit_regs (void);
extern void init_emit_once (void);
@@ -2509,6 +2509,7 @@ extern int fixup_args_size_notes (rtx, rtx, int);
/* In cfgrtl.c */
extern void print_rtl_with_bb (FILE *, const_rtx);
+extern rtx duplicate_insn_chain (rtx, rtx);
/* In cfg.c. */
extern void dump_reg_info (FILE *);
diff --git a/gcc/sched-ebb.c b/gcc/sched-ebb.c
index 9f1f1127c81..372d1081b4f 100644
--- a/gcc/sched-ebb.c
+++ b/gcc/sched-ebb.c
@@ -36,7 +36,6 @@ along with GCC; see the file COPYING3. If not see
#include "insn-attr.h"
#include "except.h"
#include "recog.h"
-#include "cfglayout.h"
#include "params.h"
#include "sched-int.h"
#include "target.h"
diff --git a/gcc/sched-rgn.c b/gcc/sched-rgn.c
index 268eddcfd98..71cb25ede1e 100644
--- a/gcc/sched-rgn.c
+++ b/gcc/sched-rgn.c
@@ -60,7 +60,6 @@ along with GCC; see the file COPYING3. If not see
#include "insn-attr.h"
#include "except.h"
#include "recog.h"
-#include "cfglayout.h"
#include "params.h"
#include "sched-int.h"
#include "sel-sched.h"
diff --git a/gcc/tracer.c b/gcc/tracer.c
index b350fc09b3a..7ea67fa0c5e 100644
--- a/gcc/tracer.c
+++ b/gcc/tracer.c
@@ -42,7 +42,6 @@
#include "rtl.h"
#include "hard-reg-set.h"
#include "basic-block.h"
-#include "cfglayout.h"
#include "fibheap.h"
#include "flags.h"
#include "timevar.h"
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index fb7e300d149..d7ab090fe4b 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -39,7 +39,6 @@ along with GCC; see the file COPYING3. If not see
#include "diagnostic-core.h"
#include "except.h"
#include "cfgloop.h"
-#include "cfglayout.h" /* for can_copy_bbs_p and copy_bbs */
#include "tree-ssa-propagate.h"
#include "value-prof.h"
#include "pointer-set.h"
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 4394b2891bd..cefc9c0f934 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -772,12 +772,7 @@ extern void make_eh_edges (gimple);
extern bool make_eh_dispatch_edges (gimple);
extern edge redirect_eh_edge (edge, basic_block);
extern void redirect_eh_dispatch_edge (gimple, edge, basic_block);
-extern bool tree_could_trap_p (tree);
-extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
- bool, tree, bool *);
-extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
extern bool stmt_could_throw_p (gimple);
-extern bool tree_could_throw_p (tree);
extern bool stmt_can_throw_internal (gimple);
extern bool stmt_can_throw_external (gimple);
extern void add_stmt_to_eh_lp_fn (struct function *, gimple, int);
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 810c17cf347..9ac0d9a04eb 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -32,7 +32,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-flow.h"
#include "tree-dump.h"
#include "cfgloop.h"
-#include "cfglayout.h" /* for can_copy_bbs_p and copy_bbs */
#include "diagnostic-core.h"
#include "tree-scalar-evolution.h"
#include "tree-vectorizer.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index 8513e554f65..924689339a2 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -5212,6 +5212,12 @@ extern void expand_return (tree);
/* In tree-eh.c */
extern void using_eh_for_cleanups (void);
+extern bool tree_could_trap_p (tree);
+extern bool operation_could_trap_helper_p (enum tree_code, bool, bool, bool,
+ bool, tree, bool *);
+extern bool operation_could_trap_p (enum tree_code, bool, bool, tree);
+extern bool tree_could_throw_p (tree);
+
/* Compare and hash for any structure which begins with a canonical
pointer. Assumes all pointers are interchangeable, which is sort
of already assumed by gcc elsewhere IIRC. */