loop-iv.c (implies_p): Detect additional cases where A implies B.

* loop-iv.c (implies_p): Detect additional cases where A implies B.
	(determine_max_iter): Take additional LOOP arg; all callers changed.
	Lose broken logic dealing with PLUS.  Try to limit the upper bound by
	one using simplifications.

From-SVN: r122288
This commit is contained in:
Bernd Schmidt 2007-02-24 13:40:54 +00:00 committed by Bernd Schmidt
parent e7d406d539
commit 606830199c
2 changed files with 112 additions and 39 deletions

View File

@ -1,3 +1,10 @@
2007-02-24 Bernd Schmidt <bernd.schmidt@analog.com>
* loop-iv.c (implies_p): Detect additional cases where A implies B.
(determine_max_iter): Take additional LOOP arg; all callers changed.
Lose broken logic dealing with PLUS. Try to limit the upper bound by
one using simplifications.
2007-02-23 DJ Delorie <dj@redhat.com>
* doc/tm.h (BIGGEST_ALIGNMENT): Clarify the purpose of this macro.

View File

@ -1392,14 +1392,34 @@ implies_p (rtx a, rtx b)
}
}
if (b == const_true_rtx)
return true;
if ((GET_RTX_CLASS (GET_CODE (a)) != RTX_COMM_COMPARE
&& GET_RTX_CLASS (GET_CODE (a)) != RTX_COMPARE)
|| (GET_RTX_CLASS (GET_CODE (b)) != RTX_COMM_COMPARE
&& GET_RTX_CLASS (GET_CODE (b)) != RTX_COMPARE))
return false;
op0 = XEXP (a, 0);
op1 = XEXP (a, 1);
opb0 = XEXP (b, 0);
opb1 = XEXP (b, 1);
mode = GET_MODE (op0);
if (mode != GET_MODE (opb0))
mode = VOIDmode;
else if (mode == VOIDmode)
{
mode = GET_MODE (op1);
if (mode != GET_MODE (opb1))
mode = VOIDmode;
}
/* A < B implies A + 1 <= B. */
if ((GET_CODE (a) == GT || GET_CODE (a) == LT)
&& (GET_CODE (b) == GE || GET_CODE (b) == LE))
{
op0 = XEXP (a, 0);
op1 = XEXP (a, 1);
opb0 = XEXP (b, 0);
opb1 = XEXP (b, 1);
if (GET_CODE (a) == GT)
{
@ -1415,22 +1435,82 @@ implies_p (rtx a, rtx b)
opb1 = r;
}
mode = GET_MODE (op0);
if (mode != GET_MODE (opb0))
mode = VOIDmode;
else if (mode == VOIDmode)
{
mode = GET_MODE (op1);
if (mode != GET_MODE (opb1))
mode = VOIDmode;
}
if (SCALAR_INT_MODE_P (mode)
&& rtx_equal_p (op1, opb1)
&& simplify_gen_binary (MINUS, mode, opb0, op0) == const1_rtx)
return true;
return false;
}
/* A < B or A > B imply A != B. TODO: Likewise
A + n < B implies A != B + n if neither wraps. */
if (GET_CODE (b) == NE
&& (GET_CODE (a) == GT || GET_CODE (a) == GTU
|| GET_CODE (a) == LT || GET_CODE (a) == LTU))
{
if (rtx_equal_p (op0, opb0)
&& rtx_equal_p (op1, opb1))
return true;
}
/* For unsigned comparisons, A != 0 implies A > 0 and A >= 1. */
if (GET_CODE (a) == NE
&& op1 == const0_rtx)
{
if ((GET_CODE (b) == GTU
&& opb1 == const0_rtx)
|| (GET_CODE (b) == GEU
&& opb1 == const1_rtx))
return rtx_equal_p (op0, opb0);
}
/* A != N is equivalent to A - (N + 1) <u -1. */
if (GET_CODE (a) == NE
&& GET_CODE (op1) == CONST_INT
&& GET_CODE (b) == LTU
&& opb1 == constm1_rtx
&& GET_CODE (opb0) == PLUS
&& GET_CODE (XEXP (opb0, 1)) == CONST_INT
/* Avoid overflows. */
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
!= ((unsigned HOST_WIDE_INT)1
<< (HOST_BITS_PER_WIDE_INT - 1)) - 1)
&& INTVAL (XEXP (opb0, 1)) + 1 == -INTVAL (op1))
return rtx_equal_p (op0, XEXP (opb0, 0));
/* Likewise, A != N implies A - N > 0. */
if (GET_CODE (a) == NE
&& GET_CODE (op1) == CONST_INT)
{
if (GET_CODE (b) == GTU
&& GET_CODE (opb0) == PLUS
&& opb1 == const0_rtx
&& GET_CODE (XEXP (opb0, 1)) == CONST_INT
/* Avoid overflows. */
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
!= ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)))
&& rtx_equal_p (XEXP (opb0, 0), op0))
return INTVAL (op1) == -INTVAL (XEXP (opb0, 1));
if (GET_CODE (b) == GEU
&& GET_CODE (opb0) == PLUS
&& opb1 == const1_rtx
&& GET_CODE (XEXP (opb0, 1)) == CONST_INT
/* Avoid overflows. */
&& ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
!= ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)))
&& rtx_equal_p (XEXP (opb0, 0), op0))
return INTVAL (op1) == -INTVAL (XEXP (opb0, 1));
}
/* A >s X, where X is positive, implies A <u Y, if Y is negative. */
if ((GET_CODE (a) == GT || GET_CODE (a) == GE)
&& GET_CODE (op1) == CONST_INT
&& ((GET_CODE (a) == GT && op1 == constm1_rtx)
|| INTVAL (op1) >= 0)
&& GET_CODE (b) == LTU
&& GET_CODE (opb1) == CONST_INT)
return INTVAL (opb1) < 0;
return false;
}
@ -1919,10 +1999,10 @@ canonicalize_iv_subregs (struct rtx_iv *iv0, struct rtx_iv *iv1,
/* Tries to estimate the maximum number of iterations. */
static unsigned HOST_WIDEST_INT
determine_max_iter (struct niter_desc *desc)
determine_max_iter (struct loop *loop, struct niter_desc *desc)
{
rtx niter = desc->niter_expr;
rtx mmin, mmax, left, right;
rtx mmin, mmax, cmp;
unsigned HOST_WIDEST_INT nmax, inc;
if (GET_CODE (niter) == AND
@ -1952,31 +2032,17 @@ determine_max_iter (struct niter_desc *desc)
else
inc = 1;
if (GET_CODE (niter) == PLUS)
/* We could use a binary search here, but for now improving the upper
bound by just one eliminates one important corner case. */
cmp = gen_rtx_fmt_ee (desc->signed_p ? LT : LTU, VOIDmode, niter, mmax);
simplify_using_initial_values (loop, UNKNOWN, &cmp);
if (cmp == const_true_rtx)
{
left = XEXP (niter, 0);
right = XEXP (niter, 0);
nmax--;
if (GET_CODE (right) == CONST_INT)
right = GEN_INT (-INTVAL (right));
if (dump_file)
fprintf (dump_file, ";; improved upper bound by one.\n");
}
else if (GET_CODE (niter) == MINUS)
{
left = XEXP (niter, 0);
right = XEXP (niter, 0);
}
else
{
left = niter;
right = mmin;
}
if (GET_CODE (left) == CONST_INT)
mmax = left;
if (GET_CODE (right) == CONST_INT)
mmin = right;
nmax = INTVAL (mmax) - INTVAL (mmin);
desc->niter_max = nmax / inc;
return nmax / inc;
}
@ -2499,7 +2565,7 @@ iv_number_of_iterations (struct loop *loop, rtx insn, rtx condition,
else
{
if (!desc->niter_max)
desc->niter_max = determine_max_iter (desc);
desc->niter_max = determine_max_iter (loop, desc);
/* simplify_using_initial_values does a copy propagation on the registers
in the expression for the number of iterations. This prolongs life