mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-16 22:19:59 +08:00
rtl.def (COND_EXEC): New.
* rtl.def (COND_EXEC): New. * rtl.h (COND_EXEC_TEST, COND_EXEC_CODE): New. * tm.texi (MAX_CONDITIONAL_EXECUTE): Document. * genconfig.c (have_cond_arith_flag): Remove. (have_cond_exec_flag): New. (walk_insn_part): Detect COND_EXEC, not arithmetic in IF_THEN_ELSE. (main): Print HAVE_conditional_execution. * haifa-sched.c (haifa_classify_insn): Recognize COND_EXEC. (sched_analyze_insn, print_pattern): Likewise. * reload.c (find_equiv_reg): Likewise. * rtlanal.c (reg_referenced_p): Likewise. (note_stores, dead_or_set_regno_p): Likewise. (reg_overlap_mentioned_p): Rewrite to use a switch. From-SVN: r32997
This commit is contained in:
parent
4c85a96d6e
commit
0c99ec5c42
@ -1,5 +1,21 @@
|
||||
2000-04-07 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* rtl.def (COND_EXEC): New.
|
||||
* rtl.h (COND_EXEC_TEST, COND_EXEC_CODE): New.
|
||||
* tm.texi (MAX_CONDITIONAL_EXECUTE): Document.
|
||||
|
||||
* genconfig.c (have_cond_arith_flag): Remove.
|
||||
(have_cond_exec_flag): New.
|
||||
(walk_insn_part): Detect COND_EXEC, not arithmetic in IF_THEN_ELSE.
|
||||
(main): Print HAVE_conditional_execution.
|
||||
|
||||
* haifa-sched.c (haifa_classify_insn): Recognize COND_EXEC.
|
||||
(sched_analyze_insn, print_pattern): Likewise.
|
||||
* reload.c (find_equiv_reg): Likewise.
|
||||
* rtlanal.c (reg_referenced_p): Likewise.
|
||||
(note_stores, dead_or_set_regno_p): Likewise.
|
||||
(reg_overlap_mentioned_p): Rewrite to use a switch.
|
||||
|
||||
* ggc.h (struct rtx_def): Forward declare.
|
||||
|
||||
* print-rtl.c (debug_rtx_range): New.
|
||||
|
@ -39,7 +39,7 @@ static int max_dup_operands; /* Largest number of match_dup in any insn. */
|
||||
static int max_clobbers_per_insn;
|
||||
static int have_cc0_flag;
|
||||
static int have_cmove_flag;
|
||||
static int have_cond_arith_flag;
|
||||
static int have_cond_exec_flag;
|
||||
static int have_lo_sum_flag;
|
||||
static int have_peephole_flag;
|
||||
static int have_peephole2_flag;
|
||||
@ -131,21 +131,17 @@ walk_insn_part (part, recog_p, non_pc_set_src)
|
||||
two arms of the IF_THEN_ELSE are both MATCH_OPERAND. Otherwise,
|
||||
we have some specific IF_THEN_ELSE construct (like the doz
|
||||
instruction on the RS/6000) that can't be used in the general
|
||||
context we want it for. If the first operand is an arithmetic
|
||||
operation and the second is a MATCH_OPERNAND, show we have
|
||||
conditional arithmetic. */
|
||||
context we want it for. */
|
||||
|
||||
if (recog_p && non_pc_set_src
|
||||
&& GET_CODE (XEXP (part, 1)) == MATCH_OPERAND
|
||||
&& GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
|
||||
have_cmove_flag = 1;
|
||||
else if (recog_p && non_pc_set_src
|
||||
&& (GET_RTX_CLASS (GET_CODE (XEXP (part, 1))) == '1'
|
||||
|| GET_RTX_CLASS (GET_CODE (XEXP (part, 1))) == '2'
|
||||
|| GET_RTX_CLASS (GET_CODE (XEXP (part, 1))) == 'c')
|
||||
&& GET_CODE (XEXP (XEXP (part, 1), 0)) == MATCH_OPERAND
|
||||
&& GET_CODE (XEXP (part, 2)) == MATCH_OPERAND)
|
||||
have_cond_arith_flag = 1;
|
||||
break;
|
||||
|
||||
case COND_EXEC:
|
||||
if (recog_p)
|
||||
have_cond_exec_flag = 1;
|
||||
break;
|
||||
|
||||
case REG: case CONST_INT: case SYMBOL_REF:
|
||||
@ -341,8 +337,9 @@ from the machine description file `md'. */\n\n");
|
||||
|
||||
/* This is conditionally defined, in case the user writes code which emits
|
||||
more splits than we can readily see (and knows s/he does it). */
|
||||
printf ("#ifndef MAX_INSNS_PER_SPLIT\n#define MAX_INSNS_PER_SPLIT %d\n#endif\n",
|
||||
max_insns_per_split);
|
||||
printf ("#ifndef MAX_INSNS_PER_SPLIT\n");
|
||||
printf ("#define MAX_INSNS_PER_SPLIT %d\n", max_insns_per_split);
|
||||
printf ("#endif\n");
|
||||
|
||||
if (have_cc0_flag)
|
||||
printf ("#define HAVE_cc0\n");
|
||||
@ -350,11 +347,8 @@ from the machine description file `md'. */\n\n");
|
||||
if (have_cmove_flag)
|
||||
printf ("#define HAVE_conditional_move\n");
|
||||
|
||||
#if 0
|
||||
/* Disabled. See the discussion in jump.c. */
|
||||
if (have_cond_arith_flag)
|
||||
printf ("#define HAVE_conditional_arithmetic\n");
|
||||
#endif
|
||||
if (have_cond_exec_flag)
|
||||
printf ("#define HAVE_conditional_execution\n");
|
||||
|
||||
if (have_lo_sum_flag)
|
||||
printf ("#define HAVE_lo_sum\n");
|
||||
|
@ -2588,6 +2588,7 @@ haifa_classify_insn (insn)
|
||||
WORST_CLASS (tmp_class,
|
||||
may_trap_exp (SET_SRC (XVECEXP (pat, 0, i)), 0));
|
||||
break;
|
||||
case COND_EXEC:
|
||||
case TRAP_IF:
|
||||
tmp_class = TRAP_RISKY;
|
||||
break;
|
||||
@ -2617,6 +2618,7 @@ haifa_classify_insn (insn)
|
||||
WORST_CLASS (tmp_class,
|
||||
may_trap_exp (SET_SRC (pat), 0));
|
||||
break;
|
||||
case COND_EXEC:
|
||||
case TRAP_IF:
|
||||
tmp_class = TRAP_RISKY;
|
||||
break;
|
||||
@ -3649,6 +3651,15 @@ sched_analyze_insn (deps, x, insn, loop_notes)
|
||||
int maxreg = max_reg_num ();
|
||||
int i;
|
||||
|
||||
if (code == COND_EXEC)
|
||||
{
|
||||
sched_analyze_2 (deps, COND_EXEC_TEST (x), insn);
|
||||
|
||||
/* ??? Should be recording conditions so we reduce the number of
|
||||
false dependancies. */
|
||||
x = COND_EXEC_CODE (x);
|
||||
code = GET_CODE (x);
|
||||
}
|
||||
if (code == SET || code == CLOBBER)
|
||||
sched_analyze_1 (deps, x, insn);
|
||||
else if (code == PARALLEL)
|
||||
@ -3656,11 +3667,19 @@ sched_analyze_insn (deps, x, insn, loop_notes)
|
||||
register int i;
|
||||
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
|
||||
{
|
||||
code = GET_CODE (XVECEXP (x, 0, i));
|
||||
rtx sub = XVECEXP (x, 0, i);
|
||||
code = GET_CODE (sub);
|
||||
|
||||
if (code == COND_EXEC)
|
||||
{
|
||||
sched_analyze_2 (deps, COND_EXEC_TEST (sub), insn);
|
||||
sub = COND_EXEC_CODE (sub);
|
||||
code = GET_CODE (sub);
|
||||
}
|
||||
if (code == SET || code == CLOBBER)
|
||||
sched_analyze_1 (deps, XVECEXP (x, 0, i), insn);
|
||||
sched_analyze_1 (deps, sub, insn);
|
||||
else
|
||||
sched_analyze_2 (deps, XVECEXP (x, 0, i), insn);
|
||||
sched_analyze_2 (deps, sub, insn);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -5313,6 +5332,11 @@ print_pattern (buf, x, verbose)
|
||||
print_value (t1, XEXP (x, 0), verbose);
|
||||
sprintf (buf, "use %s", t1);
|
||||
break;
|
||||
case COND_EXEC:
|
||||
print_value (t1, COND_EXEC_CODE (x), verbose);
|
||||
print_value (t2, COND_EXEC_TEST (x), verbose);
|
||||
sprintf (buf, "cond_exec %s %s", t1, t2);
|
||||
break;
|
||||
case PARALLEL:
|
||||
{
|
||||
int i;
|
||||
|
@ -6190,6 +6190,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
|
||||
If GOAL is a memory ref and its address is not constant,
|
||||
and this insn P changes a register used in GOAL, return 0. */
|
||||
|
||||
if (GET_CODE (pat) == COND_EXEC)
|
||||
pat = COND_EXEC_CODE (pat);
|
||||
if (GET_CODE (pat) == SET || GET_CODE (pat) == CLOBBER)
|
||||
{
|
||||
register rtx dest = SET_DEST (pat);
|
||||
@ -6232,6 +6234,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
|
||||
for (i = XVECLEN (pat, 0) - 1; i >= 0; i--)
|
||||
{
|
||||
register rtx v1 = XVECEXP (pat, 0, i);
|
||||
if (GET_CODE (v1) == COND_EXEC)
|
||||
v1 = COND_EXEC_CODE (v1);
|
||||
if (GET_CODE (v1) == SET || GET_CODE (v1) == CLOBBER)
|
||||
{
|
||||
register rtx dest = SET_DEST (v1);
|
||||
|
@ -900,6 +900,13 @@ DEF_RTL_EXPR(CALL_PLACEHOLDER, "call_placeholder", "uuuu", 'x')
|
||||
of canonical RTL. It is, however, easier to manipulate this way. */
|
||||
DEF_RTL_EXPR(PHI, "phi", "E", 'x')
|
||||
|
||||
/* Conditionally execute code.
|
||||
Operand 0 is the condition that if true, the code is executed.
|
||||
Operand 1 is the code to be executed (typically a SET).
|
||||
|
||||
Semantics are that there are no side effects if the condition
|
||||
is false. */
|
||||
DEF_RTL_EXPR(COND_EXEC, "cond_exec", "ee", 'x')
|
||||
|
||||
/*
|
||||
Local variables:
|
||||
|
@ -807,6 +807,12 @@ extern const char * const note_insn_name[];
|
||||
#define TRAP_CONDITION(RTX) XCEXP(RTX, 0, TRAP_IF)
|
||||
#define TRAP_CODE(RTX) XCEXP(RTX, 1, TRAP_IF)
|
||||
|
||||
/* For a COND_EXEC rtx, COND_EXEC_TEST is the condition to base
|
||||
conditionally executing the code on, COND_EXEC_CODE is the code
|
||||
to execute if the condition is true. */
|
||||
#define COND_EXEC_TEST(RTX) XCEXP(RTX, 0, COND_EXEC)
|
||||
#define COND_EXEC_CODE(RTX) XCEXP(RTX, 1, COND_EXEC)
|
||||
|
||||
/* 1 in a SYMBOL_REF if it addresses this function's constants pool. */
|
||||
#define CONSTANT_POOL_ADDRESS_P(RTX) ((RTX)->unchanging)
|
||||
|
||||
|
108
gcc/rtlanal.c
108
gcc/rtlanal.c
@ -429,6 +429,11 @@ reg_referenced_p (x, body)
|
||||
return 1;
|
||||
return 0;
|
||||
|
||||
case COND_EXEC:
|
||||
if (reg_overlap_mentioned_p (x, COND_EXEC_TEST (body)))
|
||||
return 1;
|
||||
return reg_referenced_p (x, COND_EXEC_CODE (body));
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -949,52 +954,61 @@ reg_overlap_mentioned_p (x, in)
|
||||
/* If either argument is a constant, then modifying X can not affect IN. */
|
||||
if (CONSTANT_P (x) || CONSTANT_P (in))
|
||||
return 0;
|
||||
else if (GET_CODE (x) == SUBREG)
|
||||
|
||||
switch (GET_CODE (x))
|
||||
{
|
||||
case SUBREG:
|
||||
regno = REGNO (SUBREG_REG (x));
|
||||
if (regno < FIRST_PSEUDO_REGISTER)
|
||||
regno += SUBREG_WORD (x);
|
||||
}
|
||||
else if (GET_CODE (x) == REG)
|
||||
regno = REGNO (x);
|
||||
else if (GET_CODE (x) == MEM)
|
||||
{
|
||||
const char *fmt;
|
||||
int i;
|
||||
goto do_reg;
|
||||
|
||||
if (GET_CODE (in) == MEM)
|
||||
return 1;
|
||||
case REG:
|
||||
regno = REGNO (x);
|
||||
do_reg:
|
||||
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
||||
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
|
||||
return refers_to_regno_p (regno, endregno, in, NULL_PTR);
|
||||
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (in));
|
||||
case MEM:
|
||||
{
|
||||
const char *fmt;
|
||||
int i;
|
||||
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
|
||||
if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
|
||||
if (GET_CODE (in) == MEM)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
fmt = GET_RTX_FORMAT (GET_CODE (in));
|
||||
for (i = GET_RTX_LENGTH (GET_CODE (in)) - 1; i >= 0; i--)
|
||||
if (fmt[i] == 'e' && reg_overlap_mentioned_p (x, XEXP (in, i)))
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SCRATCH:
|
||||
case PC:
|
||||
case CC0:
|
||||
return reg_mentioned_p (x, in);
|
||||
|
||||
case PARALLEL:
|
||||
if (GET_MODE (x) == BLKmode)
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* If any register in here refers to it we return true. */
|
||||
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
|
||||
if (reg_overlap_mentioned_p (SET_DEST (XVECEXP (x, 0, i)), in))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
|
||||
|| GET_CODE (x) == CC0)
|
||||
return reg_mentioned_p (x, in);
|
||||
else if (GET_CODE (x) == PARALLEL
|
||||
&& GET_MODE (x) == BLKmode)
|
||||
{
|
||||
register int i;
|
||||
|
||||
/* If any register in here refers to it
|
||||
we return true. */
|
||||
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
|
||||
if (reg_overlap_mentioned_p (SET_DEST (XVECEXP (x, 0, i)), in))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
|
||||
endregno = regno + (regno < FIRST_PSEUDO_REGISTER
|
||||
? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
|
||||
|
||||
return refers_to_regno_p (regno, endregno, in, NULL_PTR);
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Used for communications between the next few functions. */
|
||||
@ -1108,7 +1122,9 @@ note_stores (x, fun, data)
|
||||
void (*fun) PARAMS ((rtx, rtx, void *));
|
||||
void *data;
|
||||
{
|
||||
if ((GET_CODE (x) == SET || GET_CODE (x) == CLOBBER))
|
||||
if (GET_CODE (x) == COND_EXEC)
|
||||
x = COND_EXEC_CODE (x);
|
||||
if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
|
||||
{
|
||||
register rtx dest = SET_DEST (x);
|
||||
while ((GET_CODE (dest) == SUBREG
|
||||
@ -1135,6 +1151,8 @@ note_stores (x, fun, data)
|
||||
for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
|
||||
{
|
||||
register rtx y = XVECEXP (x, 0, i);
|
||||
if (GET_CODE (y) == COND_EXEC)
|
||||
y = COND_EXEC_CODE (y);
|
||||
if (GET_CODE (y) == SET || GET_CODE (y) == CLOBBER)
|
||||
{
|
||||
register rtx dest = SET_DEST (y);
|
||||
@ -1213,7 +1231,7 @@ dead_or_set_regno_p (insn, test_regno)
|
||||
unsigned int test_regno;
|
||||
{
|
||||
unsigned int regno, endregno;
|
||||
rtx link;
|
||||
rtx link, pattern;
|
||||
|
||||
/* See if there is a death note for something that includes
|
||||
TEST_REGNO. */
|
||||
@ -1236,7 +1254,12 @@ dead_or_set_regno_p (insn, test_regno)
|
||||
&& find_regno_fusage (insn, CLOBBER, test_regno))
|
||||
return 1;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET)
|
||||
pattern = PATTERN (insn);
|
||||
|
||||
if (GET_CODE (pattern) == COND_EXEC)
|
||||
pattern = COND_EXEC_CODE (pattern);
|
||||
|
||||
if (GET_CODE (pattern) == SET)
|
||||
{
|
||||
rtx dest = SET_DEST (PATTERN (insn));
|
||||
|
||||
@ -1259,13 +1282,16 @@ dead_or_set_regno_p (insn, test_regno)
|
||||
|
||||
return (test_regno >= regno && test_regno < endregno);
|
||||
}
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
|
||||
else if (GET_CODE (pattern) == PARALLEL)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
||||
for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
|
||||
{
|
||||
rtx body = XVECEXP (PATTERN (insn), 0, i);
|
||||
rtx body = XVECEXP (pattern, 0, i);
|
||||
|
||||
if (GET_CODE (body) == COND_EXEC)
|
||||
body = COND_EXEC_CODE (body);
|
||||
|
||||
if (GET_CODE (body) == SET || GET_CODE (body) == CLOBBER)
|
||||
{
|
||||
|
@ -7942,4 +7942,12 @@ Note that this functionality is part of POSIX.
|
||||
Defining @code{TARGET_HAS_F_SETLKW} will enable the test coverage code
|
||||
to use file locking when exiting a program, which avoids race conditions
|
||||
if the program has forked.
|
||||
|
||||
@findex MAX_CONDITIONAL_EXECUTE
|
||||
@item MAX_CONDITIONAL_EXECUTE
|
||||
|
||||
A C expression for the maximum number of instructions to execute via
|
||||
conditional execution instructions instead of a branch. A value of
|
||||
@code{BRANCH_COST}+1 is the default if the machine does not use cc0, and
|
||||
1 if it does use cc0.
|
||||
@end table
|
||||
|
Loading…
Reference in New Issue
Block a user