diff options
author | Richard Henderson <rth@cygnus.com> | 2000-04-07 02:24:45 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2000-04-07 02:24:45 -0700 |
commit | 0c99ec5c426117d4cd53e64e9ad4b22f3a903f36 (patch) | |
tree | a36fbb677db9b9d77dd79d4991fb6f4bd8349ebc | |
parent | 4c85a96d6e0a24baeeb64a13e1d522b5ee04d76f (diff) | |
download | gcc-0c99ec5c426117d4cd53e64e9ad4b22f3a903f36.zip gcc-0c99ec5c426117d4cd53e64e9ad4b22f3a903f36.tar.gz gcc-0c99ec5c426117d4cd53e64e9ad4b22f3a903f36.tar.bz2 |
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
-rw-r--r-- | gcc/ChangeLog | 16 | ||||
-rw-r--r-- | gcc/genconfig.c | 30 | ||||
-rw-r--r-- | gcc/haifa-sched.c | 30 | ||||
-rw-r--r-- | gcc/reload.c | 4 | ||||
-rw-r--r-- | gcc/rtl.def | 7 | ||||
-rw-r--r-- | gcc/rtl.h | 6 | ||||
-rw-r--r-- | gcc/rtlanal.c | 106 | ||||
-rw-r--r-- | gcc/tm.texi | 8 |
8 files changed, 146 insertions, 61 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c28a597..75360a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/genconfig.c b/gcc/genconfig.c index 8c8ee9d..65c8701 100644 --- a/gcc/genconfig.c +++ b/gcc/genconfig.c @@ -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"); diff --git a/gcc/haifa-sched.c b/gcc/haifa-sched.c index eb6f121..36a4cc8 100644 --- a/gcc/haifa-sched.c +++ b/gcc/haifa-sched.c @@ -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; diff --git a/gcc/reload.c b/gcc/reload.c index 3e5d277..128af48 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -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); diff --git a/gcc/rtl.def b/gcc/rtl.def index 570abdc..69c14e0 100644 --- a/gcc/rtl.def +++ b/gcc/rtl.def @@ -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) diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index b44b992..d9087cd 100644 --- a/gcc/rtlanal.c +++ b/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; - } - 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 (); } /* 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) { diff --git a/gcc/tm.texi b/gcc/tm.texi index dac8911..7d9610c 100644 --- a/gcc/tm.texi +++ b/gcc/tm.texi @@ -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 |