summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-12 20:32:47 +0000
committerrakdver <rakdver@138bc75d-0d04-0410-961f-82ee72b054a4>2008-12-12 20:32:47 +0000
commit590f8b68be58b7480fc9bebb4581cf6ee9f342b9 (patch)
treed2bf855f278b353dce85dfa95de900d9e0e0ca37 /gcc
parent5c397e0450ef11297d3e4d0e83631f9f6a5ddfd1 (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/pr34027-1.c6
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr32044.c55
-rw-r--r--gcc/tree-scalar-evolution.c60
-rw-r--r--gcc/tree-scalar-evolution.h1
-rw-r--r--gcc/tree-ssa-loop-ivopts.c5
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;
}