Commit 969d70ca by Jan Hubicka

cfglayout.c (function_tail_eff_head): Rename to ...

	* cfglayout.c (function_tail_eff_head): Rename to ...
	(function_footer): ... this one.
	(unlink_insn_chain): New functions.
	(label_for_bb): Only call block_label and emit debug message.
	(record_effective_endpoints): Actually unlink the headers and footers.
	(fixup_reorder_cahin): Re-insert the unlinked sequences.
	(cfg_layout_duplicate_bb): Use duplicate_insn_chain.
	* cfglayout.h (struct reorder_block_def): New fields footer/header;
	remove eff_head/eff_end.
	* rtl.h (set_first_insn): Declare.
	* emit-rtl.c (set_first_insn): New function.

	* cfglayout.c (fixup_reorder_chain): Dump duplicated
	(cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
	cfg_layout_duplicate_bb): New global function.
	(duplicate_insn_chain): New static function.
	* cfglayout.h (cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
	cfg_layout_duplicate_bb): Declare.
	(struct reorder_block_def): Add "original" field.
	* emit-rtl.c (emit_copy_of_insn_after): New function.
	* rtl.h (emit_copy_of_insn_after): Declare.

	* cfglayout.c (fixup_fallthru_exit_predecessor): Kill.
	(fixup_reorder_chain): properly handle edges to exit block.

Wed May  8 11:10:31 CEST 2002  Zdenek Dvorak  <rakdver@atrey.karlin.mff.cuni.cz>
			       Jan Hubicka  <jh@suse.cz>

	* basic-block.h (note_prediction_to_br_prob): declare.
	* c-semantics.c: Inlucde predit.h
	(expand_stmt): predict GOTO_STMT as not taken.
	* cfgcleanup.c: (delete_unreachable_blocks): Make global.
	(cleanup_cfg): Do not free tail_recursion_list.
	* cfgrtl.c (can_delete_note_p): Delete NOTE_INSN_PREDICTION.
	(flow_delete_block): Kill predictions past end of basic block.
	* output.h (delete_unreachable_blocks): Declare.
	* predict.c (predicted_by_p, process_note_predictions,
	process_note_prediction, last_block_p): New function.
	(estimate_probability): Bypass loop on PRED_CONTINUE;
	do not handle noreturn heuristics; kill PRED_RETURN; add
	PRED_EARLY_RETURN.
	* predict.def (PRED_CONTINUE, PRED_EARLY_RETURN, PRED_GOTO,
	PRED_CONST_RETURN, PRED_NEGATIVE_RETURN, PRED_NULL_RETURN): New.
	* predict.h (IS_TAKEN): New constant.
	* print-rtl.c (print_rtx): Pretty print NOTE_INSN_PREDICTION.
	* rtl.c (NOTE_INSN_PREDICTION): New.
	* rtl.h (NOTE_PREDICTION, NOTE_PREDICTION_ALG, NOTE_PREDICTION_FLAGS):
	New macro.
	(insn_note): add NOTE_INSN_PREDICTION.
	* sibcall.c (optimize_sibling_and_tail_recursive_call): Do not build
	CFG; free tail_recursion_label_list.
	* stmt.c: Include predict.h;
	(return_prediction): New.
	(expand_value_return): Use it.
	* toplev.c: Lower NOTE_INSN_PREDICTION before sibcall.

