diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr72817.c | 13 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr73450.c | 14 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-niter.c | 51 |
5 files changed, 72 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c380045..99fb2d2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2016-08-16 Bin Cheng <bin.cheng@arm.com> + + 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. + 2016-08-15 Uros Bizjak <ubizjak@gmail.com> PR target/72867 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 810aca1..26266df 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2016-08-16 Bin Cheng <bin.cheng@arm.com> + + PR tree-optimization/72817 + PR tree-optimization/73450 + * gcc.dg/tree-ssa/pr72817.c: New test. + * gcc.dg/tree-ssa/pr73450.c: New test. + 2016-08-15 Fritz Reese <fritzoreese@gmail.com> * gfortran.dg/init_flag_13.f90: New testcase. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr72817.c b/gcc/testsuite/gcc.dg/tree-ssa/pr72817.c new file mode 100644 index 0000000..6ee0b08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr72817.c @@ -0,0 +1,13 @@ +/* { dg-do run } */ +/* { dg-options "-O3" } */ + +char a; +short b; + +int main () +{ + for (a = 3; a != -1; a -= 5) + while (b) + ; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr73450.c b/gcc/testsuite/gcc.dg/tree-ssa/pr73450.c new file mode 100644 index 0000000..7dd44db --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr73450.c @@ -0,0 +1,14 @@ +/* { dg-do run } */ +/* { dg-options "-O3" } */ + +int a; +char b; +int main() { + char c = 0; + for (; c != 3; c = c + 7) { + a = b & a; + if (a) + break; + } + return 0; +} 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); } } } |