diff options
author | DJ Delorie <dj@redhat.com> | 2001-07-27 23:13:34 -0400 |
---|---|---|
committer | DJ Delorie <dj@gcc.gnu.org> | 2001-07-27 23:13:34 -0400 |
commit | 7f64687763a1770d52b5c11d2e5044d3ccda20ed (patch) | |
tree | b6602dcfbcbb2441cb51d0b3db365bfa56c733e6 /gcc/ifcvt.c | |
parent | da397f8ed09544229b06599cb2878421a2844670 (diff) | |
download | gcc-7f64687763a1770d52b5c11d2e5044d3ccda20ed.zip gcc-7f64687763a1770d52b5c11d2e5044d3ccda20ed.tar.gz gcc-7f64687763a1770d52b5c11d2e5044d3ccda20ed.tar.bz2 |
ifcvt.c (noce_get_alt_condition): If the condition is a compare against a constant...
* ifcvt.c (noce_get_alt_condition): If the condition is a compare
against a constant, try to adjust the compare to have the desired
constant in it so that min/max optimizations happen more often.
From-SVN: r44435
Diffstat (limited to 'gcc/ifcvt.c')
-rw-r--r-- | gcc/ifcvt.c | 110 |
1 files changed, 109 insertions, 1 deletions
diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 08ec087..4de879d 100644 --- a/gcc/ifcvt.c +++ b/gcc/ifcvt.c @@ -1,5 +1,5 @@ /* If-conversion support. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2001 Free Software Foundation, Inc. This file is part of GNU CC. @@ -1150,6 +1150,114 @@ noce_get_alt_condition (if_info, target, earliest) = GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF && XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump); + /* If we're looking for a constant, try to make the conditional + have that constant in it. There are two reasons why it may + not have the constant we want: + + 1. GCC may have needed to put the constant in a register, because + the target can't compare directly against that constant. For + this case, we look for a SET immediately before the comparison + that puts a constant in that register. + + 2. GCC may have canonicalized the conditional, for example + replacing "if x < 4" with "if x <= 3". We can undo that (or + make equivalent types of changes) to get the constants we need + if they're off by one in the right direction. */ + + if (GET_CODE (target) == CONST_INT) + { + enum rtx_code code = GET_CODE (if_info->cond); + rtx op_a = XEXP (if_info->cond, 0); + rtx op_b = XEXP (if_info->cond, 1); + rtx prev_insn; + + /* First, look to see if we put a constant in a register. */ + prev_insn = PREV_INSN (if_info->cond_earliest); + if (prev_insn + && INSN_P (prev_insn) + && GET_CODE (PATTERN (prev_insn)) == SET) + { + rtx src = find_reg_equal_equiv_note (prev_insn); + if (!src) + src = SET_SRC (PATTERN (prev_insn)); + if (GET_CODE (src) == CONST_INT) + { + if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn)))) + { + op_a = src; + if_info->cond_earliest = prev_insn; + } + else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn)))) + { + op_b = src; + if_info->cond_earliest = prev_insn; + } + + if (GET_CODE (op_a) == CONST_INT) + { + rtx tmp = op_a; + op_a = op_b; + op_b = tmp; + code = swap_condition (code); + } + } + } + + /* Now, look to see if we can get the right constant by + adjusting the conditional. */ + if (GET_CODE (op_b) == CONST_INT) + { + HOST_WIDE_INT desired_val = INTVAL (target); + HOST_WIDE_INT actual_val = INTVAL (op_b); + + switch (code) + { + case LT: + if (actual_val == desired_val + 1) + { + code = LE; + op_b = GEN_INT (desired_val); + } + break; + case LE: + if (actual_val == desired_val - 1) + { + code = LT; + op_b = GEN_INT (desired_val); + } + break; + case GT: + if (actual_val == desired_val - 1) + { + code = GE; + op_b = GEN_INT (desired_val); + } + break; + case GE: + if (actual_val == desired_val + 1) + { + code = GT; + op_b = GEN_INT (desired_val); + } + break; + default: + break; + } + } + + /* If we made any changes, generate a new conditional that is + equivalent to what we started with, but has the right + constants in it. */ + if (code != GET_CODE (if_info->cond) + || op_a != XEXP (if_info->cond, 0) + || op_b != XEXP (if_info->cond, 1)) + { + cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b); + *earliest = if_info->cond_earliest; + return cond; + } + } + cond = canonicalize_condition (if_info->jump, cond, reverse, earliest, target); if (! cond || ! reg_mentioned_p (target, cond)) |