diff options
author | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-12-12 20:32:47 +0000 |
---|---|---|
committer | rakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-12-12 20:32:47 +0000 |
commit | 590f8b68be58b7480fc9bebb4581cf6ee9f342b9 (patch) | |
tree | d2bf855f278b353dce85dfa95de900d9e0e0ca37 /gcc | |
parent | 5c397e0450ef11297d3e4d0e83631f9f6a5ddfd1 (diff) | |
download | gcc-590f8b68be58b7480fc9bebb4581cf6ee9f342b9.tar.gz |
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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142719 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr34027-1.c | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/pr32044.c | 55 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.c | 60 | ||||
-rw-r--r-- | gcc/tree-scalar-evolution.h | 1 | ||||
-rw-r--r-- | gcc/tree-ssa-loop-ivopts.c | 5 |
7 files changed, 133 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9bedbaf6049..8fdd1627582 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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> PR middle-end/38409 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ad5bc361c16..895c3561a27 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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> PR target/11594 diff --git a/gcc/testsuite/gcc.dg/pr34027-1.c b/gcc/testsuite/gcc.dg/pr34027-1.c index 532e4976dc3..8e8872a5133 100644 --- a/gcc/testsuite/gcc.dg/pr34027-1.c +++ b/gcc/testsuite/gcc.dg/pr34027-1.c @@ -8,5 +8,9 @@ unsigned long foobar(unsigned long 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" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c new file mode 100644 index 00000000000..0c1a58206f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c @@ -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" } } */ diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c index e3d60e98b2e..f306ab8277c 100644 --- a/gcc/tree-scalar-evolution.c +++ b/gcc/tree-scalar-evolution.c @@ -2805,6 +2805,50 @@ scev_finalize (void) 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 appropriate constants. Also perform final value replacement in loops, in case the replacement expressions are cheap. @@ -2896,12 +2940,6 @@ scev_const_prop (void) continue; 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) continue; @@ -2938,7 +2976,15 @@ scev_const_prop (void) /* Moving the computation from the loop may prolong life range of some ssa names, which may cause problems if they appear 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); continue; diff --git a/gcc/tree-scalar-evolution.h b/gcc/tree-scalar-evolution.h index 7ba0708354f..0aa8837cbbc 100644 --- a/gcc/tree-scalar-evolution.h +++ b/gcc/tree-scalar-evolution.h @@ -35,6 +35,7 @@ extern void gather_stats_on_scev_database (void); extern void scev_analysis (void); unsigned int scev_const_prop (void); +bool expression_expensive_p (tree); extern bool simple_iv (struct loop *, gimple, tree, affine_iv *, bool); /* Returns the basic block preceding LOOP or ENTRY_BLOCK_PTR when the diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c index 683d7d4b5fa..2d36becf5ec 100644 --- a/gcc/tree-ssa-loop-ivopts.c +++ b/gcc/tree-ssa-loop-ivopts.c @@ -3844,7 +3844,12 @@ may_eliminate_iv (struct ivopts_data *data, return false; cand_value_at (loop, cand, use->stmt, nit, &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; } |