From-SVN: r53285
parent 41f8d041
Wed May 8 11:08:50 CEST 2002 Jan Hubicka <jh@suse.cz>
* cfglayout.c (function_tail_eff_head): Rename to ...
(function_footer): ... this one.
(unlink_insn_chain): New functions.
(label_for_bb): Only call block_label and emit debug message.
(record_effective_endpoints): Actually unlink the headers and footers.
(fixup_reorder_cahin): Re-insert the unlinked sequences.
(cfg_layout_duplicate_bb): Use duplicate_insn_chain.
* cfglayout.h (struct reorder_block_def): New fields footer/header;
remove eff_head/eff_end.
* rtl.h (set_first_insn): Declare.
* emit-rtl.c (set_first_insn): New function.
* cfglayout.c (fixup_reorder_chain): Dump duplicated
(cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
cfg_layout_duplicate_bb): New global function.
(duplicate_insn_chain): New static function.
* cfglayout.h (cfg_layout_can_duplicate_bb_p, cfg_layout_rerirect_edge,
cfg_layout_duplicate_bb): Declare.
(struct reorder_block_def): Add "original" field.
* emit-rtl.c (emit_copy_of_insn_after): New function.
* rtl.h (emit_copy_of_insn_after): Declare.
* cfglayout.c (fixup_fallthru_exit_predecessor): Kill.
(fixup_reorder_chain): properly handle edges to exit block.
Wed May 8 11:10:31 CEST 2002 Zdenek Dvorak <rakdver@atrey.karlin.mff.cuni.cz>
Jan Hubicka <jh@suse.cz>
* basic-block.h (note_prediction_to_br_prob): declare.
* c-semantics.c: Inlucde predit.h
(expand_stmt): predict GOTO_STMT as not taken.
* cfgcleanup.c: (delete_unreachable_blocks): Make global.
(cleanup_cfg): Do not free tail_recursion_list.
* cfgrtl.c (can_delete_note_p): Delete NOTE_INSN_PREDICTION.
(flow_delete_block): Kill predictions past end of basic block.
* output.h (delete_unreachable_blocks): Declare.
* predict.c (predicted_by_p, process_note_predictions,
process_note_prediction, last_block_p): New function.
(estimate_probability): Bypass loop on PRED_CONTINUE;
do not handle noreturn heuristics; kill PRED_RETURN; add
PRED_EARLY_RETURN.
* predict.def (PRED_CONTINUE, PRED_EARLY_RETURN, PRED_GOTO,
PRED_CONST_RETURN, PRED_NEGATIVE_RETURN, PRED_NULL_RETURN): New.
* predict.h (IS_TAKEN): New constant.
* print-rtl.c (print_rtx): Pretty print NOTE_INSN_PREDICTION.
* rtl.c (NOTE_INSN_PREDICTION): New.
* rtl.h (NOTE_PREDICTION, NOTE_PREDICTION_ALG, NOTE_PREDICTION_FLAGS):
New macro.
(insn_note): add NOTE_INSN_PREDICTION.
* sibcall.c (optimize_sibling_and_tail_recursive_call): Do not build
CFG; free tail_recursion_label_list.
* stmt.c: Include predict.h;
(return_prediction): New.
(expand_value_return): Use it.
* toplev.c: Lower NOTE_INSN_PREDICTION before sibcall.
2002-05-08 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.md: Name the unspecs with define_constant.
......
......@@ -1227,7 +1227,7 @@ c-format.o : c-format.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) langhooks.h \
c-semantics.o : c-semantics.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(C_TREE_H) \
c-lex.h flags.h toplev.h output.h c-pragma.h $(RTL_H) $(GGC_H) \
$(EXPR_H)
$(EXPR_H) predict.h
# Language-independent files.
......@@ -1389,7 +1389,7 @@ function.o : function.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
stmt.o : stmt.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
insn-config.h hard-reg-set.h $(EXPR_H) libfuncs.h except.h \
$(LOOP_H) $(RECOG_H) toplev.h output.h varray.h $(GGC_H) $(TM_P_H) \
langhooks.h
langhooks.h predict.h
except.o : except.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
except.h function.h $(EXPR_H) libfuncs.h integrate.h langhooks.h \
insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
......
......@@ -625,6 +625,7 @@ extern rtx emit_block_insn_before PARAMS ((rtx, rtx, basic_block));
/* In predict.c */
extern void estimate_probability PARAMS ((struct loops *));
extern void note_prediction_to_br_prob PARAMS ((void));
extern void expected_value_to_br_prob PARAMS ((void));
/* In flow.c */
......
......@@ -36,6 +36,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "expr.h"
#include "output.h"
#include "timevar.h"
#include "predict.h"
/* If non-NULL, the address of a language-specific function for
expanding statements. */
......@@ -834,6 +835,14 @@ expand_stmt (t)
break;
case GOTO_STMT:
/* Emit information for branch prediction. */
if (!GOTO_FAKE_P (t)
&& TREE_CODE (GOTO_DESTINATION (t)) == LABEL_DECL)
{
rtx note = emit_note (NULL, NOTE_INSN_PREDICTION);
NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_GOTO, NOT_TAKEN);
}
genrtl_goto_stmt (GOTO_DESTINATION (t));
break;
......
......@@ -74,7 +74,7 @@ static int flow_find_cross_jump PARAMS ((int, basic_block, basic_block,
rtx *, rtx *));
static bool insns_match_p PARAMS ((int, rtx, rtx));
static bool delete_unreachable_blocks PARAMS ((void));
bool delete_unreachable_blocks PARAMS ((void));
static bool label_is_jump_target_p PARAMS ((rtx, rtx));
static bool tail_recursion_label_p PARAMS ((rtx));
static void merge_blocks_move_predecessor_nojumps PARAMS ((basic_block,
......@@ -1748,7 +1748,7 @@ try_optimize_cfg (mode)
/* Delete all unreachable basic blocks. */
static bool
bool
delete_unreachable_blocks ()
{
int i, j;
......@@ -1829,7 +1829,6 @@ cleanup_cfg (mode)
/* Kill the data we won't maintain. */
free_EXPR_LIST_list (&label_value_list);
free_EXPR_LIST_list (&tail_recursion_label_list);
timevar_pop (TV_CLEANUP_CFG);
return changed;
......
......@@ -21,9 +21,12 @@
/* Structure to hold information about the blocks during reordering. */
typedef struct reorder_block_def
{
rtx eff_head;
rtx eff_end;
rtx header;
rtx footer;
basic_block next;
basic_block original;
/* These fields are used by bb-reorder pass. */
int visited;
} *reorder_block_def;
......@@ -31,6 +34,8 @@ typedef struct reorder_block_def
extern void cfg_layout_initialize PARAMS ((void));
extern void cfg_layout_finalize PARAMS ((void));
extern bool cfg_layout_can_duplicate_bb_p PARAMS ((basic_block));
extern basic_block cfg_layout_duplicate_bb PARAMS ((basic_block, edge));
extern void scope_to_insns_initialize PARAMS ((void));
extern void scope_to_insns_finalize PARAMS ((void));
extern void cfg_layout_redirect_edge PARAMS ((edge, basic_block));
......@@ -89,7 +89,8 @@ can_delete_note_p (note)
rtx note;
{
return (NOTE_LINE_NUMBER (note) == NOTE_INSN_DELETED
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK);
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_BASIC_BLOCK
|| NOTE_LINE_NUMBER (note) == NOTE_INSN_PREDICTION);
}
/* True if a given label can be deleted. */
......@@ -375,6 +376,16 @@ flow_delete_block_noexpunge (b)
and remove the associated NOTE_INSN_EH_REGION_BEG and
NOTE_INSN_EH_REGION_END notes. */
/* Get rid of all NOTE_INSN_PREDICTIONs hanging before the block. */
for (insn = PREV_INSN (b->head); insn; insn = PREV_INSN (insn))
{
if (GET_CODE (insn) != NOTE)
break;
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION)
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
}
insn = b->head;
never_reached_warning (insn, b->end);
......
......@@ -3731,6 +3731,27 @@ emit_call_insn_before (pattern, before)
return insn;
}
/* Make an instruction with body PATTERN and code CALL_INSN
and output it before the instruction BEFORE. */
rtx
emit_call_insn_after (pattern, before)
rtx pattern, before;
{
rtx insn;
if (GET_CODE (pattern) == SEQUENCE)
insn = emit_insn_after (pattern, before);
else
{
insn = make_call_insn_raw (pattern);
add_insn_after (insn, before);
PUT_CODE (insn, CALL_INSN);
}
return insn;
}
/* Make an insn of code BARRIER
and output it before the insn BEFORE. */
......@@ -5052,3 +5073,68 @@ restore_line_number_status (old_value)
{
no_line_numbers = old_value;
}
/* Produce exact duplicate of insn INSN after AFTER.
Care updating of libcall regions if present. */
rtx
emit_copy_of_insn_after (insn, after)
rtx insn, after;
{
rtx new;
rtx note1, note2, link;
switch (GET_CODE (insn))
{
case INSN:
new = emit_insn_after (copy_insn (PATTERN (insn)), after);
break;
case JUMP_INSN:
new = emit_jump_insn_after (copy_insn (PATTERN (insn)), after);
break;
case CALL_INSN:
new = emit_call_insn_after (copy_insn (PATTERN (insn)), after);
if (CALL_INSN_FUNCTION_USAGE (insn))
CALL_INSN_FUNCTION_USAGE (new)
= copy_insn (CALL_INSN_FUNCTION_USAGE (insn));
SIBLING_CALL_P (new) = SIBLING_CALL_P (insn);
CONST_OR_PURE_CALL_P (new) = CONST_OR_PURE_CALL_P (insn);
break;
default:
abort ();
}
/* Update LABEL_NUSES. */
mark_jump_label (PATTERN (new), new, 0);
/* Copy all REG_NOTES except REG_LABEL since mark_jump_label will
make them. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) != REG_LABEL)
{
if (GET_CODE (link) == EXPR_LIST)
REG_NOTES (new)
= copy_insn_1 (gen_rtx_EXPR_LIST (REG_NOTE_KIND (link),
XEXP (link, 0),
REG_NOTES (new)));
else
REG_NOTES (new)
= copy_insn_1 (gen_rtx_INSN_LIST (REG_NOTE_KIND (link),
XEXP (link, 0),
REG_NOTES (new)));
}
/* Fix the libcall sequences. */
if ((note1 = find_reg_note (new, REG_RETVAL, NULL_RTX)) != NULL)
{
rtx p = new;
while ((note2 = find_reg_note (p, REG_LIBCALL, NULL_RTX)) == NULL)
p = PREV_INSN (p);
XEXP (note1, 0) = p;
XEXP (note2, 0) = new;
}
return new;
}
......@@ -145,6 +145,7 @@ extern int regno_uninitialized PARAMS ((unsigned int));
extern int regno_clobbered_at_setjmp PARAMS ((int));
extern void find_basic_blocks PARAMS ((rtx, int, FILE *));
extern bool cleanup_cfg PARAMS ((int));
extern bool delete_unreachable_blocks PARAMS ((void));
extern void check_function_return_warnings PARAMS ((void));
#endif
......
......@@ -63,6 +63,9 @@ DEF_PREDICTOR (PRED_LOOP_ITERATIONS, "loop iterations", PROB_ALWAYS,
DEF_PREDICTOR (PRED_BUILTIN_EXPECT, "__builtin_expect", PROB_VERY_LIKELY,
PRED_FLAG_FIRST_MATCH)
/* Branch containing goto is probably not taken. */
DEF_PREDICTOR (PRED_CONTINUE, "continue", HITRATE (56), 0)
/* Branch to basic block containing call marked by noreturn attribute. */
DEF_PREDICTOR (PRED_NORETURN, "noreturn call", HITRATE (99),
PRED_FLAG_FIRST_MATCH)
......@@ -97,4 +100,16 @@ DEF_PREDICTOR (PRED_FPOPCODE, "fp_opcode", HITRATE (90), 0)
DEF_PREDICTOR (PRED_CALL, "call", HITRATE (70), 0)
/* Branch causing function to terminate is probably not taken. */
DEF_PREDICTOR (PRED_ERROR_RETURN, "error return", HITRATE (52), 0)
DEF_PREDICTOR (PRED_EARLY_RETURN, "early return", HITRATE (67), 0)
/* Branch containing goto is probably not taken. */
DEF_PREDICTOR (PRED_GOTO, "goto", HITRATE (70), 0)
/* Branch ending with return constant is probably not taken. */
DEF_PREDICTOR (PRED_CONST_RETURN, "const return", HITRATE (95), 0)
/* Branch ending with return negative constant is probably not taken. */
DEF_PREDICTOR (PRED_NEGATIVE_RETURN, "negative return", HITRATE (96), 0)
/* Branch ending with return; is probably not taken */
DEF_PREDICTOR (PRED_NULL_RETURN, "null return", HITRATE (90), 0)
......@@ -34,6 +34,9 @@ enum prediction
TAKEN
};
/* Flags for NOTE_PREDICTION */
#define IS_TAKEN 1 /* Predict edges to the block as taken. */
extern void predict_insn_def PARAMS ((rtx, enum br_predictor,
enum prediction));
extern void predict_insn PARAMS ((rtx, enum br_predictor, int));
......
......@@ -284,6 +284,15 @@ print_rtx (in_rtx)
fprintf (outfile, " \"\"");
break;
case NOTE_INSN_PREDICTION:
if (NOTE_PREDICTION (in_rtx))
fprintf (outfile, " [ %d %d ] ",
(int)NOTE_PREDICTION_ALG (in_rtx),
(int) NOTE_PREDICTION_FLAGS (in_rtx));
else
fprintf (outfile, " [ ERROR ]");
break;
default:
{
const char * const str = X0STR (in_rtx, i);
......
......@@ -216,7 +216,8 @@ const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] =
"NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
"NOTE_INSN_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_BEG",
"NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
"NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE"
"NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE",
"NOTE_INSN_PREDICTION"
};
const char * const reg_note_name[] =
......
......@@ -740,6 +740,7 @@ extern const char * const reg_note_name[];
#define NOTE_LIVE_INFO(INSN) XCEXP (INSN, 3, NOTE)
#define NOTE_BASIC_BLOCK(INSN) XCBBDEF (INSN, 3, NOTE)
#define NOTE_EXPECTED_VALUE(INSN) XCEXP (INSN, 3, NOTE)
#define NOTE_PREDICTION(INSN) XCINT (INSN, 3, NOTE)
/* In a NOTE that is a line number, this is the line number.
Other kinds of NOTEs are identified by negative numbers here. */
......@@ -750,6 +751,11 @@ extern const char * const reg_note_name[];
(GET_CODE (INSN) == NOTE \
&& NOTE_LINE_NUMBER (INSN) == NOTE_INSN_BASIC_BLOCK)
/* Algorithm and flags for prediction. */
#define NOTE_PREDICTION_ALG(INSN) (XCINT(INSN, 3, NOTE)>>8)
#define NOTE_PREDICTION_FLAGS(INSN) (XCINT(INSN, 3, NOTE)&0xff)
#define NOTE_PREDICT(ALG,FLAGS) ((ALG<<8)+(FLAGS))
/* Codes that appear in the NOTE_LINE_NUMBER field
for kinds of notes that are not line numbers.
......@@ -838,6 +844,9 @@ enum insn_note
NOTE_EXPECTED_VALUE; stored as (eq (reg) (const_int)). */
NOTE_INSN_EXPECTED_VALUE,
/* Record a prediction. Uses NOTE_PREDICTION. */
NOTE_INSN_PREDICTION,
NOTE_INSN_MAX
};
......@@ -1349,6 +1358,7 @@ extern rtx copy_insn_1 PARAMS ((rtx));
extern rtx copy_insn PARAMS ((rtx));
extern rtx gen_int_mode PARAMS ((HOST_WIDE_INT,
enum machine_mode));
extern rtx emit_copy_of_insn_after PARAMS ((rtx, rtx));
/* In rtl.c */
extern rtx rtx_alloc PARAMS ((RTX_CODE));
......@@ -1437,6 +1447,7 @@ extern rtx emit_label_before PARAMS ((rtx, rtx));
extern rtx emit_note_before PARAMS ((int, rtx));
extern rtx emit_insn_after PARAMS ((rtx, rtx));
extern rtx emit_jump_insn_after PARAMS ((rtx, rtx));
extern rtx emit_call_insn_after PARAMS ((rtx, rtx));
extern rtx emit_barrier_after PARAMS ((rtx));
extern rtx emit_label_after PARAMS ((rtx, rtx));
extern rtx emit_note_after PARAMS ((int, rtx));
......
......@@ -580,16 +580,6 @@ optimize_sibling_and_tail_recursive_calls ()
insns = get_insns ();
/* We do not perform these calls when flag_exceptions is true, so this
is probably a NOP at the current time. However, we may want to support
sibling and tail recursion optimizations in the future, so let's plan
ahead and find all the EH labels. */
find_exception_handler_labels ();
rebuild_jump_labels (insns);
/* We need cfg information to determine which blocks are succeeded
only by the epilogue. */
find_basic_blocks (insns, max_reg_num (), 0);
cleanup_cfg (CLEANUP_PRE_SIBCALL | CLEANUP_PRE_LOOP);
/* If there are no basic blocks, then there is nothing to do. */
......@@ -776,4 +766,5 @@ optimize_sibling_and_tail_recursive_calls ()
/* This information will be invalid after inline expansion. Kill it now. */
free_basic_block_vars (0);
free_EXPR_LIST_list (&tail_recursion_label_list);
}
......@@ -54,6 +54,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "output.h"
#include "ggc.h"
#include "langhooks.h"
#include "predict.h"
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
......@@ -414,6 +415,7 @@ static tree resolve_operand_names PARAMS ((tree, tree, tree,
const char **));
static char *resolve_operand_name_1 PARAMS ((char *, tree, tree));
static void expand_null_return_1 PARAMS ((rtx));
static enum br_predictor return_prediction PARAMS ((rtx));
static void expand_value_return PARAMS ((rtx));
static int tail_recursion_args PARAMS ((tree, tree));
static void expand_cleanups PARAMS ((tree, tree, int, int));
......@@ -2824,6 +2826,11 @@ int
expand_continue_loop (whichloop)
struct nesting *whichloop;
{
/* Emit information for branch prediction. */
rtx note;
note = emit_note (NULL, NOTE_INSN_PREDICTION);
NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN);
last_expr_type = 0;
if (whichloop == 0)
whichloop = loop_stack;
......@@ -2965,7 +2972,9 @@ expand_exit_something ()
void
expand_null_return ()
{
rtx last_insn = get_last_insn ();
rtx last_insn;
last_insn = get_last_insn ();
/* If this function was declared to return a value, but we
didn't, clobber the return registers so that they are not
......@@ -2975,14 +2984,58 @@ expand_null_return ()
expand_null_return_1 (last_insn);
}
/* Try to guess whether the value of return means error code. */
static enum br_predictor
return_prediction (val)
rtx val;
{
/* Different heuristics for pointers and scalars. */
if (POINTER_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
{
/* NULL is usually not returned. */
if (val == const0_rtx)
return PRED_NULL_RETURN;
}
else
{
/* Negative return values are often used to indicate
errors. */
if (GET_CODE (val) == CONST_INT
&& INTVAL (val) < 0)
return PRED_NEGATIVE_RETURN;
/* Constant return values are also usually erors,
zero/one often mean booleans so exclude them from the
heuristics. */
if (CONSTANT_P (val)
&& (val != const0_rtx && val != const1_rtx))
return PRED_CONST_RETURN;
}
return PRED_NO_PREDICTION;
}
/* Generate RTL to return from the current function, with value VAL. */
static void
expand_value_return (val)
rtx val;
{
rtx last_insn = get_last_insn ();
rtx return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
rtx last_insn;
rtx return_reg;
enum br_predictor pred;
if ((pred = return_prediction (val)) != PRED_NO_PREDICTION)
{
/* Emit information for branch prediction. */
rtx note;
note = emit_note (NULL, NOTE_INSN_PREDICTION);
NOTE_PREDICTION (note) = NOTE_PREDICT (pred, NOT_TAKEN);
}
last_insn = get_last_insn ();
return_reg = DECL_RTL (DECL_RESULT (current_function_decl));
/* Copy the value to the return location
unless it's already there. */
......
......@@ -2492,18 +2492,38 @@ rest_of_compilation (decl)
|| errorcount || sorrycount)
goto exit_rest_of_compilation;
timevar_push (TV_JUMP);
open_dump_file (DFI_sibling, decl);
insns = get_insns ();
rebuild_jump_labels (insns);
find_exception_handler_labels ();
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
delete_unreachable_blocks ();
/* Turn NOTE_INSN_PREDICTIONs into branch predictions. */
note_prediction_to_br_prob ();
/* We may have potential sibling or tail recursion sites. Select one
(of possibly multiple) methods of performing the call. */
if (flag_optimize_sibling_calls)
{
timevar_push (TV_JUMP);
open_dump_file (DFI_sibling, decl);
rtx insn;
optimize_sibling_and_tail_recursive_calls ();
close_dump_file (DFI_sibling, print_rtl, get_insns ());
timevar_pop (TV_JUMP);
/* There is pass ordering problem - we must lower NOTE_INSN_PREDICTION
notes before simplifying cfg and we must do lowering after sibcall
that unhides parts of RTL chain and cleans up the CFG.
Until sibcall is replaced by tree-level optimizer, lets just
sweep away the NOTE_INSN_PREDICTION notes that leaked out. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_PREDICTION)
delete_insn (insn);
}
close_dump_file (DFI_sibling, print_rtl, get_insns ());
timevar_pop (TV_JUMP);
/* Complete generation of exception handling code. */
find_exception_handler_labels ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment