summaryrefslogtreecommitdiff
path: root/gcc/function.c
diff options
context:
space:
mode:
authordberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-11 18:02:15 +0000
committerdberlin <dberlin@138bc75d-0d04-0410-961f-82ee72b054a4>2007-06-11 18:02:15 +0000
commit3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b (patch)
treefdb9e9f8a0700a2713dc690fed1a2cf20dae8392 /gcc/function.c
parent8ceb1bfd33bc40bf0cbe1fab8903c2c31efd10ee (diff)
downloadgcc-3072d30e7983a3ca5ad030f1f98a5c39bcc2c07b.tar.gz
Merge dataflow branch into mainline
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@125624 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/function.c')
-rw-r--r--gcc/function.c128
1 files changed, 111 insertions, 17 deletions
diff --git a/gcc/function.c b/gcc/function.c
index 7d2063c3a22..10fe7febe6c 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -63,6 +63,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "tree-gimple.h"
#include "tree-pass.h"
#include "predict.h"
+#include "df.h"
+#include "timevar.h"
#include "vecprim.h"
#ifndef LOCAL_ALIGNMENT
@@ -100,7 +102,7 @@ int current_function_is_leaf;
/* Nonzero if function being compiled doesn't modify the stack pointer
(ignoring the prologue and epilogue). This is only valid after
- life_analysis has run. */
+ pass_stack_ptr_mod has run. */
int current_function_sp_is_unchanging;
/* Nonzero if the function being compiled is a leaf function which only
@@ -3485,13 +3487,32 @@ pad_below (struct args_size *offset_ptr, enum machine_mode passed_mode, tree siz
}
}
-/* Walk the tree of blocks describing the binding levels within a function
- and warn about variables the might be killed by setjmp or vfork.
- This is done after calling flow_analysis and before global_alloc
- clobbers the pseudo-regs to hard regs. */
-void
-setjmp_vars_warning (tree block)
+/* True if register REGNO was alive at a place where `setjmp' was
+ called and was set more than once or is an argument. Such regs may
+ be clobbered by `longjmp'. */
+
+static bool
+regno_clobbered_at_setjmp (bitmap setjmp_crosses, int regno)
+{
+ /* There appear to be cases where some local vars never reach the
+ backend but have bogus regnos. */
+ if (regno >= max_reg_num ())
+ return false;
+
+ return ((REG_N_SETS (regno) > 1
+ || REGNO_REG_SET_P (df_get_live_out (ENTRY_BLOCK_PTR), regno))
+ && REGNO_REG_SET_P (setjmp_crosses, regno));
+}
+
+/* Walk the tree of blocks describing the binding levels within a
+ function and warn about variables the might be killed by setjmp or
+ vfork. This is done after calling flow_analysis before register
+ allocation since that will clobber the pseudo-regs to hard
+ regs. */
+
+static void
+setjmp_vars_warning (bitmap setjmp_crosses, tree block)
{
tree decl, sub;
@@ -3500,32 +3521,47 @@ setjmp_vars_warning (tree block)
if (TREE_CODE (decl) == VAR_DECL
&& DECL_RTL_SET_P (decl)
&& REG_P (DECL_RTL (decl))
- && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
+ && regno_clobbered_at_setjmp (setjmp_crosses, REGNO (DECL_RTL (decl))))
warning (OPT_Wclobbered, "variable %q+D might be clobbered by"
" %<longjmp%> or %<vfork%>", decl);
}
for (sub = BLOCK_SUBBLOCKS (block); sub; sub = TREE_CHAIN (sub))
- setjmp_vars_warning (sub);
+ setjmp_vars_warning (setjmp_crosses, sub);
}
/* Do the appropriate part of setjmp_vars_warning
but for arguments instead of local variables. */
-void
-setjmp_args_warning (void)
+static void
+setjmp_args_warning (bitmap setjmp_crosses)
{
tree decl;
for (decl = DECL_ARGUMENTS (current_function_decl);
decl; decl = TREE_CHAIN (decl))
if (DECL_RTL (decl) != 0
&& REG_P (DECL_RTL (decl))
- && regno_clobbered_at_setjmp (REGNO (DECL_RTL (decl))))
+ && regno_clobbered_at_setjmp (setjmp_crosses, REGNO (DECL_RTL (decl))))
warning (OPT_Wclobbered,
"argument %q+D might be clobbered by %<longjmp%> or %<vfork%>",
decl);
}
+/* Generate warning messages for variables live across setjmp. */
+
+void
+generate_setjmp_warnings (void)
+{
+ bitmap setjmp_crosses = regstat_get_setjmp_crosses ();
+
+ if (n_basic_blocks == NUM_FIXED_BLOCKS
+ || bitmap_empty_p (setjmp_crosses))
+ return;
+
+ setjmp_vars_warning (setjmp_crosses, DECL_INITIAL (current_function_decl));
+ setjmp_args_warning (setjmp_crosses);
+}
+
/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
and create duplicate blocks. */
@@ -4328,6 +4364,14 @@ expand_function_end (void)
if (flag_exceptions)
sjlj_emit_function_exit_after (get_last_insn ());
}
+ else
+ {
+ /* We want to ensure that instructions that may trap are not
+ moved into the epilogue by scheduling, because we don't
+ always emit unwind information for the epilogue. */
+ if (flag_non_call_exceptions)
+ emit_insn (gen_blockage ());
+ }
/* If this is an implementation of throw, do what's necessary to
communicate between __builtin_eh_return and the epilogue. */
@@ -4782,7 +4826,7 @@ keep_stack_depressed (rtx insns)
&& !fixed_regs[regno]
&& TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)
&& !REGNO_REG_SET_P
- (EXIT_BLOCK_PTR->il.rtl->global_live_at_start, regno)
+ (DF_LR_IN (EXIT_BLOCK_PTR), regno)
&& !refers_to_regno_p (regno,
end_hard_regno (Pmode, regno),
info.equiv_reg_src, NULL)
@@ -4993,8 +5037,8 @@ emit_equiv_load (struct epi_info *p)
this into place with notes indicating where the prologue ends and where
the epilogue begins. Update the basic block information when possible. */
-void
-thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
+static void
+thread_prologue_and_epilogue_insns (void)
{
int inserted = 0;
edge e;
@@ -5016,6 +5060,11 @@ thread_prologue_and_epilogue_insns (rtx f ATTRIBUTE_UNUSED)
seq = gen_prologue ();
emit_insn (seq);
+ /* Insert an explicit USE for the frame pointer
+ if the profiling is on and the frame pointer is required. */
+ if (current_function_profile && frame_pointer_needed)
+ emit_insn (gen_rtx_USE (VOIDmode, hard_frame_pointer_rtx));
+
/* Retain a map of the prologue insns. */
record_insns (seq, &prologue);
prologue_end = emit_note (NOTE_INSN_PROLOGUE_END);
@@ -5254,13 +5303,18 @@ epilogue_done:
}
}
#endif
+
+ /* Threading the prologue and epilogue changes the artificial refs
+ in the entry and exit blocks. */
+ epilogue_completed = 1;
+ df_update_entry_exit_and_calls ();
}
/* Reposition the prologue-end and epilogue-begin notes after instruction
scheduling and delayed branch scheduling. */
void
-reposition_prologue_and_epilogue_notes (rtx f ATTRIBUTE_UNUSED)
+reposition_prologue_and_epilogue_notes (void)
{
#if defined (HAVE_prologue) || defined (HAVE_epilogue)
rtx insn, last, note;
@@ -5273,7 +5327,7 @@ reposition_prologue_and_epilogue_notes (rtx f ATTRIBUTE_UNUSED)
/* Scan from the beginning until we reach the last prologue insn.
We apparently can't depend on basic_block_{head,end} after
reorg has run. */
- for (insn = f; insn; insn = NEXT_INSN (insn))
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (NOTE_P (insn))
{
@@ -5354,6 +5408,13 @@ current_function_name (void)
{
return lang_hooks.decl_printable_name (cfun->decl, 2);
}
+
+/* Returns the raw (mangled) name of the current function. */
+const char *
+current_function_assembler_name (void)
+{
+ return IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (cfun->decl));
+}
static unsigned int
@@ -5411,5 +5472,38 @@ struct tree_opt_pass pass_leaf_regs =
0 /* letter */
};
+static unsigned int
+rest_of_handle_thread_prologue_and_epilogue (void)
+{
+ if (optimize)
+ cleanup_cfg (CLEANUP_EXPENSIVE);
+ /* On some machines, the prologue and epilogue code, or parts thereof,
+ can be represented as RTL. Doing so lets us schedule insns between
+ it and the rest of the code and also allows delayed branch
+ scheduling to operate in the epilogue. */
+
+ thread_prologue_and_epilogue_insns ();
+ return 0;
+}
+
+struct tree_opt_pass pass_thread_prologue_and_epilogue =
+{
+ "pro_and_epilogue", /* name */
+ NULL, /* gate */
+ rest_of_handle_thread_prologue_and_epilogue, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_THREAD_PROLOGUE_AND_EPILOGUE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ TODO_verify_flow, /* todo_flags_start */
+ TODO_dump_func |
+ TODO_df_finish |
+ TODO_ggc_collect, /* todo_flags_finish */
+ 'w' /* letter */
+};
+
#include "gt-function.h"