Fix __builtin_expect on PowerPCs

From-SVN: r43470
This commit is contained in:
Michael Meissner 2001-06-20 07:18:18 +00:00 committed by Michael Meissner
parent f34c9fd4a6
commit 5f2d6cfa81
5 changed files with 164 additions and 3 deletions

View File

@ -1,3 +1,17 @@
2001-06-20 Michael Meissner <meissner@redhat.com>
* builtins.c (predict.h): Include.
(expand_builtin_expect): Update comment.
(expand_builtin_expect_jump): New function to expand
__builtin_expect inside of a conditional jump expansion.
* expr.c (do_jump): Special case __builtin_expect (<test>, 0) and
__builtin_expect (<test>, 1).
* Makefile.in (builtins.o): Depend on $(PREDICT_H).
* rtl.h (expand_builtin_expect_jump): Add prototype.
2001-06-19 Geoffrey Keating <geoffk@redhat.com>
* doc/rtl.texi (Machine Modes): Correct description of

View File

@ -1371,7 +1371,7 @@ expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h function.h \
builtins.o : builtins.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \
function.h $(REGS_H) $(EXPR_H) insn-config.h \
$(RECOG_H) output.h typeclass.h hard-reg-set.h toplev.h hard-reg-set.h \
except.h $(TM_P_H)
except.h $(TM_P_H) $(PREDICT_H)
calls.o : calls.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h $(EXPR_H) \
$(REGS_H) toplev.h output.h function.h $(TIMEVAR_H) $(TM_P_H)
expmed.o : expmed.c $(CONFIG_H) $(SYSTEM_H) $(RTL_H) $(TREE_H) flags.h \

View File

@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA. */
#include "output.h"
#include "typeclass.h"
#include "toplev.h"
#include "predict.h"
#include "tm_p.h"
#define CALLED_AS_BUILT_IN(NODE) \
@ -3232,8 +3233,9 @@ expand_builtin_fputs (arglist, ignore)
VOIDmode, EXPAND_NORMAL);
}
/* Expand a call to __builtin_expect. We return our argument and
emit a NOTE_INSN_EXPECTED_VALUE note. */
/* Expand a call to __builtin_expect. We return our argument and emit a
NOTE_INSN_EXPECTED_VALUE note. This is the expansion of __builtin_expect in
a non-jump context. */
static rtx
expand_builtin_expect (arglist, target)
@ -3273,6 +3275,115 @@ expand_builtin_expect (arglist, 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 SEQUENCE 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 (exp, if_false_label, if_true_label)
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
&& TREE_CODE (arg1) == INTEGER_CST
&& (TREE_INT_CST_LOW (arg1) == 0 || TREE_INT_CST_LOW (arg1) == 1)
&& TREE_INT_CST_HIGH (arg1) == 0)
{
int j;
int num_jumps = 0;
/* Expand the jump insns. */
start_sequence ();
do_jump (arg0, if_false_label, if_true_label);
ret = gen_sequence ();
end_sequence ();
/* Now that the __builtin_expect has been validated, go through and add
the expect's to each of the conditional jumps. If we run into an
error, just give up and generate the 'safe' code of doing a SCC
operation and then doing a branch on that. */
for (j = 0; j < XVECLEN (ret, 0); j++)
{
rtx insn = XVECEXP (ret, 0, j);
rtx pattern;
if (GET_CODE (insn) == JUMP_INSN && any_condjump_p (insn)
&& (pattern = pc_set (insn)) != NULL_RTX)
{
rtx ifelse = SET_SRC (pattern);
rtx label;
int taken;
if (GET_CODE (ifelse) != IF_THEN_ELSE)
continue;
if (GET_CODE (XEXP (ifelse, 1)) == LABEL_REF)
{
taken = 1;
label = XEXP (XEXP (ifelse, 1), 0);
}
/* An inverted jump reverses the probabilities. */
else if (GET_CODE (XEXP (ifelse, 2)) == LABEL_REF)
{
taken = 0;
label = XEXP (XEXP (ifelse, 2), 0);
}
/* We shouldn't have to worry about conditional returns during
the expansion stage, but handle it gracefully anyway. */
else if (GET_CODE (XEXP (ifelse, 1)) == RETURN)
{
taken = 1;
label = NULL_RTX;
}
/* An inverted return reverses the probabilities. */
else if (GET_CODE (XEXP (ifelse, 2)) == RETURN)
{
taken = 0;
label = NULL_RTX;
}
else
continue;
/* If the test is expected to fail, reverse the
probabilities. */
if (TREE_INT_CST_LOW (arg1) == 0)
taken = 1 - taken;
/* If we are jumping to the false label, reverse the
probabilities. */
if (label == NULL_RTX)
; /* conditional return */
else if (label == if_false_label)
taken = 1 - taken;
else if (label != if_true_label)
continue;
num_jumps++;
predict_insn_def (insn, PRED_BUILTIN_EXPECT, taken);
}
}
/* If no jumps were modified, fail and do __builtin_expect the normal
way. */
if (num_jumps == 0)
ret = NULL_RTX;
}
return ret;
}
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient

View File

@ -9913,6 +9913,39 @@ do_jump (exp, if_false_label, if_true_label)
}
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. */
if (TREE_CODE (TREE_OPERAND (exp, 0)) == ADDR_EXPR)
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1);
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& DECL_BUILT_IN (fndecl)
&& 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. */
default:
normal:
temp = expand_expr (exp, NULL_RTX, VOIDmode, 0);

View File

@ -1146,6 +1146,9 @@ extern int ceil_log2 PARAMS ((unsigned HOST_WIDE_INT));
#define plus_constant_for_output(X,C) \
plus_constant_for_output_wide (X, (HOST_WIDE_INT) (C))
/* In builtins.c */
extern rtx expand_builtin_expect_jump PARAMS ((union tree_node *, rtx, rtx));
/* In explow.c */
extern void set_stack_check_libfunc PARAMS ((rtx));
extern HOST_WIDE_INT trunc_int_for_mode PARAMS ((HOST_WIDE_INT,