diff options
author | Bin Cheng <bin.cheng@arm.com> | 2016-08-16 09:13:50 +0000 |
---|---|---|
committer | Bin Cheng <amker@gcc.gnu.org> | 2016-08-16 09:13:50 +0000 |
commit | 8f21990a676b65040761886e54fc9d5149ec014c (patch) | |
tree | 8a0e3d884dc48aba31f839c3b7d5ab8a28c04e5c /gcc/tree-ssa-loop-niter.c | |
parent | f6ba953d245fe7f6a39eedc94c97ae7c2c7ffe13 (diff) | |
download | gcc-8f21990a676b65040761886e54fc9d5149ec014c.zip gcc-8f21990a676b65040761886e54fc9d5149ec014c.tar.gz gcc-8f21990a676b65040761886e54fc9d5149ec014c.tar.bz2 |
re PR tree-optimization/72817 (wrong code at -O3 on x86_64-linux-gnu (in both 32-bit and 64-bit modes))
PR tree-optimization/72817
PR tree-optimization/73450
* tree-ssa-loop-niter.c (number_of_iterations_ne): Check
multiple_of_p for adjusted IV.base.
gcc/testsuite
* gcc.dg/tree-ssa/pr72817.c: New test.
* gcc.dg/tree-ssa/pr73450.c: New test.
From-SVN: r239494
Diffstat (limited to 'gcc/tree-ssa-loop-niter.c')
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 51 |
1 files changed, 31 insertions, 20 deletions
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c index a50d2b4..5041c83 100644 --- a/gcc/tree-ssa-loop-niter.c +++ b/gcc/tree-ssa-loop-niter.c @@ -999,33 +999,36 @@ number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv, mpz_clear (max); /* Compute no-overflow information for the control iv. This can be - proven when below two conditions hold. - - 1) |FINAL - base| is an exact multiple of step. - 2) IV evaluates toward FINAL at beginning, i.e: + proven when below two conditions are satisfied: + 1) IV evaluates toward FINAL at beginning, i.e: base <= FINAL ; step > 0 base >= FINAL ; step < 0 - Note the first condition holds, the second can be then relaxed - to below condition. + 2) |FINAL - base| is an exact multiple of step. + + Unfortunately, it's hard to prove above conditions after pass loop-ch + because loop with exit condition (IV != FINAL) usually will be guarded + by initial-condition (IV.base - IV.step != FINAL). In this case, we + can alternatively try to prove below conditions: + + 1') IV evaluates toward FINAL at beginning, i.e: + new_base = base - step < FINAL ; step > 0 + && base - step doesn't underflow + new_base = base - step > FINAL ; step < 0 + && base - step doesn't overflow - base - step < FINAL ; step > 0 - && base - step doesn't underflow - base - step > FINAL ; step < 0 - && base - step doesn't overflow + 2') |FINAL - new_base| is an exact multiple of step. - The relaxation is important because after pass loop-ch, loop - with exit condition (IV != FINAL) will usually be guarded by - pre-condition (IV.base - IV.step != FINAL). Please refer to - PR34114 as an example. + Please refer to PR34114 as an example of loop-ch's impact, also refer + to PR72817 as an example why condition 2') is necessary. - Also note, for NE_EXPR, base equals to FINAL is a special case, in + Note, for NE_EXPR, base equals to FINAL is a special case, in which the loop exits immediately, and the iv does not overflow. */ if (!niter->control.no_overflow && (integer_onep (s) || multiple_of_p (type, c, s))) { - tree t, cond, relaxed_cond = boolean_false_node; + tree t, cond, new_c, relaxed_cond = boolean_false_node; if (tree_int_cst_sign_bit (iv->step)) { @@ -1039,8 +1042,12 @@ number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv, if (integer_nonzerop (t)) { t = fold_build2 (MINUS_EXPR, type, iv->base, iv->step); - relaxed_cond = fold_build2 (GT_EXPR, boolean_type_node, - t, final); + new_c = fold_build2 (MINUS_EXPR, niter_type, + fold_convert (niter_type, t), + fold_convert (niter_type, final)); + if (multiple_of_p (type, new_c, s)) + relaxed_cond = fold_build2 (GT_EXPR, boolean_type_node, + t, final); } } } @@ -1056,8 +1063,12 @@ number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv, if (integer_nonzerop (t)) { t = fold_build2 (MINUS_EXPR, type, iv->base, iv->step); - relaxed_cond = fold_build2 (LT_EXPR, boolean_type_node, - t, final); + new_c = fold_build2 (MINUS_EXPR, niter_type, + fold_convert (niter_type, final), + fold_convert (niter_type, t)); + if (multiple_of_p (type, new_c, s)) + relaxed_cond = fold_build2 (LT_EXPR, boolean_type_node, + t, final); } } } |