Commit ef950eba by Jan Hubicka Committed by Jan Hubicka

extended.texi (__builtin_expect): We no longer require second argument to be constant.


	* extended.texi (__builtin_expect): We no longer require second argument
	to be constant.
	* gengtype.c (adjust_field_rtx_def): Drop NOTE_INSN_EXPECTED_VALUE.
	* builtins.c (expand_builtin_expect): Simplify.
	(expand_builtin_expect_jump): Kill.
	* final.c (final_scan_insn): Do not skip the removed notes.
	* insn-notes.def (LOOP_BEG, LOOP_END, REPEATED_LINE_NUMBER,
	EXPECTED_VALUE): Remove.
	* dojump.c (do_jump): Do not care about __builtin_expect.
	* predict.c (expected_value_to_br_prob): Kill.
	* function.c (expand_function_end): Do not expand
	NOTE_INSN_REPEATED_LINE_NUMBER.
	* print-rtl.c (print_rtx): Do not pretty print the removed notes.
	* expect.c (sjlj_emit_function_enter): Emit directly branch probability.
	* cfgexpand.c (add_reg_br_prob_note): Export.
	* cfgcleanup.c (rest_of_handle_jump2): Do not call
	expected_value_to_br_prob.
	* cfglayout.c (duplicate_insn_chain): Do not deal with removed notes.
	* rtl.h (add_reg_br_prob_note): Declare.

