summaryrefslogtreecommitdiffstats
path: root/toolchain/gcc/4.3.1/901-backport-fix-for-bug-32044.patch
blob: 9337bf9eed11e8c8642df2ec48da4cd92219e28f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
Index: gcc-4.3.2/gcc/tree-scalar-evolution.c
===================================================================
--- gcc-4.3.2.orig/gcc/tree-scalar-evolution.c	2009-01-28 10:14:37.000000000 +0100
+++ gcc-4.3.2/gcc/tree-scalar-evolution.c	2009-01-28 10:17:50.000000000 +0100
@@ -2716,6 +2716,50 @@
   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.
@@ -2802,12 +2846,6 @@
 	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
-	 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;
 
@@ -2838,7 +2876,15 @@
 	      /* 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))
 	    continue;
 
 	  /* Eliminate the PHI node and replace it by a computation outside
Index: gcc-4.3.2/gcc/tree-scalar-evolution.h
===================================================================
--- gcc-4.3.2.orig/gcc/tree-scalar-evolution.h	2009-01-28 10:22:47.000000000 +0100
+++ gcc-4.3.2/gcc/tree-scalar-evolution.h	2009-01-28 10:23:10.000000000 +0100
@@ -35,6 +35,7 @@
 extern void scev_analysis (void);
 unsigned int scev_const_prop (void);
 
+bool expression_expensive_p (tree);
 extern bool simple_iv (struct loop *, tree, tree, affine_iv *, bool);
 
 /* Returns the loop of the polynomial chrec CHREC.  */
Index: gcc-4.3.2/gcc/testsuite/gcc.dg/pr34027-1.c
===================================================================
--- gcc-4.3.2.orig/gcc/testsuite/gcc.dg/pr34027-1.c	2009-01-28 10:24:09.000000000 +0100
+++ gcc-4.3.2/gcc/testsuite/gcc.dg/pr34027-1.c	2009-01-28 10:24:43.000000000 +0100
@@ -8,5 +8,9 @@
   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" } } */
Index: gcc-4.3.2/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gcc-4.3.2/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c	2009-01-28 10:25:50.000000000 +0100
@@ -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" } } */
Index: gcc-4.3.2/gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc-4.3.2.orig/gcc/tree-ssa-loop-ivopts.c	2009-01-28 10:26:04.000000000 +0100
+++ gcc-4.3.2/gcc/tree-ssa-loop-ivopts.c	2009-01-28 10:27:09.000000000 +0100
@@ -3778,7 +3778,12 @@
     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;
 }