summaryrefslogtreecommitdiff
path: root/gcc/stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/stmt.c')
-rw-r--r--gcc/stmt.c59
1 files changed, 56 insertions, 3 deletions
diff --git a/gcc/stmt.c b/gcc/stmt.c
index 42a9659ade6..639587aa45e 100644
--- a/gcc/stmt.c
+++ b/gcc/stmt.c
@@ -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. */