summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-30 23:27:52 +0000
committerdje <dje@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-30 23:27:52 +0000
commit0cb3e18b4b762914e0b0f091f9e9b55991fe89d6 (patch)
treed95f24ee811f21b2743ece3e6720b2fd527d36e1
parent213fb6cc62fbba3f974b0d2e80b75ac7645a1d17 (diff)
downloadgcc-0cb3e18b4b762914e0b0f091f9e9b55991fe89d6.tar.gz
* unroll.c (unroll_loop): Correct special exit cases.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@47499 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog4
-rw-r--r--gcc/unroll.c41
2 files changed, 36 insertions, 9 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 85aa8d205f3..b077028e7ba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,7 @@
+2001-11-30 Zoltan Hidvegi <hzoli@hzoli.2y.net>
+
+ * unroll.c (unroll_loop): Correct special exit cases.
+
2001-11-30 Stephane Carrez <Stephane.Carrez@sun.com>
* config/sparc/sparc.c (DF_MODES_NO_S): Fix pr/3623, define to
diff --git a/gcc/unroll.c b/gcc/unroll.c
index 4b7dd974925..b66916e320b 100644
--- a/gcc/unroll.c
+++ b/gcc/unroll.c
@@ -901,6 +901,9 @@ unroll_loop (loop, insn_count, strength_reduce_p)
rtx diff;
rtx *labels;
int abs_inc, neg_inc;
+ enum rtx_code cc = loop_info->comparison_code;
+ int less_p = (cc == LE || cc == LEU || cc == LT || cc == LTU);
+ int unsigned_p = (cc == LEU || cc == GEU || cc == LTU || cc == GTU);
map->reg_map = (rtx *) xmalloc (maxregnum * sizeof (rtx));
@@ -933,11 +936,25 @@ unroll_loop (loop, insn_count, strength_reduce_p)
a constant.
We must copy the final and initial values here to avoid
- improperly shared rtl. */
-
- diff = expand_simple_binop (mode, MINUS, copy_rtx (final_value),
- copy_rtx (initial_value), NULL_RTX, 0,
- OPTAB_LIB_WIDEN);
+ improperly shared rtl.
+
+ We have to deal with for (i = 0; --i < 6;) type loops.
+ For such loops the real final value is the first time the
+ loop variable overflows, so the diff we calculate is the
+ distance from the overflow value. This is 0 or ~0 for
+ unsigned loops depending on the direction, or INT_MAX,
+ INT_MAX+1 for signed loops. We really do not need the
+ exact value, since we are only interested in the diff
+ modulo the increment, and the increment is a power of 2,
+ so we can pretend that the overflow value is 0/~0. */
+
+ if (cc == NE || less_p != neg_inc)
+ diff = expand_simple_binop (mode, MINUS, copy_rtx (final_value),
+ copy_rtx (initial_value), NULL_RTX, 0,
+ OPTAB_LIB_WIDEN);
+ else
+ diff = expand_simple_unop (mode, neg_inc ? NOT : NEG,
+ copy_rtx (initial_value), NULL_RTX, 0);
/* Now calculate (diff % (unroll * abs (increment))) by using an
and instruction. */
@@ -958,11 +975,17 @@ unroll_loop (loop, insn_count, strength_reduce_p)
case. This check does not apply if the loop has a NE
comparison at the end. */
- if (loop_info->comparison_code != NE)
+ if (cc != NE)
{
- emit_cmp_and_jump_insns (initial_value, final_value,
- neg_inc ? LE : GE,
- NULL_RTX, mode, 0, labels[1]);
+ rtx incremented_initval;
+ incremented_initval = expand_simple_binop (mode, PLUS,
+ initial_value,
+ increment,
+ NULL_RTX, 0,
+ OPTAB_LIB_WIDEN);
+ emit_cmp_and_jump_insns (incremented_initval, final_value,
+ less_p ? GE : LE, NULL_RTX,
+ mode, unsigned_p, labels[1]);
predict_insn_def (get_last_insn (), PRED_LOOP_CONDITION,
NOT_TAKEN);
JUMP_LABEL (get_last_insn ()) = labels[1];