From: steven Date: Tue, 2 Nov 2004 17:59:46 +0000 (+0000) Subject: * cfgloop.h (struct loop): Update comment. X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=commitdiff_plain;h=ea92ba8003d183cd5defac7bd67254e8ce04f18e * cfgloop.h (struct loop): Update comment. * cse.c (cse_main): Remove obsolete comment. * expr.h (gen_cond_trap): Move prototype under functions provided by optabs.c. (canonicalize_condition, get_condition): Move to... * rtl.h (canonicalize_condition, get_condition): ...here. (branch_target_load_optimize): Add comment that this function is in bt-load.c. * loop.c (canonicalize_condition, get_condition): Move to... * rtlanal.c (canonicalize_condition, get_condition): ...here. * sched-deps.c (get_condition): Rename to sched_get_condition. (add_dependence): Update this caller. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@89995 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 00dc1027ea9..f6c687404fe 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2004-11-02 Steven Bosscher + + * cfgloop.h (struct loop): Update comment. + * cse.c (cse_main): Remove obsolete comment. + + * expr.h (gen_cond_trap): Move prototype under functions provided + by optabs.c. + (canonicalize_condition, get_condition): Move to... + * rtl.h (canonicalize_condition, get_condition): ...here. + (branch_target_load_optimize): Add comment that this function is + in bt-load.c. + * loop.c (canonicalize_condition, get_condition): Move to... + * rtlanal.c (canonicalize_condition, get_condition): ...here. + * sched-deps.c (get_condition): Rename to sched_get_condition. + (add_dependence): Update this caller. + 2004-11-02 Andrew Pinski PR tree-opt/16808 diff --git a/gcc/cfgloop.h b/gcc/cfgloop.h index 61af71738a1..3261adb8e2d 100644 --- a/gcc/cfgloop.h +++ b/gcc/cfgloop.h @@ -144,7 +144,7 @@ struct loop void *aux; /* The following are currently used by loop.c but they are likely to - disappear as loop.c is converted to use the CFG. */ + disappear when loop.c is replaced and removed. */ /* The NOTE_INSN_LOOP_BEG. */ rtx start; diff --git a/gcc/cse.c b/gcc/cse.c index 2b21852544b..19e7f7145cf 100644 --- a/gcc/cse.c +++ b/gcc/cse.c @@ -6775,11 +6775,7 @@ cse_main (rtx f, int nregs, FILE *file) /* Process a single basic block. FROM and TO and the limits of the basic block. NEXT_BRANCH points to the branch path when following jumps or - a null path when not following jumps. - - AROUND_LOOP is nonzero if we are to try to cse around to the start of a - loop. This is true when we are being called for the last time on a - block and this CSE pass is before loop.c. */ + a null path when not following jumps. */ static rtx cse_basic_block (rtx from, rtx to, struct branch_path *next_branch) diff --git a/gcc/expr.h b/gcc/expr.h index 54b04c2eb60..b5ec33f02bf 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -298,6 +298,9 @@ extern void emit_cmp_and_jump_insns (rtx, rtx, enum rtx_code, rtx, /* Generate code to indirectly jump to a location given in the rtx LOC. */ extern void emit_indirect_jump (rtx); +/* Generate a conditional trap instruction. */ +extern rtx gen_cond_trap (enum rtx_code, rtx, rtx, rtx); + #include "insn-config.h" #ifdef HAVE_conditional_move @@ -329,19 +332,6 @@ extern rtx emit_store_flag (rtx, enum rtx_code, rtx, rtx, enum machine_mode, /* Like emit_store_flag, but always succeeds. */ extern rtx emit_store_flag_force (rtx, enum rtx_code, rtx, rtx, enum machine_mode, int, int); - -/* Functions from loop.c: */ - -/* Given an insn and condition, return a canonical description of - the test being made. */ -extern rtx canonicalize_condition (rtx, rtx, int, rtx *, rtx, int, int); - -/* Given a JUMP_INSN, return a canonical description of the test - being made. */ -extern rtx get_condition (rtx, rtx *, int, int); - -/* Generate a conditional trap instruction. */ -extern rtx gen_cond_trap (enum rtx_code, rtx, rtx, rtx); /* Functions from builtins.c: */ extern rtx expand_builtin (tree, rtx, rtx, enum machine_mode, int); diff --git a/gcc/loop.c b/gcc/loop.c index a573616d0e1..08b85293b8a 100644 --- a/gcc/loop.c +++ b/gcc/loop.c @@ -10438,319 +10438,8 @@ update_reg_last_use (rtx x, rtx insn) } } -/* Given an insn INSN and condition COND, return the condition in a - canonical form to simplify testing by callers. Specifically: - - (1) The code will always be a comparison operation (EQ, NE, GT, etc.). - (2) Both operands will be machine operands; (cc0) will have been replaced. - (3) If an operand is a constant, it will be the second operand. - (4) (LE x const) will be replaced with (LT x ) and similarly - for GE, GEU, and LEU. - - If the condition cannot be understood, or is an inequality floating-point - comparison which needs to be reversed, 0 will be returned. - - If REVERSE is nonzero, then reverse the condition prior to canonizing it. - - If EARLIEST is nonzero, it is a pointer to a place where the earliest - insn used in locating the condition was found. If a replacement test - of the condition is desired, it should be placed in front of that - insn and we will be sure that the inputs are still valid. - - If WANT_REG is nonzero, we wish the condition to be relative to that - register, if possible. Therefore, do not canonicalize the condition - further. If ALLOW_CC_MODE is nonzero, allow the condition returned - to be a compare to a CC mode register. - - If VALID_AT_INSN_P, the condition must be valid at both *EARLIEST - and at INSN. */ - -rtx -canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest, - rtx want_reg, int allow_cc_mode, int valid_at_insn_p) -{ - enum rtx_code code; - rtx prev = insn; - rtx set; - rtx tem; - rtx op0, op1; - int reverse_code = 0; - enum machine_mode mode; - - code = GET_CODE (cond); - mode = GET_MODE (cond); - op0 = XEXP (cond, 0); - op1 = XEXP (cond, 1); - - if (reverse) - code = reversed_comparison_code (cond, insn); - if (code == UNKNOWN) - return 0; - - if (earliest) - *earliest = insn; - - /* If we are comparing a register with zero, see if the register is set - in the previous insn to a COMPARE or a comparison operation. Perform - the same tests as a function of STORE_FLAG_VALUE as find_comparison_args - in cse.c */ - - while ((GET_RTX_CLASS (code) == RTX_COMPARE - || GET_RTX_CLASS (code) == RTX_COMM_COMPARE) - && op1 == CONST0_RTX (GET_MODE (op0)) - && op0 != want_reg) - { - /* Set nonzero when we find something of interest. */ - rtx x = 0; - -#ifdef HAVE_cc0 - /* If comparison with cc0, import actual comparison from compare - insn. */ - if (op0 == cc0_rtx) - { - if ((prev = prev_nonnote_insn (prev)) == 0 - || !NONJUMP_INSN_P (prev) - || (set = single_set (prev)) == 0 - || SET_DEST (set) != cc0_rtx) - return 0; - - op0 = SET_SRC (set); - op1 = CONST0_RTX (GET_MODE (op0)); - if (earliest) - *earliest = prev; - } -#endif - - /* If this is a COMPARE, pick up the two things being compared. */ - if (GET_CODE (op0) == COMPARE) - { - op1 = XEXP (op0, 1); - op0 = XEXP (op0, 0); - continue; - } - else if (!REG_P (op0)) - break; - - /* Go back to the previous insn. Stop if it is not an INSN. We also - stop if it isn't a single set or if it has a REG_INC note because - we don't want to bother dealing with it. */ - - if ((prev = prev_nonnote_insn (prev)) == 0 - || !NONJUMP_INSN_P (prev) - || FIND_REG_INC_NOTE (prev, NULL_RTX)) - break; - - set = set_of (op0, prev); - - if (set - && (GET_CODE (set) != SET - || !rtx_equal_p (SET_DEST (set), op0))) - break; - - /* If this is setting OP0, get what it sets it to if it looks - relevant. */ - if (set) - { - enum machine_mode inner_mode = GET_MODE (SET_DEST (set)); -#ifdef FLOAT_STORE_FLAG_VALUE - REAL_VALUE_TYPE fsfv; -#endif - - /* ??? We may not combine comparisons done in a CCmode with - comparisons not done in a CCmode. This is to aid targets - like Alpha that have an IEEE compliant EQ instruction, and - a non-IEEE compliant BEQ instruction. The use of CCmode is - actually artificial, simply to prevent the combination, but - should not affect other platforms. - - However, we must allow VOIDmode comparisons to match either - CCmode or non-CCmode comparison, because some ports have - modeless comparisons inside branch patterns. - - ??? This mode check should perhaps look more like the mode check - in simplify_comparison in combine. */ - - if ((GET_CODE (SET_SRC (set)) == COMPARE - || (((code == NE - || (code == LT - && GET_MODE_CLASS (inner_mode) == MODE_INT - && (GET_MODE_BITSIZE (inner_mode) - <= HOST_BITS_PER_WIDE_INT) - && (STORE_FLAG_VALUE - & ((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (inner_mode) - 1)))) -#ifdef FLOAT_STORE_FLAG_VALUE - || (code == LT - && GET_MODE_CLASS (inner_mode) == MODE_FLOAT - && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), - REAL_VALUE_NEGATIVE (fsfv))) -#endif - )) - && COMPARISON_P (SET_SRC (set)))) - && (((GET_MODE_CLASS (mode) == MODE_CC) - == (GET_MODE_CLASS (inner_mode) == MODE_CC)) - || mode == VOIDmode || inner_mode == VOIDmode)) - x = SET_SRC (set); - else if (((code == EQ - || (code == GE - && (GET_MODE_BITSIZE (inner_mode) - <= HOST_BITS_PER_WIDE_INT) - && GET_MODE_CLASS (inner_mode) == MODE_INT - && (STORE_FLAG_VALUE - & ((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (inner_mode) - 1)))) -#ifdef FLOAT_STORE_FLAG_VALUE - || (code == GE - && GET_MODE_CLASS (inner_mode) == MODE_FLOAT - && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), - REAL_VALUE_NEGATIVE (fsfv))) -#endif - )) - && COMPARISON_P (SET_SRC (set)) - && (((GET_MODE_CLASS (mode) == MODE_CC) - == (GET_MODE_CLASS (inner_mode) == MODE_CC)) - || mode == VOIDmode || inner_mode == VOIDmode)) - - { - reverse_code = 1; - x = SET_SRC (set); - } - else - break; - } - - else if (reg_set_p (op0, prev)) - /* If this sets OP0, but not directly, we have to give up. */ - break; - - if (x) - { - /* If the caller is expecting the condition to be valid at INSN, - make sure X doesn't change before INSN. */ - if (valid_at_insn_p) - if (modified_in_p (x, prev) || modified_between_p (x, prev, insn)) - break; - if (COMPARISON_P (x)) - code = GET_CODE (x); - if (reverse_code) - { - code = reversed_comparison_code (x, prev); - if (code == UNKNOWN) - return 0; - reverse_code = 0; - } - - op0 = XEXP (x, 0), op1 = XEXP (x, 1); - if (earliest) - *earliest = prev; - } - } - - /* If constant is first, put it last. */ - if (CONSTANT_P (op0)) - code = swap_condition (code), tem = op0, op0 = op1, op1 = tem; - - /* If OP0 is the result of a comparison, we weren't able to find what - was really being compared, so fail. */ - if (!allow_cc_mode - && GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) - return 0; - - /* Canonicalize any ordered comparison with integers involving equality - if we can do computations in the relevant mode and we do not - overflow. */ - - if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_CC - && GET_CODE (op1) == CONST_INT - && GET_MODE (op0) != VOIDmode - && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) - { - HOST_WIDE_INT const_val = INTVAL (op1); - unsigned HOST_WIDE_INT uconst_val = const_val; - unsigned HOST_WIDE_INT max_val - = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0)); - - switch (code) - { - case LE: - if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1) - code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0)); - break; - - /* When cross-compiling, const_val might be sign-extended from - BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */ - case GE: - if ((HOST_WIDE_INT) (const_val & max_val) - != (((HOST_WIDE_INT) 1 - << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) - code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0)); - break; - - case LEU: - if (uconst_val < max_val) - code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0)); - break; - - case GEU: - if (uconst_val != 0) - code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0)); - break; - - default: - break; - } - } - - /* Never return CC0; return zero instead. */ - if (CC0_P (op0)) - return 0; - - return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); -} - -/* Given a jump insn JUMP, return the condition that will cause it to branch - to its JUMP_LABEL. If the condition cannot be understood, or is an - inequality floating-point comparison which needs to be reversed, 0 will - be returned. - - If EARLIEST is nonzero, it is a pointer to a place where the earliest - insn used in locating the condition was found. If a replacement test - of the condition is desired, it should be placed in front of that - insn and we will be sure that the inputs are still valid. If EARLIEST - is null, the returned condition will be valid at INSN. - - If ALLOW_CC_MODE is nonzero, allow the condition returned to be a - compare CC mode register. - - VALID_AT_INSN_P is the same as for canonicalize_condition. */ - -rtx -get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p) -{ - rtx cond; - int reverse; - rtx set; - - /* If this is not a standard conditional jump, we can't parse it. */ - if (!JUMP_P (jump) - || ! any_condjump_p (jump)) - return 0; - set = pc_set (jump); - - cond = XEXP (SET_SRC (set), 0); - - /* If this branches to JUMP_LABEL when the condition is false, reverse - the condition. */ - reverse - = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF - && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump); - - return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX, - allow_cc_mode, valid_at_insn_p); -} - -/* Similar to above routine, except that we also put an invariant last - unless both operands are invariants. */ +/* Similar to rtlanal.c:get_condition, except that we also put an + invariant last unless both operands are invariants. */ static rtx get_condition_for_loop (const struct loop *loop, rtx x) diff --git a/gcc/rtl.h b/gcc/rtl.h index 9b9bfcce6b7..67eea8b04b9 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -1657,6 +1657,15 @@ extern bool keep_with_call_p (rtx); extern bool label_is_jump_target_p (rtx, rtx); extern int insn_rtx_cost (rtx); +/* Given an insn and condition, return a canonical description of + the test being made. */ +extern rtx canonicalize_condition (rtx, rtx, int, rtx *, rtx, int, int); + +/* Given a JUMP_INSN, return a canonical description of the test + being made. */ +extern rtx get_condition (rtx, rtx *, int, int); + + /* flow.c */ extern rtx find_use_as_address (rtx, rtx, HOST_WIDE_INT); @@ -2017,6 +2026,8 @@ extern void print_inline_rtx (FILE *, rtx, int); /* In loop.c */ extern void init_loop (void); extern void loop_optimize (rtx, FILE *, int); + +/* In bt-load.c */ extern void branch_target_load_optimize (bool); /* In function.c */ diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index d61df8902bf..8ada3974c1b 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -4333,3 +4333,315 @@ insn_rtx_cost (rtx pat) cost = rtx_cost (SET_SRC (set), SET); return cost > 0 ? cost : COSTS_N_INSNS (1); } + +/* Given an insn INSN and condition COND, return the condition in a + canonical form to simplify testing by callers. Specifically: + + (1) The code will always be a comparison operation (EQ, NE, GT, etc.). + (2) Both operands will be machine operands; (cc0) will have been replaced. + (3) If an operand is a constant, it will be the second operand. + (4) (LE x const) will be replaced with (LT x ) and similarly + for GE, GEU, and LEU. + + If the condition cannot be understood, or is an inequality floating-point + comparison which needs to be reversed, 0 will be returned. + + If REVERSE is nonzero, then reverse the condition prior to canonizing it. + + If EARLIEST is nonzero, it is a pointer to a place where the earliest + insn used in locating the condition was found. If a replacement test + of the condition is desired, it should be placed in front of that + insn and we will be sure that the inputs are still valid. + + If WANT_REG is nonzero, we wish the condition to be relative to that + register, if possible. Therefore, do not canonicalize the condition + further. If ALLOW_CC_MODE is nonzero, allow the condition returned + to be a compare to a CC mode register. + + If VALID_AT_INSN_P, the condition must be valid at both *EARLIEST + and at INSN. */ + +rtx +canonicalize_condition (rtx insn, rtx cond, int reverse, rtx *earliest, + rtx want_reg, int allow_cc_mode, int valid_at_insn_p) +{ + enum rtx_code code; + rtx prev = insn; + rtx set; + rtx tem; + rtx op0, op1; + int reverse_code = 0; + enum machine_mode mode; + + code = GET_CODE (cond); + mode = GET_MODE (cond); + op0 = XEXP (cond, 0); + op1 = XEXP (cond, 1); + + if (reverse) + code = reversed_comparison_code (cond, insn); + if (code == UNKNOWN) + return 0; + + if (earliest) + *earliest = insn; + + /* If we are comparing a register with zero, see if the register is set + in the previous insn to a COMPARE or a comparison operation. Perform + the same tests as a function of STORE_FLAG_VALUE as find_comparison_args + in cse.c */ + + while ((GET_RTX_CLASS (code) == RTX_COMPARE + || GET_RTX_CLASS (code) == RTX_COMM_COMPARE) + && op1 == CONST0_RTX (GET_MODE (op0)) + && op0 != want_reg) + { + /* Set nonzero when we find something of interest. */ + rtx x = 0; + +#ifdef HAVE_cc0 + /* If comparison with cc0, import actual comparison from compare + insn. */ + if (op0 == cc0_rtx) + { + if ((prev = prev_nonnote_insn (prev)) == 0 + || !NONJUMP_INSN_P (prev) + || (set = single_set (prev)) == 0 + || SET_DEST (set) != cc0_rtx) + return 0; + + op0 = SET_SRC (set); + op1 = CONST0_RTX (GET_MODE (op0)); + if (earliest) + *earliest = prev; + } +#endif + + /* If this is a COMPARE, pick up the two things being compared. */ + if (GET_CODE (op0) == COMPARE) + { + op1 = XEXP (op0, 1); + op0 = XEXP (op0, 0); + continue; + } + else if (!REG_P (op0)) + break; + + /* Go back to the previous insn. Stop if it is not an INSN. We also + stop if it isn't a single set or if it has a REG_INC note because + we don't want to bother dealing with it. */ + + if ((prev = prev_nonnote_insn (prev)) == 0 + || !NONJUMP_INSN_P (prev) + || FIND_REG_INC_NOTE (prev, NULL_RTX)) + break; + + set = set_of (op0, prev); + + if (set + && (GET_CODE (set) != SET + || !rtx_equal_p (SET_DEST (set), op0))) + break; + + /* If this is setting OP0, get what it sets it to if it looks + relevant. */ + if (set) + { + enum machine_mode inner_mode = GET_MODE (SET_DEST (set)); +#ifdef FLOAT_STORE_FLAG_VALUE + REAL_VALUE_TYPE fsfv; +#endif + + /* ??? We may not combine comparisons done in a CCmode with + comparisons not done in a CCmode. This is to aid targets + like Alpha that have an IEEE compliant EQ instruction, and + a non-IEEE compliant BEQ instruction. The use of CCmode is + actually artificial, simply to prevent the combination, but + should not affect other platforms. + + However, we must allow VOIDmode comparisons to match either + CCmode or non-CCmode comparison, because some ports have + modeless comparisons inside branch patterns. + + ??? This mode check should perhaps look more like the mode check + in simplify_comparison in combine. */ + + if ((GET_CODE (SET_SRC (set)) == COMPARE + || (((code == NE + || (code == LT + && GET_MODE_CLASS (inner_mode) == MODE_INT + && (GET_MODE_BITSIZE (inner_mode) + <= HOST_BITS_PER_WIDE_INT) + && (STORE_FLAG_VALUE + & ((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (inner_mode) - 1)))) +#ifdef FLOAT_STORE_FLAG_VALUE + || (code == LT + && GET_MODE_CLASS (inner_mode) == MODE_FLOAT + && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), + REAL_VALUE_NEGATIVE (fsfv))) +#endif + )) + && COMPARISON_P (SET_SRC (set)))) + && (((GET_MODE_CLASS (mode) == MODE_CC) + == (GET_MODE_CLASS (inner_mode) == MODE_CC)) + || mode == VOIDmode || inner_mode == VOIDmode)) + x = SET_SRC (set); + else if (((code == EQ + || (code == GE + && (GET_MODE_BITSIZE (inner_mode) + <= HOST_BITS_PER_WIDE_INT) + && GET_MODE_CLASS (inner_mode) == MODE_INT + && (STORE_FLAG_VALUE + & ((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (inner_mode) - 1)))) +#ifdef FLOAT_STORE_FLAG_VALUE + || (code == GE + && GET_MODE_CLASS (inner_mode) == MODE_FLOAT + && (fsfv = FLOAT_STORE_FLAG_VALUE (inner_mode), + REAL_VALUE_NEGATIVE (fsfv))) +#endif + )) + && COMPARISON_P (SET_SRC (set)) + && (((GET_MODE_CLASS (mode) == MODE_CC) + == (GET_MODE_CLASS (inner_mode) == MODE_CC)) + || mode == VOIDmode || inner_mode == VOIDmode)) + + { + reverse_code = 1; + x = SET_SRC (set); + } + else + break; + } + + else if (reg_set_p (op0, prev)) + /* If this sets OP0, but not directly, we have to give up. */ + break; + + if (x) + { + /* If the caller is expecting the condition to be valid at INSN, + make sure X doesn't change before INSN. */ + if (valid_at_insn_p) + if (modified_in_p (x, prev) || modified_between_p (x, prev, insn)) + break; + if (COMPARISON_P (x)) + code = GET_CODE (x); + if (reverse_code) + { + code = reversed_comparison_code (x, prev); + if (code == UNKNOWN) + return 0; + reverse_code = 0; + } + + op0 = XEXP (x, 0), op1 = XEXP (x, 1); + if (earliest) + *earliest = prev; + } + } + + /* If constant is first, put it last. */ + if (CONSTANT_P (op0)) + code = swap_condition (code), tem = op0, op0 = op1, op1 = tem; + + /* If OP0 is the result of a comparison, we weren't able to find what + was really being compared, so fail. */ + if (!allow_cc_mode + && GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC) + return 0; + + /* Canonicalize any ordered comparison with integers involving equality + if we can do computations in the relevant mode and we do not + overflow. */ + + if (GET_MODE_CLASS (GET_MODE (op0)) != MODE_CC + && GET_CODE (op1) == CONST_INT + && GET_MODE (op0) != VOIDmode + && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) + { + HOST_WIDE_INT const_val = INTVAL (op1); + unsigned HOST_WIDE_INT uconst_val = const_val; + unsigned HOST_WIDE_INT max_val + = (unsigned HOST_WIDE_INT) GET_MODE_MASK (GET_MODE (op0)); + + switch (code) + { + case LE: + if ((unsigned HOST_WIDE_INT) const_val != max_val >> 1) + code = LT, op1 = gen_int_mode (const_val + 1, GET_MODE (op0)); + break; + + /* When cross-compiling, const_val might be sign-extended from + BITS_PER_WORD to HOST_BITS_PER_WIDE_INT */ + case GE: + if ((HOST_WIDE_INT) (const_val & max_val) + != (((HOST_WIDE_INT) 1 + << (GET_MODE_BITSIZE (GET_MODE (op0)) - 1)))) + code = GT, op1 = gen_int_mode (const_val - 1, GET_MODE (op0)); + break; + + case LEU: + if (uconst_val < max_val) + code = LTU, op1 = gen_int_mode (uconst_val + 1, GET_MODE (op0)); + break; + + case GEU: + if (uconst_val != 0) + code = GTU, op1 = gen_int_mode (uconst_val - 1, GET_MODE (op0)); + break; + + default: + break; + } + } + + /* Never return CC0; return zero instead. */ + if (CC0_P (op0)) + return 0; + + return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); +} + +/* Given a jump insn JUMP, return the condition that will cause it to branch + to its JUMP_LABEL. If the condition cannot be understood, or is an + inequality floating-point comparison which needs to be reversed, 0 will + be returned. + + If EARLIEST is nonzero, it is a pointer to a place where the earliest + insn used in locating the condition was found. If a replacement test + of the condition is desired, it should be placed in front of that + insn and we will be sure that the inputs are still valid. If EARLIEST + is null, the returned condition will be valid at INSN. + + If ALLOW_CC_MODE is nonzero, allow the condition returned to be a + compare CC mode register. + + VALID_AT_INSN_P is the same as for canonicalize_condition. */ + +rtx +get_condition (rtx jump, rtx *earliest, int allow_cc_mode, int valid_at_insn_p) +{ + rtx cond; + int reverse; + rtx set; + + /* If this is not a standard conditional jump, we can't parse it. */ + if (!JUMP_P (jump) + || ! any_condjump_p (jump)) + return 0; + set = pc_set (jump); + + cond = XEXP (SET_SRC (set), 0); + + /* If this branches to JUMP_LABEL when the condition is false, reverse + the condition. */ + reverse + = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF + && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (jump); + + return canonicalize_condition (jump, cond, reverse, earliest, NULL_RTX, + allow_cc_mode, valid_at_insn_p); +} + diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c index 1df1b47facb..ef53ea602aa 100644 --- a/gcc/sched-deps.c +++ b/gcc/sched-deps.c @@ -101,7 +101,7 @@ static void sched_analyze_1 (struct deps *, rtx, rtx); static void sched_analyze_2 (struct deps *, rtx, rtx); static void sched_analyze_insn (struct deps *, rtx, rtx, rtx); -static rtx get_condition (rtx); +static rtx sched_get_condition (rtx); static int conditions_mutex_p (rtx, rtx); /* Return nonzero if a load of the memory reference MEM can cause a trap. */ @@ -138,7 +138,7 @@ find_insn_list (rtx insn, rtx list) /* Find the condition under which INSN is executed. */ static rtx -get_condition (rtx insn) +sched_get_condition (rtx insn) { rtx pat = PATTERN (insn); rtx src; @@ -218,8 +218,8 @@ add_dependence (rtx insn, rtx elem, enum reg_note dep_type) be dependent. */ if (!CALL_P (insn) && !CALL_P (elem)) { - cond1 = get_condition (insn); - cond2 = get_condition (elem); + cond1 = sched_get_condition (insn); + cond2 = sched_get_condition (elem); if (cond1 && cond2 && conditions_mutex_p (cond1, cond2) /* Make sure first instruction doesn't affect condition of second