mirror of git://gcc.gnu.org/git/gcc.git
re PR tree-optimization/32044 (final value replacement too aggressive for e.g. targets with no native div/mod insns)
PR tree-optimization/32044 * tree-scalar-evolution.h (expression_expensive_p): Declare. * tree-scalar-evolution.c (expression_expensive_p): New function. (scev_const_prop): Avoid introducing expensive expressions. * tree-ssa-loop-ivopts.c (may_eliminate_iv): Ditto. * gcc.dg/pr34027-1.c: Change outcome. * gcc.dg/tree-ssa/pr32044.c: New test. From-SVN: r142719
This commit is contained in:
parent
9c877fcc00
commit
771f882e18
|
@ -1,3 +1,11 @@
|
||||||
|
2008-12-12 Zdenek Dvorak <ook@ucw.cz>
|
||||||
|
|
||||||
|
PR tree-optimization/32044
|
||||||
|
* tree-scalar-evolution.h (expression_expensive_p): Declare.
|
||||||
|
* tree-scalar-evolution.c (expression_expensive_p): New function.
|
||||||
|
(scev_const_prop): Avoid introducing expensive expressions.
|
||||||
|
* tree-ssa-loop-ivopts.c (may_eliminate_iv): Ditto.
|
||||||
|
|
||||||
2008-12-12 Sebastian Pop <sebastian.pop@amd.com>
|
2008-12-12 Sebastian Pop <sebastian.pop@amd.com>
|
||||||
|
|
||||||
PR middle-end/38409
|
PR middle-end/38409
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
2008-12-12 Zdenek Dvorak <ook@ucw.cz>
|
||||||
|
|
||||||
|
PR tree-optimization/32044
|
||||||
|
* gcc.dg/pr34027-1.c: Change outcome.
|
||||||
|
* gcc.dg/tree-ssa/pr32044.c: New test.
|
||||||
|
|
||||||
2008-12-12 Janis Johnson <janis187@us.ibm.com>
|
2008-12-12 Janis Johnson <janis187@us.ibm.com>
|
||||||
|
|
||||||
PR target/11594
|
PR target/11594
|
||||||
|
|
|
@ -8,5 +8,9 @@ unsigned long foobar(unsigned long ns)
|
||||||
return ns;
|
return ns;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* { dg-final { scan-tree-dump "ns % 10000" "optimized" } } */
|
/* This test was originally introduced to test that we transform
|
||||||
|
to ns % 10000. See the discussion of PR 32044 why we do not do
|
||||||
|
that anymore. */
|
||||||
|
/* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */
|
||||||
|
/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */
|
||||||
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
/* { dg-final { cleanup-tree-dump "optimized" } } */
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
/* { dg-do compile } */
|
||||||
|
/* { dg-options "-O2 -fdump-tree-empty -fdump-tree-final_cleanup" } */
|
||||||
|
|
||||||
|
int foo (int n)
|
||||||
|
{
|
||||||
|
while (n >= 45)
|
||||||
|
n -= 45;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bar (int n)
|
||||||
|
{
|
||||||
|
while (n >= 64)
|
||||||
|
n -= 64;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
int bla (int n)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (n >= 45)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
n -= 45;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int baz (int n)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (n >= 64)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
n -= 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The loops computing division/modulo by 64 should be eliminated. */
|
||||||
|
/* { dg-final { scan-tree-dump-times "Removing empty loop" 2 "empty" } } */
|
||||||
|
|
||||||
|
/* There should be no division/modulo in the final dump (division and modulo
|
||||||
|
by 64 are done using bit operations). */
|
||||||
|
/* { dg-final { scan-tree-dump-times "/" 0 "final_cleanup" } } */
|
||||||
|
/* { dg-final { scan-tree-dump-times "%" 0 "final_cleanup" } } */
|
||||||
|
|
||||||
|
/* { dg-final { cleanup-tree-dump "empty" } } */
|
||||||
|
/* { dg-final { cleanup-tree-dump "final_cleanup" } } */
|
|
@ -2805,6 +2805,50 @@ scev_finalize (void)
|
||||||
scalar_evolution_info = NULL;
|
scalar_evolution_info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Returns true if the expression EXPR is considered to be too expensive
|
||||||
|
for scev_const_prop. */
|
||||||
|
|
||||||
|
bool
|
||||||
|
expression_expensive_p (tree expr)
|
||||||
|
{
|
||||||
|
enum tree_code code;
|
||||||
|
|
||||||
|
if (is_gimple_val (expr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
code = TREE_CODE (expr);
|
||||||
|
if (code == TRUNC_DIV_EXPR
|
||||||
|
|| code == CEIL_DIV_EXPR
|
||||||
|
|| code == FLOOR_DIV_EXPR
|
||||||
|
|| code == ROUND_DIV_EXPR
|
||||||
|
|| code == TRUNC_MOD_EXPR
|
||||||
|
|| code == CEIL_MOD_EXPR
|
||||||
|
|| code == FLOOR_MOD_EXPR
|
||||||
|
|| code == ROUND_MOD_EXPR
|
||||||
|
|| code == EXACT_DIV_EXPR)
|
||||||
|
{
|
||||||
|
/* Division by power of two is usually cheap, so we allow it.
|
||||||
|
Forbid anything else. */
|
||||||
|
if (!integer_pow2p (TREE_OPERAND (expr, 1)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (TREE_CODE_CLASS (code))
|
||||||
|
{
|
||||||
|
case tcc_binary:
|
||||||
|
case tcc_comparison:
|
||||||
|
if (expression_expensive_p (TREE_OPERAND (expr, 1)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
/* Fallthru. */
|
||||||
|
case tcc_unary:
|
||||||
|
return expression_expensive_p (TREE_OPERAND (expr, 0));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Replace ssa names for that scev can prove they are constant by the
|
/* Replace ssa names for that scev can prove they are constant by the
|
||||||
appropriate constants. Also perform final value replacement in loops,
|
appropriate constants. Also perform final value replacement in loops,
|
||||||
in case the replacement expressions are cheap.
|
in case the replacement expressions are cheap.
|
||||||
|
@ -2896,12 +2940,6 @@ scev_const_prop (void)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
niter = number_of_latch_executions (loop);
|
niter = number_of_latch_executions (loop);
|
||||||
/* We used to check here whether the computation of NITER is expensive,
|
|
||||||
and avoided final value elimination if that is the case. The problem
|
|
||||||
is that it is hard to evaluate whether the expression is too
|
|
||||||
expensive, as we do not know what optimization opportunities the
|
|
||||||
elimination of the final value may reveal. Therefore, we now
|
|
||||||
eliminate the final values of induction variables unconditionally. */
|
|
||||||
if (niter == chrec_dont_know)
|
if (niter == chrec_dont_know)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -2938,7 +2976,15 @@ scev_const_prop (void)
|
||||||
/* Moving the computation from the loop may prolong life range
|
/* Moving the computation from the loop may prolong life range
|
||||||
of some ssa names, which may cause problems if they appear
|
of some ssa names, which may cause problems if they appear
|
||||||
on abnormal edges. */
|
on abnormal edges. */
|
||||||
|| contains_abnormal_ssa_name_p (def))
|
|| contains_abnormal_ssa_name_p (def)
|
||||||
|
/* Do not emit expensive expressions. The rationale is that
|
||||||
|
when someone writes a code like
|
||||||
|
|
||||||
|
while (n > 45) n -= 45;
|
||||||
|
|
||||||
|
he probably knows that n is not large, and does not want it
|
||||||
|
to be turned into n %= 45. */
|
||||||
|
|| expression_expensive_p (def))
|
||||||
{
|
{
|
||||||
gsi_next (&psi);
|
gsi_next (&psi);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -35,6 +35,7 @@ extern void gather_stats_on_scev_database (void);
|
||||||
extern void scev_analysis (void);
|
extern void scev_analysis (void);
|
||||||
unsigned int scev_const_prop (void);
|
unsigned int scev_const_prop (void);
|
||||||
|
|
||||||
|
bool expression_expensive_p (tree);
|
||||||
extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool);
|
extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool);
|
||||||
|
|
||||||
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
|
/* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the
|
||||||
|
|
|
@ -3844,7 +3844,12 @@ may_eliminate_iv (struct ivopts_data *data,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
cand_value_at (loop, cand, use->stmt, nit, &bnd);
|
cand_value_at (loop, cand, use->stmt, nit, &bnd);
|
||||||
|
|
||||||
*bound = aff_combination_to_tree (&bnd);
|
*bound = aff_combination_to_tree (&bnd);
|
||||||
|
/* It is unlikely that computing the number of iterations using division
|
||||||
|
would be more profitable than keeping the original induction variable. */
|
||||||
|
if (expression_expensive_p (*bound))
|
||||||
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue