diff options
author | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-24 13:40:54 +0000 |
---|---|---|
committer | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-02-24 13:40:54 +0000 |
commit | 731d95c8a2990fa936e3c6dd5be7acedfffe9cad (patch) | |
tree | 67928433b94e9ad8469534989cfdcbab20edfa74 /gcc/loop-iv.c | |
parent | d11c218949676961e1826706e25a709db31cd308 (diff) | |
download | gcc-731d95c8a2990fa936e3c6dd5be7acedfffe9cad.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122288 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/loop-iv.c')
-rw-r--r-- | gcc/loop-iv.c | 144 |
1 files changed, 105 insertions, 39 deletions
diff --git a/gcc/loop-iv.c b/gcc/loop-iv.c index 58108d2d2fe..fb0ec4525cc 100644 --- a/gcc/loop-iv.c +++ b/gcc/loop-iv.c @@ -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)); - } - else if (GET_CODE (niter) == MINUS) - { - left = XEXP (niter, 0); - right = XEXP (niter, 0); - } - else - { - left = niter; - right = mmin; + if (dump_file) + fprintf (dump_file, ";; improved upper bound by one.\n"); } - - 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 |