From-SVN: r118696
parent 89fa98d6
2006-11-11 Jan Hubicka <jh@suse.cz>
* extended.texi (__builtin_expect): We no longer require second argument
to be constant.
* gengtype.c (adjust_field_rtx_def): Drop NOTE_INSN_EXPECTED_VALUE.
* builtins.c (expand_builtin_expect): Simplify.
(expand_builtin_expect_jump): Kill.
* final.c (final_scan_insn): Do not skip the removed notes.
* insn-notes.def (LOOP_BEG, LOOP_END, REPEATED_LINE_NUMBER,
EXPECTED_VALUE): Remove.
* dojump.c (do_jump): Do not care about __builtin_expect.
* predict.c (expected_value_to_br_prob): Kill.
* function.c (expand_function_end): Do not expand
NOTE_INSN_REPEATED_LINE_NUMBER.
* print-rtl.c (print_rtx): Do not pretty print the removed notes.
* expect.c (sjlj_emit_function_enter): Emit directly branch probability.
* cfgexpand.c (add_reg_br_prob_note): Export.
* cfgcleanup.c (rest_of_handle_jump2): Do not call
expected_value_to_br_prob.
* cfglayout.c (duplicate_insn_chain): Do not deal with removed notes.
* rtl.h (add_reg_br_prob_note): Declare.
2006-11-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2006-11-11 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* tree-pretty-print.c (dump_generic_node): Print sign of Inf. * tree-pretty-print.c (dump_generic_node): Print sign of Inf.
......
...@@ -4693,9 +4693,9 @@ expand_builtin_fputs (tree arglist, rtx target, bool unlocked) ...@@ -4693,9 +4693,9 @@ expand_builtin_fputs (tree arglist, rtx target, bool unlocked)
return 0; return 0;
} }
/* Expand a call to __builtin_expect. We return our argument and emit a /* Expand a call to __builtin_expect. We just return our argument
NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in as the builtin_expect semantic should've been already executed by
a non-jump context. */ tree branch prediction pass. */
static rtx static rtx
expand_builtin_expect (tree arglist, rtx target) expand_builtin_expect (tree arglist, rtx target)
...@@ -4709,149 +4709,12 @@ expand_builtin_expect (tree arglist, rtx target) ...@@ -4709,149 +4709,12 @@ expand_builtin_expect (tree arglist, rtx target)
exp = TREE_VALUE (arglist); exp = TREE_VALUE (arglist);
c = TREE_VALUE (TREE_CHAIN (arglist)); c = TREE_VALUE (TREE_CHAIN (arglist));
if (TREE_CODE (c) != INTEGER_CST)
{
error ("second argument to %<__builtin_expect%> must be a constant");
c = integer_zero_node;
}
target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL); target = expand_expr (exp, target, VOIDmode, EXPAND_NORMAL);
/* When guessing was done, the hints should be already stripped away. */
/* Don't bother with expected value notes for integral constants. */ gcc_assert (!flag_guess_branch_prob);
if (flag_guess_branch_prob && GET_CODE (target) != CONST_INT)
{
/* We do need to force this into a register so that we can be
moderately sure to be able to correctly interpret the branch
condition later. */
target = force_reg (GET_MODE (target), target);
rtx_c = expand_expr (c, NULL_RTX, GET_MODE (target), EXPAND_NORMAL);
note = emit_note (NOTE_INSN_EXPECTED_VALUE);
NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, target, rtx_c);
}
return target; return target;
} }
/* Like expand_builtin_expect, except do this in a jump context. This is
called from do_jump if the conditional is a __builtin_expect. Return either
a list of insns to emit the jump or NULL if we cannot optimize
__builtin_expect. We need to optimize this at jump time so that machines
like the PowerPC don't turn the test into a SCC operation, and then jump
based on the test being 0/1. */
rtx
expand_builtin_expect_jump (tree exp, rtx if_false_label, rtx if_true_label)
{
tree arglist = TREE_OPERAND (exp, 1);
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
rtx ret = NULL_RTX;
/* Only handle __builtin_expect (test, 0) and
__builtin_expect (test, 1). */
if (TREE_CODE (TREE_TYPE (arg1)) == INTEGER_TYPE
&& (integer_zerop (arg1) || integer_onep (arg1)))
{
rtx insn, drop_through_label, temp;
/* Expand the jump insns. */
start_sequence ();
do_jump (arg0, if_false_label, if_true_label);
ret = get_insns ();
drop_through_label = get_last_insn ();
if (drop_through_label && NOTE_P (drop_through_label))
drop_through_label = prev_nonnote_insn (drop_through_label);
if (drop_through_label && !LABEL_P (drop_through_label))
drop_through_label = NULL_RTX;
end_sequence ();
if (! if_true_label)
if_true_label = drop_through_label;
if (! if_false_label)
if_false_label = drop_through_label;
/* Go through and add the expect's to each of the conditional jumps. */
insn = ret;
while (insn != NULL_RTX)
{
rtx next = NEXT_INSN (insn);
if (JUMP_P (insn) && any_condjump_p (insn))
{
rtx ifelse = SET_SRC (pc_set (insn));
rtx then_dest = XEXP (ifelse, 1);
rtx else_dest = XEXP (ifelse, 2);
int taken = -1;
/* First check if we recognize any of the labels. */
if (GET_CODE (then_dest) == LABEL_REF
&& XEXP (then_dest, 0) == if_true_label)
taken = 1;
else if (GET_CODE (then_dest) == LABEL_REF
&& XEXP (then_dest, 0) == if_false_label)
taken = 0;
else if (GET_CODE (else_dest) == LABEL_REF
&& XEXP (else_dest, 0) == if_false_label)
taken = 1;
else if (GET_CODE (else_dest) == LABEL_REF
&& XEXP (else_dest, 0) == if_true_label)
taken = 0;
/* Otherwise check where we drop through. */
else if (else_dest == pc_rtx)
{
if (next && NOTE_P (next))
next = next_nonnote_insn (next);
if (next && JUMP_P (next)
&& any_uncondjump_p (next))
temp = XEXP (SET_SRC (pc_set (next)), 0);
else
temp = next;
/* TEMP is either a CODE_LABEL, NULL_RTX or something
else that can't possibly match either target label. */
if (temp == if_false_label)
taken = 1;
else if (temp == if_true_label)
taken = 0;
}
else if (then_dest == pc_rtx)
{
if (next && NOTE_P (next))
next = next_nonnote_insn (next);
if (next && JUMP_P (next)
&& any_uncondjump_p (next))
temp = XEXP (SET_SRC (pc_set (next)), 0);
else
temp = next;
if (temp == if_false_label)
taken = 0;
else if (temp == if_true_label)
taken = 1;
}
if (taken != -1)
{
/* If the test is expected to fail, reverse the
probabilities. */
if (integer_zerop (arg1))
taken = 1 - taken;
predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
}
}
insn = next;
}
}
return ret;
}
void void
expand_builtin_trap (void) expand_builtin_trap (void)
{ {
......
...@@ -2300,11 +2300,6 @@ struct tree_opt_pass pass_jump = ...@@ -2300,11 +2300,6 @@ struct tree_opt_pass pass_jump =
static unsigned int static unsigned int
rest_of_handle_jump2 (void) rest_of_handle_jump2 (void)
{ {
/* Turn NOTE_INSN_EXPECTED_VALUE into REG_BR_PROB. Do this
before jump optimization switches branch directions. */
if (flag_guess_branch_prob)
expected_value_to_br_prob ();
delete_trivially_dead_insns (get_insns (), max_reg_num ()); delete_trivially_dead_insns (get_insns (), max_reg_num ());
reg_scan (get_insns (), max_reg_num ()); reg_scan (get_insns (), max_reg_num ());
if (dump_file) if (dump_file)
......
...@@ -45,7 +45,7 @@ Boston, MA 02110-1301, USA. */ ...@@ -45,7 +45,7 @@ Boston, MA 02110-1301, USA. */
??? We really ought to pass the probability down to RTL expanders and let it ??? We really ought to pass the probability down to RTL expanders and let it
re-distribute it when the conditional expands into multiple conditionals. re-distribute it when the conditional expands into multiple conditionals.
This is however difficult to do. */ This is however difficult to do. */
static void void
add_reg_br_prob_note (rtx last, int probability) add_reg_br_prob_note (rtx last, int probability)
{ {
if (profile_status == PROFILE_ABSENT) if (profile_status == PROFILE_ABSENT)
......
...@@ -997,7 +997,6 @@ duplicate_insn_chain (rtx from, rtx to) ...@@ -997,7 +997,6 @@ duplicate_insn_chain (rtx from, rtx to)
case NOTE_INSN_BASIC_BLOCK: case NOTE_INSN_BASIC_BLOCK:
break; break;
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_SWITCH_TEXT_SECTIONS: case NOTE_INSN_SWITCH_TEXT_SECTIONS:
emit_note_copy (insn); emit_note_copy (insn);
break; break;
......
...@@ -5874,10 +5874,9 @@ programmers are notoriously bad at predicting how their programs ...@@ -5874,10 +5874,9 @@ programmers are notoriously bad at predicting how their programs
actually perform. However, there are applications in which this actually perform. However, there are applications in which this
data is hard to collect. data is hard to collect.
The return value is the value of @var{exp}, which should be an The return value is the value of @var{exp}, which should be an integral
integral expression. The value of @var{c} must be a compile-time expression. The semantics of the built-in are that it is expected that
constant. The semantics of the built-in are that it is expected @var{exp} == @var{c}. For example:
that @var{exp} == @var{c}. For example:
@smallexample @smallexample
if (__builtin_expect (x, 0)) if (__builtin_expect (x, 0))
......
...@@ -551,37 +551,6 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label) ...@@ -551,37 +551,6 @@ do_jump (tree exp, rtx if_false_label, rtx if_true_label)
} }
break; break;
/* Special case:
__builtin_expect (<test>, 0) and
__builtin_expect (<test>, 1)
We need to do this here, so that <test> is not converted to a SCC
operation on machines that use condition code registers and COMPARE
like the PowerPC, and then the jump is done based on whether the SCC
operation produced a 1 or 0. */
case CALL_EXPR:
/* Check for a built-in function. */
{
tree fndecl = get_callee_fndecl (exp);
tree arglist = TREE_OPERAND (exp, 1);
if (fndecl
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
&& DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
&& arglist != NULL_TREE
&& TREE_CHAIN (arglist) != NULL_TREE)
{
rtx seq = expand_builtin_expect_jump (exp, if_false_label,
if_true_label);
if (seq != NULL_RTX)
{
emit_insn (seq);
return;
}
}
}
/* Fall through and generate the normal code. */ /* Fall through and generate the normal code. */
default: default:
normal: normal:
......
...@@ -1875,11 +1875,9 @@ sjlj_emit_function_enter (rtx dispatch_label) ...@@ -1875,11 +1875,9 @@ sjlj_emit_function_enter (rtx dispatch_label)
plus_constant (XEXP (fc, 0), plus_constant (XEXP (fc, 0),
sjlj_fc_jbuf_ofs), Pmode); sjlj_fc_jbuf_ofs), Pmode);
note = emit_note (NOTE_INSN_EXPECTED_VALUE);
NOTE_EXPECTED_VALUE (note) = gen_rtx_EQ (VOIDmode, x, const0_rtx);
emit_cmp_and_jump_insns (x, const0_rtx, NE, 0, emit_cmp_and_jump_insns (x, const0_rtx, NE, 0,
TYPE_MODE (integer_type_node), 0, dispatch_label); TYPE_MODE (integer_type_node), 0, dispatch_label);
add_reg_br_prob_note (get_insns (), REG_BR_PROB_BASE/100);
} }
#else #else
expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs), expand_builtin_setjmp_setup (plus_constant (XEXP (fc, 0), sjlj_fc_jbuf_ofs),
......
...@@ -1698,8 +1698,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED, ...@@ -1698,8 +1698,6 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
{ {
case NOTE_INSN_DELETED: case NOTE_INSN_DELETED:
case NOTE_INSN_FUNCTION_END: case NOTE_INSN_FUNCTION_END:
case NOTE_INSN_REPEATED_LINE_NUMBER:
case NOTE_INSN_EXPECTED_VALUE:
break; break;
case NOTE_INSN_SWITCH_TEXT_SECTIONS: case NOTE_INSN_SWITCH_TEXT_SECTIONS:
......
...@@ -519,7 +519,6 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt)) ...@@ -519,7 +519,6 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
note_flds = create_field (note_flds, tree_tp, "rt_tree"); note_flds = create_field (note_flds, tree_tp, "rt_tree");
break; break;
case NOTE_INSN_EXPECTED_VALUE:
case NOTE_INSN_VAR_LOCATION: case NOTE_INSN_VAR_LOCATION:
note_flds = create_field (note_flds, rtx_tp, "rt_rtx"); note_flds = create_field (note_flds, rtx_tp, "rt_rtx");
break; break;
......
...@@ -1340,79 +1340,6 @@ tree_estimate_probability (void) ...@@ -1340,79 +1340,6 @@ tree_estimate_probability (void)
return 0; return 0;
} }
/* __builtin_expect dropped tokens into the insn stream describing expected
values of registers. Generate branch probabilities based off these
values. */
void
expected_value_to_br_prob (void)
{
rtx insn, cond, ev = NULL_RTX, ev_reg = NULL_RTX;
for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
{
switch (GET_CODE (insn))
{
case NOTE:
/* Look for expected value notes. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EXPECTED_VALUE)
{
ev = NOTE_EXPECTED_VALUE (insn);
ev_reg = XEXP (ev, 0);
delete_insn (insn);
}
continue;
case CODE_LABEL:
/* Never propagate across labels. */
ev = NULL_RTX;
continue;
case JUMP_INSN:
/* Look for simple conditional branches. If we haven't got an
expected value yet, no point going further. */
if (!JUMP_P (insn) || ev == NULL_RTX
|| ! any_condjump_p (insn))
continue;
break;
default:
/* Look for insns that clobber the EV register. */
if (ev && reg_set_p (ev_reg, insn))
ev = NULL_RTX;
continue;
}
/* Collect the branch condition, hopefully relative to EV_REG. */
/* ??? At present we'll miss things like
(expected_value (eq r70 0))
(set r71 -1)
(set r80 (lt r70 r71))
(set pc (if_then_else (ne r80 0) ...))
as canonicalize_condition will render this to us as
(lt r70, r71)
Could use cselib to try and reduce this further. */
cond = XEXP (SET_SRC (pc_set (insn)), 0);
cond = canonicalize_condition (insn, cond, 0, NULL, ev_reg,
false, false);
if (! cond || XEXP (cond, 0) != ev_reg
|| GET_CODE (XEXP (cond, 1)) != CONST_INT)
continue;
/* Substitute and simplify. Given that the expression we're
building involves two constants, we should wind up with either
true or false. */
cond = gen_rtx_fmt_ee (GET_CODE (cond), VOIDmode,
XEXP (ev, 1), XEXP (cond, 1));
cond = simplify_rtx (cond);
/* Turn the condition into a scaled branch probability. */
gcc_assert (cond == const_true_rtx || cond == const0_rtx);
predict_insn_def (insn, PRED_BUILTIN_EXPECT,
cond == const_true_rtx ? TAKEN : NOT_TAKEN);
}
}
/* Check whether this is the last basic block of function. Commonly /* Check whether this is the last basic block of function. Commonly
there is one extra common cleanup block. */ there is one extra common cleanup block. */
static bool static bool
......
...@@ -299,14 +299,6 @@ print_rtx (rtx in_rtx) ...@@ -299,14 +299,6 @@ print_rtx (rtx in_rtx)
break; break;
} }
case NOTE_INSN_EXPECTED_VALUE:
indent += 2;
if (!sawclose)
fprintf (outfile, " ");
print_rtx (NOTE_EXPECTED_VALUE (in_rtx));
indent -= 2;
break;
case NOTE_INSN_DELETED_LABEL: case NOTE_INSN_DELETED_LABEL:
{ {
const char *label = NOTE_DELETED_LABEL_NAME (in_rtx); const char *label = NOTE_DELETED_LABEL_NAME (in_rtx);
......
...@@ -2250,6 +2250,8 @@ extern GTY(()) rtx stack_limit_rtx; ...@@ -2250,6 +2250,8 @@ extern GTY(()) rtx stack_limit_rtx;
/* In predict.c */ /* In predict.c */
extern void invert_br_probabilities (rtx); extern void invert_br_probabilities (rtx);
extern bool expensive_function_p (int); extern bool expensive_function_p (int);
/* In cfgexpand.c */
extern void add_reg_br_prob_note (rtx last, int probability);
/* In tracer.c */ /* In tracer.c */
extern void tracer (unsigned int); extern void tracer (unsigned int);
......
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