re PR tree-optimization/68529 (scev failed for while(i--))
PR tree-optimization/68529 * tree-ssa-loop-niter.c (number_of_iterations_ne): Add new param. Compute no-overflow information for control iv. (number_of_iterations_lt, number_of_iterations_le): Add new param. (number_of_iterations_cond): Pass new argument to above functions. PR tree-optimization/68529 * gcc.dg/tree-ssa/pr68529-1.c: New test. * gcc.dg/tree-ssa/pr68529-2.c: New test. * gcc.dg/tree-ssa/pr68529-3.c: New test. From-SVN: r231097
This commit is contained in:
parent
6ea98dee20
commit
cdf66caf4f
6 changed files with 139 additions and 15 deletions
|
@ -1,3 +1,11 @@
|
|||
2015-12-01 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
PR tree-optimization/68529
|
||||
* tree-ssa-loop-niter.c (number_of_iterations_ne): Add new param.
|
||||
Compute no-overflow information for control iv.
|
||||
(number_of_iterations_lt, number_of_iterations_le): Add new param.
|
||||
(number_of_iterations_cond): Pass new argument to above functions.
|
||||
|
||||
2015-11-30 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* ipa-inline-transform.c (inline_call): Drop -fstrict-aliasing when
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
2015-12-01 Bin Cheng <bin.cheng@arm.com>
|
||||
|
||||
PR tree-optimization/68529
|
||||
* gcc.dg/tree-ssa/pr68529-1.c: New test.
|
||||
* gcc.dg/tree-ssa/pr68529-2.c: New test.
|
||||
* gcc.dg/tree-ssa/pr68529-3.c: New test.
|
||||
|
||||
2015-11-30 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* gcc.dg/lto/alias-1_0.c: New testcase.
|
||||
|
|
20
gcc/testsuite/gcc.dg/tree-ssa/pr68529-1.c
Normal file
20
gcc/testsuite/gcc.dg/tree-ssa/pr68529-1.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-distribution -ftree-loop-distribute-patterns -fdump-tree-ldist-details" } */
|
||||
|
||||
void bar(char *s);
|
||||
int foo()
|
||||
{
|
||||
char c[10000] = {};
|
||||
unsigned short nchar = 9999;
|
||||
|
||||
while(nchar-- != 0)
|
||||
{
|
||||
c[nchar] = 'A';
|
||||
}
|
||||
|
||||
bar (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "distributed: split to 0 loops and 1 library calls" "ldist" } } */
|
||||
/* { dg-final { scan-tree-dump "generated memset" "ldist" } } */
|
23
gcc/testsuite/gcc.dg/tree-ssa/pr68529-2.c
Normal file
23
gcc/testsuite/gcc.dg/tree-ssa/pr68529-2.c
Normal file
|
@ -0,0 +1,23 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-distribution -ftree-loop-distribute-patterns -fdump-tree-ldist-details" } */
|
||||
|
||||
void bar(char *s);
|
||||
int foo(unsigned short l)
|
||||
{
|
||||
char c[10000] = {};
|
||||
unsigned short nchar = 9999;
|
||||
|
||||
if (nchar <= l)
|
||||
return -1;
|
||||
|
||||
while(nchar-- != l)
|
||||
{
|
||||
c[nchar] = 'A';
|
||||
}
|
||||
|
||||
bar (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "distributed: split to 0 loops and 1 library calls" "ldist" } } */
|
||||
/* { dg-final { scan-tree-dump "generated memset" "ldist" } } */
|
47
gcc/testsuite/gcc.dg/tree-ssa/pr68529-3.c
Normal file
47
gcc/testsuite/gcc.dg/tree-ssa/pr68529-3.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -ftree-loop-distribution -ftree-loop-distribute-patterns -fdump-tree-ldist-details" } */
|
||||
|
||||
void bar(char *s);
|
||||
int foo1(unsigned short l)
|
||||
{
|
||||
char c[10000] = {};
|
||||
unsigned short nchar = 9999;
|
||||
|
||||
while(nchar-- != l)
|
||||
{
|
||||
c[nchar] = 'A';
|
||||
}
|
||||
|
||||
bar (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int foo2()
|
||||
{
|
||||
char c[100000] = {};
|
||||
unsigned short nchar;
|
||||
|
||||
for (nchar = 0; nchar != 1000; --nchar)
|
||||
{
|
||||
c[nchar] = 'A';
|
||||
}
|
||||
|
||||
bar (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int foo3()
|
||||
{
|
||||
char c[100000] = {};
|
||||
unsigned short nchar;
|
||||
|
||||
for (nchar = 0; nchar != 1000; nchar += 3)
|
||||
{
|
||||
c[nchar] = 'A';
|
||||
}
|
||||
|
||||
bar (c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "failed: evolution of offset is not affine" 3 "ldist" } } */
|
|
@ -957,13 +957,14 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
|
|||
bounds on the difference FINAL - IV->base. */
|
||||
|
||||
static bool
|
||||
number_of_iterations_ne (tree type, affine_iv *iv, tree final,
|
||||
struct tree_niter_desc *niter, bool exit_must_be_taken,
|
||||
bounds *bnds)
|
||||
number_of_iterations_ne (struct loop *loop, tree type, affine_iv *iv,
|
||||
tree final, struct tree_niter_desc *niter,
|
||||
bool exit_must_be_taken, bounds *bnds)
|
||||
{
|
||||
tree niter_type = unsigned_type_for (type);
|
||||
tree s, c, d, bits, assumption, tmp, bound;
|
||||
mpz_t max;
|
||||
tree e;
|
||||
|
||||
niter->control = *iv;
|
||||
niter->bound = final;
|
||||
|
@ -998,6 +999,23 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
|
|||
TYPE_SIGN (niter_type));
|
||||
mpz_clear (max);
|
||||
|
||||
/* Compute no-overflow information for the control iv. Note we are
|
||||
handling NE_EXPR, if iv base equals to final value, the loop exits
|
||||
immediately, and the iv does not overflow. */
|
||||
if (tree_int_cst_sign_bit (iv->step))
|
||||
e = fold_build2 (GE_EXPR, boolean_type_node, iv->base, final);
|
||||
else
|
||||
e = fold_build2 (LE_EXPR, boolean_type_node, iv->base, final);
|
||||
e = simplify_using_initial_conditions (loop, e);
|
||||
if (integer_onep (e)
|
||||
&& (integer_onep (s)
|
||||
|| (TREE_CODE (c) == INTEGER_CST
|
||||
&& TREE_CODE (s) == INTEGER_CST
|
||||
&& wi::mod_trunc (c, s, TYPE_SIGN (type)) == 0)))
|
||||
{
|
||||
niter->control.no_overflow = true;
|
||||
}
|
||||
|
||||
/* First the trivial cases -- when the step is 1. */
|
||||
if (integer_onep (s))
|
||||
{
|
||||
|
@ -1361,8 +1379,8 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
that the exit must be taken eventually. */
|
||||
|
||||
static bool
|
||||
number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
||||
struct tree_niter_desc *niter,
|
||||
number_of_iterations_lt (struct loop *loop, tree type, affine_iv *iv0,
|
||||
affine_iv *iv1, struct tree_niter_desc *niter,
|
||||
bool exit_must_be_taken, bounds *bnds)
|
||||
{
|
||||
tree niter_type = unsigned_type_for (type);
|
||||
|
@ -1434,7 +1452,8 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
zps does not overflow. */
|
||||
zps.no_overflow = true;
|
||||
|
||||
return number_of_iterations_ne (type, &zps, delta, niter, true, bnds);
|
||||
return number_of_iterations_ne (loop, type, &zps,
|
||||
delta, niter, true, bnds);
|
||||
}
|
||||
|
||||
/* Make sure that the control iv does not overflow. */
|
||||
|
@ -1473,9 +1492,9 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
is the case). BNDS bounds the difference IV1->base - IV0->base. */
|
||||
|
||||
static bool
|
||||
number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
|
||||
struct tree_niter_desc *niter, bool exit_must_be_taken,
|
||||
bounds *bnds)
|
||||
number_of_iterations_le (struct loop *loop, tree type, affine_iv *iv0,
|
||||
affine_iv *iv1, struct tree_niter_desc *niter,
|
||||
bool exit_must_be_taken, bounds *bnds)
|
||||
{
|
||||
tree assumption;
|
||||
tree type1 = type;
|
||||
|
@ -1523,7 +1542,7 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
|
|||
|
||||
bounds_add (bnds, 1, type1);
|
||||
|
||||
return number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
|
||||
return number_of_iterations_lt (loop, type, iv0, iv1, niter, exit_must_be_taken,
|
||||
bnds);
|
||||
}
|
||||
|
||||
|
@ -1698,18 +1717,18 @@ number_of_iterations_cond (struct loop *loop,
|
|||
{
|
||||
case NE_EXPR:
|
||||
gcc_assert (integer_zerop (iv1->step));
|
||||
ret = number_of_iterations_ne (type, iv0, iv1->base, niter,
|
||||
ret = number_of_iterations_ne (loop, type, iv0, iv1->base, niter,
|
||||
exit_must_be_taken, &bnds);
|
||||
break;
|
||||
|
||||
case LT_EXPR:
|
||||
ret = number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
|
||||
&bnds);
|
||||
ret = number_of_iterations_lt (loop, type, iv0, iv1, niter,
|
||||
exit_must_be_taken, &bnds);
|
||||
break;
|
||||
|
||||
case LE_EXPR:
|
||||
ret = number_of_iterations_le (type, iv0, iv1, niter, exit_must_be_taken,
|
||||
&bnds);
|
||||
ret = number_of_iterations_le (loop, type, iv0, iv1, niter,
|
||||
exit_must_be_taken, &bnds);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
Loading…
Add table
Reference in a new issue