* 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
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.
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;
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:
/* 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");
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");
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;
WORST_CLASS (tmp_class,
may_trap_exp (SET_SRC (pat), 0));
break;
+ case COND_EXEC:
case TRAP_IF:
tmp_class = TRAP_RISKY;
break;
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)
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
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;
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);
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);
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:
#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)
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;
}
/* 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;
- }
- 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;
+ 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;
- /* 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 ();
+ return 0;
+ }
+
+ case SCRATCH:
+ case PC:
+ case CC0:
+ return reg_mentioned_p (x, in);
- endregno = regno + (regno < FIRST_PSEUDO_REGISTER
- ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
+ case PARALLEL:
+ if (GET_MODE (x) == BLKmode)
+ {
+ register int i;
- return refers_to_regno_p (regno, endregno, in, NULL_PTR);
+ /* 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;
+ }
+
+ abort ();
}
\f
/* Used for communications between the next few functions. */
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
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);
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. */
&& 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));
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)
{
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