annotate gcc/gimple-ssa-strength-reduction.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Straight-line strength reduction.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2 Copyright (C) 2012-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Bill Schmidt, IBM <wschmidt@linux.ibm.com>
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 /* There are many algorithms for performing strength reduction on
kono
parents:
diff changeset
22 loops. This is not one of them. IVOPTS handles strength reduction
kono
parents:
diff changeset
23 of induction variables just fine. This pass is intended to pick
kono
parents:
diff changeset
24 up the crumbs it leaves behind, by considering opportunities for
kono
parents:
diff changeset
25 strength reduction along dominator paths.
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 Strength reduction addresses explicit multiplies, and certain
kono
parents:
diff changeset
28 multiplies implicit in addressing expressions. It would also be
kono
parents:
diff changeset
29 possible to apply strength reduction to divisions and modulos,
kono
parents:
diff changeset
30 but such opportunities are relatively uncommon.
kono
parents:
diff changeset
31
kono
parents:
diff changeset
32 Strength reduction is also currently restricted to integer operations.
kono
parents:
diff changeset
33 If desired, it could be extended to floating-point operations under
kono
parents:
diff changeset
34 control of something like -funsafe-math-optimizations. */
kono
parents:
diff changeset
35
kono
parents:
diff changeset
36 #include "config.h"
kono
parents:
diff changeset
37 #include "system.h"
kono
parents:
diff changeset
38 #include "coretypes.h"
kono
parents:
diff changeset
39 #include "backend.h"
kono
parents:
diff changeset
40 #include "rtl.h"
kono
parents:
diff changeset
41 #include "tree.h"
kono
parents:
diff changeset
42 #include "gimple.h"
kono
parents:
diff changeset
43 #include "cfghooks.h"
kono
parents:
diff changeset
44 #include "tree-pass.h"
kono
parents:
diff changeset
45 #include "ssa.h"
kono
parents:
diff changeset
46 #include "expmed.h"
kono
parents:
diff changeset
47 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
48 #include "fold-const.h"
kono
parents:
diff changeset
49 #include "gimple-iterator.h"
kono
parents:
diff changeset
50 #include "gimplify-me.h"
kono
parents:
diff changeset
51 #include "stor-layout.h"
kono
parents:
diff changeset
52 #include "cfgloop.h"
kono
parents:
diff changeset
53 #include "tree-cfg.h"
kono
parents:
diff changeset
54 #include "domwalk.h"
kono
parents:
diff changeset
55 #include "tree-ssa-address.h"
kono
parents:
diff changeset
56 #include "tree-affine.h"
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
57 #include "tree-eh.h"
111
kono
parents:
diff changeset
58 #include "builtins.h"
kono
parents:
diff changeset
59
kono
parents:
diff changeset
60 /* Information about a strength reduction candidate. Each statement
kono
parents:
diff changeset
61 in the candidate table represents an expression of one of the
kono
parents:
diff changeset
62 following forms (the special case of CAND_REF will be described
kono
parents:
diff changeset
63 later):
kono
parents:
diff changeset
64
kono
parents:
diff changeset
65 (CAND_MULT) S1: X = (B + i) * S
kono
parents:
diff changeset
66 (CAND_ADD) S1: X = B + (i * S)
kono
parents:
diff changeset
67
kono
parents:
diff changeset
68 Here X and B are SSA names, i is an integer constant, and S is
kono
parents:
diff changeset
69 either an SSA name or a constant. We call B the "base," i the
kono
parents:
diff changeset
70 "index", and S the "stride."
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 Any statement S0 that dominates S1 and is of the form:
kono
parents:
diff changeset
73
kono
parents:
diff changeset
74 (CAND_MULT) S0: Y = (B + i') * S
kono
parents:
diff changeset
75 (CAND_ADD) S0: Y = B + (i' * S)
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 is called a "basis" for S1. In both cases, S1 may be replaced by
kono
parents:
diff changeset
78
kono
parents:
diff changeset
79 S1': X = Y + (i - i') * S,
kono
parents:
diff changeset
80
kono
parents:
diff changeset
81 where (i - i') * S is folded to the extent possible.
kono
parents:
diff changeset
82
kono
parents:
diff changeset
83 All gimple statements are visited in dominator order, and each
kono
parents:
diff changeset
84 statement that may contribute to one of the forms of S1 above is
kono
parents:
diff changeset
85 given at least one entry in the candidate table. Such statements
kono
parents:
diff changeset
86 include addition, pointer addition, subtraction, multiplication,
kono
parents:
diff changeset
87 negation, copies, and nontrivial type casts. If a statement may
kono
parents:
diff changeset
88 represent more than one expression of the forms of S1 above,
kono
parents:
diff changeset
89 multiple "interpretations" are stored in the table and chained
kono
parents:
diff changeset
90 together. Examples:
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 * An add of two SSA names may treat either operand as the base.
kono
parents:
diff changeset
93 * A multiply of two SSA names, likewise.
kono
parents:
diff changeset
94 * A copy or cast may be thought of as either a CAND_MULT with
kono
parents:
diff changeset
95 i = 0 and S = 1, or as a CAND_ADD with i = 0 or S = 0.
kono
parents:
diff changeset
96
kono
parents:
diff changeset
97 Candidate records are allocated from an obstack. They are addressed
kono
parents:
diff changeset
98 both from a hash table keyed on S1, and from a vector of candidate
kono
parents:
diff changeset
99 pointers arranged in predominator order.
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 Opportunity note
kono
parents:
diff changeset
102 ----------------
kono
parents:
diff changeset
103 Currently we don't recognize:
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 S0: Y = (S * i') - B
kono
parents:
diff changeset
106 S1: X = (S * i) - B
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 as a strength reduction opportunity, even though this S1 would
kono
parents:
diff changeset
109 also be replaceable by the S1' above. This can be added if it
kono
parents:
diff changeset
110 comes up in practice.
kono
parents:
diff changeset
111
kono
parents:
diff changeset
112 Strength reduction in addressing
kono
parents:
diff changeset
113 --------------------------------
kono
parents:
diff changeset
114 There is another kind of candidate known as CAND_REF. A CAND_REF
kono
parents:
diff changeset
115 describes a statement containing a memory reference having
kono
parents:
diff changeset
116 complex addressing that might benefit from strength reduction.
kono
parents:
diff changeset
117 Specifically, we are interested in references for which
kono
parents:
diff changeset
118 get_inner_reference returns a base address, offset, and bitpos as
kono
parents:
diff changeset
119 follows:
kono
parents:
diff changeset
120
kono
parents:
diff changeset
121 base: MEM_REF (T1, C1)
kono
parents:
diff changeset
122 offset: MULT_EXPR (PLUS_EXPR (T2, C2), C3)
kono
parents:
diff changeset
123 bitpos: C4 * BITS_PER_UNIT
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 Here T1 and T2 are arbitrary trees, and C1, C2, C3, C4 are
kono
parents:
diff changeset
126 arbitrary integer constants. Note that C2 may be zero, in which
kono
parents:
diff changeset
127 case the offset will be MULT_EXPR (T2, C3).
kono
parents:
diff changeset
128
kono
parents:
diff changeset
129 When this pattern is recognized, the original memory reference
kono
parents:
diff changeset
130 can be replaced with:
kono
parents:
diff changeset
131
kono
parents:
diff changeset
132 MEM_REF (POINTER_PLUS_EXPR (T1, MULT_EXPR (T2, C3)),
kono
parents:
diff changeset
133 C1 + (C2 * C3) + C4)
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 which distributes the multiply to allow constant folding. When
kono
parents:
diff changeset
136 two or more addressing expressions can be represented by MEM_REFs
kono
parents:
diff changeset
137 of this form, differing only in the constants C1, C2, and C4,
kono
parents:
diff changeset
138 making this substitution produces more efficient addressing during
kono
parents:
diff changeset
139 the RTL phases. When there are not at least two expressions with
kono
parents:
diff changeset
140 the same values of T1, T2, and C3, there is nothing to be gained
kono
parents:
diff changeset
141 by the replacement.
kono
parents:
diff changeset
142
kono
parents:
diff changeset
143 Strength reduction of CAND_REFs uses the same infrastructure as
kono
parents:
diff changeset
144 that used by CAND_MULTs and CAND_ADDs. We record T1 in the base (B)
kono
parents:
diff changeset
145 field, MULT_EXPR (T2, C3) in the stride (S) field, and
kono
parents:
diff changeset
146 C1 + (C2 * C3) + C4 in the index (i) field. A basis for a CAND_REF
kono
parents:
diff changeset
147 is thus another CAND_REF with the same B and S values. When at
kono
parents:
diff changeset
148 least two CAND_REFs are chained together using the basis relation,
kono
parents:
diff changeset
149 each of them is replaced as above, resulting in improved code
kono
parents:
diff changeset
150 generation for addressing.
kono
parents:
diff changeset
151
kono
parents:
diff changeset
152 Conditional candidates
kono
parents:
diff changeset
153 ======================
kono
parents:
diff changeset
154
kono
parents:
diff changeset
155 Conditional candidates are best illustrated with an example.
kono
parents:
diff changeset
156 Consider the code sequence:
kono
parents:
diff changeset
157
kono
parents:
diff changeset
158 (1) x_0 = ...;
kono
parents:
diff changeset
159 (2) a_0 = x_0 * 5; MULT (B: x_0; i: 0; S: 5)
kono
parents:
diff changeset
160 if (...)
kono
parents:
diff changeset
161 (3) x_1 = x_0 + 1; ADD (B: x_0, i: 1; S: 1)
kono
parents:
diff changeset
162 (4) x_2 = PHI <x_0, x_1>; PHI (B: x_0, i: 0, S: 1)
kono
parents:
diff changeset
163 (5) x_3 = x_2 + 1; ADD (B: x_2, i: 1, S: 1)
kono
parents:
diff changeset
164 (6) a_1 = x_3 * 5; MULT (B: x_2, i: 1; S: 5)
kono
parents:
diff changeset
165
kono
parents:
diff changeset
166 Here strength reduction is complicated by the uncertain value of x_2.
kono
parents:
diff changeset
167 A legitimate transformation is:
kono
parents:
diff changeset
168
kono
parents:
diff changeset
169 (1) x_0 = ...;
kono
parents:
diff changeset
170 (2) a_0 = x_0 * 5;
kono
parents:
diff changeset
171 if (...)
kono
parents:
diff changeset
172 {
kono
parents:
diff changeset
173 (3) [x_1 = x_0 + 1;]
kono
parents:
diff changeset
174 (3a) t_1 = a_0 + 5;
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176 (4) [x_2 = PHI <x_0, x_1>;]
kono
parents:
diff changeset
177 (4a) t_2 = PHI <a_0, t_1>;
kono
parents:
diff changeset
178 (5) [x_3 = x_2 + 1;]
kono
parents:
diff changeset
179 (6r) a_1 = t_2 + 5;
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 where the bracketed instructions may go dead.
kono
parents:
diff changeset
182
kono
parents:
diff changeset
183 To recognize this opportunity, we have to observe that statement (6)
kono
parents:
diff changeset
184 has a "hidden basis" (2). The hidden basis is unlike a normal basis
kono
parents:
diff changeset
185 in that the statement and the hidden basis have different base SSA
kono
parents:
diff changeset
186 names (x_2 and x_0, respectively). The relationship is established
kono
parents:
diff changeset
187 when a statement's base name (x_2) is defined by a phi statement (4),
kono
parents:
diff changeset
188 each argument of which (x_0, x_1) has an identical "derived base name."
kono
parents:
diff changeset
189 If the argument is defined by a candidate (as x_1 is by (3)) that is a
kono
parents:
diff changeset
190 CAND_ADD having a stride of 1, the derived base name of the argument is
kono
parents:
diff changeset
191 the base name of the candidate (x_0). Otherwise, the argument itself
kono
parents:
diff changeset
192 is its derived base name (as is the case with argument x_0).
kono
parents:
diff changeset
193
kono
parents:
diff changeset
194 The hidden basis for statement (6) is the nearest dominating candidate
kono
parents:
diff changeset
195 whose base name is the derived base name (x_0) of the feeding phi (4),
kono
parents:
diff changeset
196 and whose stride is identical to that of the statement. We can then
kono
parents:
diff changeset
197 create the new "phi basis" (4a) and feeding adds along incoming arcs (3a),
kono
parents:
diff changeset
198 allowing the final replacement of (6) by the strength-reduced (6r).
kono
parents:
diff changeset
199
kono
parents:
diff changeset
200 To facilitate this, a new kind of candidate (CAND_PHI) is introduced.
kono
parents:
diff changeset
201 A CAND_PHI is not a candidate for replacement, but is maintained in the
kono
parents:
diff changeset
202 candidate table to ease discovery of hidden bases. Any phi statement
kono
parents:
diff changeset
203 whose arguments share a common derived base name is entered into the
kono
parents:
diff changeset
204 table with the derived base name, an (arbitrary) index of zero, and a
kono
parents:
diff changeset
205 stride of 1. A statement with a hidden basis can then be detected by
kono
parents:
diff changeset
206 simply looking up its feeding phi definition in the candidate table,
kono
parents:
diff changeset
207 extracting the derived base name, and searching for a basis in the
kono
parents:
diff changeset
208 usual manner after substituting the derived base name.
kono
parents:
diff changeset
209
kono
parents:
diff changeset
210 Note that the transformation is only valid when the original phi and
kono
parents:
diff changeset
211 the statements that define the phi's arguments are all at the same
kono
parents:
diff changeset
212 position in the loop hierarchy. */
kono
parents:
diff changeset
213
kono
parents:
diff changeset
214
kono
parents:
diff changeset
215 /* Index into the candidate vector, offset by 1. VECs are zero-based,
kono
parents:
diff changeset
216 while cand_idx's are one-based, with zero indicating null. */
kono
parents:
diff changeset
217 typedef unsigned cand_idx;
kono
parents:
diff changeset
218
kono
parents:
diff changeset
219 /* The kind of candidate. */
kono
parents:
diff changeset
220 enum cand_kind
kono
parents:
diff changeset
221 {
kono
parents:
diff changeset
222 CAND_MULT,
kono
parents:
diff changeset
223 CAND_ADD,
kono
parents:
diff changeset
224 CAND_REF,
kono
parents:
diff changeset
225 CAND_PHI
kono
parents:
diff changeset
226 };
kono
parents:
diff changeset
227
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
228 class slsr_cand_d
111
kono
parents:
diff changeset
229 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
230 public:
111
kono
parents:
diff changeset
231 /* The candidate statement S1. */
kono
parents:
diff changeset
232 gimple *cand_stmt;
kono
parents:
diff changeset
233
kono
parents:
diff changeset
234 /* The base expression B: often an SSA name, but not always. */
kono
parents:
diff changeset
235 tree base_expr;
kono
parents:
diff changeset
236
kono
parents:
diff changeset
237 /* The stride S. */
kono
parents:
diff changeset
238 tree stride;
kono
parents:
diff changeset
239
kono
parents:
diff changeset
240 /* The index constant i. */
kono
parents:
diff changeset
241 widest_int index;
kono
parents:
diff changeset
242
kono
parents:
diff changeset
243 /* The type of the candidate. This is normally the type of base_expr,
kono
parents:
diff changeset
244 but casts may have occurred when combining feeding instructions.
kono
parents:
diff changeset
245 A candidate can only be a basis for candidates of the same final type.
kono
parents:
diff changeset
246 (For CAND_REFs, this is the type to be used for operand 1 of the
kono
parents:
diff changeset
247 replacement MEM_REF.) */
kono
parents:
diff changeset
248 tree cand_type;
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 /* The type to be used to interpret the stride field when the stride
kono
parents:
diff changeset
251 is not a constant. Normally the same as the type of the recorded
kono
parents:
diff changeset
252 stride, but when the stride has been cast we need to maintain that
kono
parents:
diff changeset
253 knowledge in order to make legal substitutions without losing
kono
parents:
diff changeset
254 precision. When the stride is a constant, this will be sizetype. */
kono
parents:
diff changeset
255 tree stride_type;
kono
parents:
diff changeset
256
kono
parents:
diff changeset
257 /* The kind of candidate (CAND_MULT, etc.). */
kono
parents:
diff changeset
258 enum cand_kind kind;
kono
parents:
diff changeset
259
kono
parents:
diff changeset
260 /* Index of this candidate in the candidate vector. */
kono
parents:
diff changeset
261 cand_idx cand_num;
kono
parents:
diff changeset
262
kono
parents:
diff changeset
263 /* Index of the next candidate record for the same statement.
kono
parents:
diff changeset
264 A statement may be useful in more than one way (e.g., due to
kono
parents:
diff changeset
265 commutativity). So we can have multiple "interpretations"
kono
parents:
diff changeset
266 of a statement. */
kono
parents:
diff changeset
267 cand_idx next_interp;
kono
parents:
diff changeset
268
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
269 /* Index of the first candidate record in a chain for the same
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
270 statement. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
271 cand_idx first_interp;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
272
111
kono
parents:
diff changeset
273 /* Index of the basis statement S0, if any, in the candidate vector. */
kono
parents:
diff changeset
274 cand_idx basis;
kono
parents:
diff changeset
275
kono
parents:
diff changeset
276 /* First candidate for which this candidate is a basis, if one exists. */
kono
parents:
diff changeset
277 cand_idx dependent;
kono
parents:
diff changeset
278
kono
parents:
diff changeset
279 /* Next candidate having the same basis as this one. */
kono
parents:
diff changeset
280 cand_idx sibling;
kono
parents:
diff changeset
281
kono
parents:
diff changeset
282 /* If this is a conditional candidate, the CAND_PHI candidate
kono
parents:
diff changeset
283 that defines the base SSA name B. */
kono
parents:
diff changeset
284 cand_idx def_phi;
kono
parents:
diff changeset
285
kono
parents:
diff changeset
286 /* Savings that can be expected from eliminating dead code if this
kono
parents:
diff changeset
287 candidate is replaced. */
kono
parents:
diff changeset
288 int dead_savings;
kono
parents:
diff changeset
289
kono
parents:
diff changeset
290 /* For PHI candidates, use a visited flag to keep from processing the
kono
parents:
diff changeset
291 same PHI twice from multiple paths. */
kono
parents:
diff changeset
292 int visited;
kono
parents:
diff changeset
293
kono
parents:
diff changeset
294 /* We sometimes have to cache a phi basis with a phi candidate to
kono
parents:
diff changeset
295 avoid processing it twice. Valid only if visited==1. */
kono
parents:
diff changeset
296 tree cached_basis;
kono
parents:
diff changeset
297 };
kono
parents:
diff changeset
298
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
299 typedef class slsr_cand_d slsr_cand, *slsr_cand_t;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
300 typedef const class slsr_cand_d *const_slsr_cand_t;
111
kono
parents:
diff changeset
301
kono
parents:
diff changeset
302 /* Pointers to candidates are chained together as part of a mapping
kono
parents:
diff changeset
303 from base expressions to the candidates that use them. */
kono
parents:
diff changeset
304
kono
parents:
diff changeset
305 struct cand_chain_d
kono
parents:
diff changeset
306 {
kono
parents:
diff changeset
307 /* Base expression for the chain of candidates: often, but not
kono
parents:
diff changeset
308 always, an SSA name. */
kono
parents:
diff changeset
309 tree base_expr;
kono
parents:
diff changeset
310
kono
parents:
diff changeset
311 /* Pointer to a candidate. */
kono
parents:
diff changeset
312 slsr_cand_t cand;
kono
parents:
diff changeset
313
kono
parents:
diff changeset
314 /* Chain pointer. */
kono
parents:
diff changeset
315 struct cand_chain_d *next;
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 };
kono
parents:
diff changeset
318
kono
parents:
diff changeset
319 typedef struct cand_chain_d cand_chain, *cand_chain_t;
kono
parents:
diff changeset
320 typedef const struct cand_chain_d *const_cand_chain_t;
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 /* Information about a unique "increment" associated with candidates
kono
parents:
diff changeset
323 having an SSA name for a stride. An increment is the difference
kono
parents:
diff changeset
324 between the index of the candidate and the index of its basis,
kono
parents:
diff changeset
325 i.e., (i - i') as discussed in the module commentary.
kono
parents:
diff changeset
326
kono
parents:
diff changeset
327 When we are not going to generate address arithmetic we treat
kono
parents:
diff changeset
328 increments that differ only in sign as the same, allowing sharing
kono
parents:
diff changeset
329 of the cost of initializers. The absolute value of the increment
kono
parents:
diff changeset
330 is stored in the incr_info. */
kono
parents:
diff changeset
331
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
332 class incr_info_d
111
kono
parents:
diff changeset
333 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
334 public:
111
kono
parents:
diff changeset
335 /* The increment that relates a candidate to its basis. */
kono
parents:
diff changeset
336 widest_int incr;
kono
parents:
diff changeset
337
kono
parents:
diff changeset
338 /* How many times the increment occurs in the candidate tree. */
kono
parents:
diff changeset
339 unsigned count;
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 /* Cost of replacing candidates using this increment. Negative and
kono
parents:
diff changeset
342 zero costs indicate replacement should be performed. */
kono
parents:
diff changeset
343 int cost;
kono
parents:
diff changeset
344
kono
parents:
diff changeset
345 /* If this increment is profitable but is not -1, 0, or 1, it requires
kono
parents:
diff changeset
346 an initializer T_0 = stride * incr to be found or introduced in the
kono
parents:
diff changeset
347 nearest common dominator of all candidates. This field holds T_0
kono
parents:
diff changeset
348 for subsequent use. */
kono
parents:
diff changeset
349 tree initializer;
kono
parents:
diff changeset
350
kono
parents:
diff changeset
351 /* If the initializer was found to already exist, this is the block
kono
parents:
diff changeset
352 where it was found. */
kono
parents:
diff changeset
353 basic_block init_bb;
kono
parents:
diff changeset
354 };
kono
parents:
diff changeset
355
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
356 typedef class incr_info_d incr_info, *incr_info_t;
111
kono
parents:
diff changeset
357
kono
parents:
diff changeset
358 /* Candidates are maintained in a vector. If candidate X dominates
kono
parents:
diff changeset
359 candidate Y, then X appears before Y in the vector; but the
kono
parents:
diff changeset
360 converse does not necessarily hold. */
kono
parents:
diff changeset
361 static vec<slsr_cand_t> cand_vec;
kono
parents:
diff changeset
362
kono
parents:
diff changeset
363 enum cost_consts
kono
parents:
diff changeset
364 {
kono
parents:
diff changeset
365 COST_NEUTRAL = 0,
kono
parents:
diff changeset
366 COST_INFINITE = 1000
kono
parents:
diff changeset
367 };
kono
parents:
diff changeset
368
kono
parents:
diff changeset
369 enum stride_status
kono
parents:
diff changeset
370 {
kono
parents:
diff changeset
371 UNKNOWN_STRIDE = 0,
kono
parents:
diff changeset
372 KNOWN_STRIDE = 1
kono
parents:
diff changeset
373 };
kono
parents:
diff changeset
374
kono
parents:
diff changeset
375 enum phi_adjust_status
kono
parents:
diff changeset
376 {
kono
parents:
diff changeset
377 NOT_PHI_ADJUST = 0,
kono
parents:
diff changeset
378 PHI_ADJUST = 1
kono
parents:
diff changeset
379 };
kono
parents:
diff changeset
380
kono
parents:
diff changeset
381 enum count_phis_status
kono
parents:
diff changeset
382 {
kono
parents:
diff changeset
383 DONT_COUNT_PHIS = 0,
kono
parents:
diff changeset
384 COUNT_PHIS = 1
kono
parents:
diff changeset
385 };
kono
parents:
diff changeset
386
kono
parents:
diff changeset
387 /* Constrain how many PHI nodes we will visit for a conditional
kono
parents:
diff changeset
388 candidate (depth and breadth). */
kono
parents:
diff changeset
389 const int MAX_SPREAD = 16;
kono
parents:
diff changeset
390
kono
parents:
diff changeset
391 /* Pointer map embodying a mapping from statements to candidates. */
kono
parents:
diff changeset
392 static hash_map<gimple *, slsr_cand_t> *stmt_cand_map;
kono
parents:
diff changeset
393
kono
parents:
diff changeset
394 /* Obstack for candidates. */
kono
parents:
diff changeset
395 static struct obstack cand_obstack;
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 /* Obstack for candidate chains. */
kono
parents:
diff changeset
398 static struct obstack chain_obstack;
kono
parents:
diff changeset
399
kono
parents:
diff changeset
400 /* An array INCR_VEC of incr_infos is used during analysis of related
kono
parents:
diff changeset
401 candidates having an SSA name for a stride. INCR_VEC_LEN describes
kono
parents:
diff changeset
402 its current length. MAX_INCR_VEC_LEN is used to avoid costly
kono
parents:
diff changeset
403 pathological cases. */
kono
parents:
diff changeset
404 static incr_info_t incr_vec;
kono
parents:
diff changeset
405 static unsigned incr_vec_len;
kono
parents:
diff changeset
406 const int MAX_INCR_VEC_LEN = 16;
kono
parents:
diff changeset
407
kono
parents:
diff changeset
408 /* For a chain of candidates with unknown stride, indicates whether or not
kono
parents:
diff changeset
409 we must generate pointer arithmetic when replacing statements. */
kono
parents:
diff changeset
410 static bool address_arithmetic_p;
kono
parents:
diff changeset
411
kono
parents:
diff changeset
412 /* Forward function declarations. */
kono
parents:
diff changeset
413 static slsr_cand_t base_cand_from_table (tree);
kono
parents:
diff changeset
414 static tree introduce_cast_before_cand (slsr_cand_t, tree, tree);
kono
parents:
diff changeset
415 static bool legal_cast_p_1 (tree, tree);
kono
parents:
diff changeset
416
kono
parents:
diff changeset
417 /* Produce a pointer to the IDX'th candidate in the candidate vector. */
kono
parents:
diff changeset
418
kono
parents:
diff changeset
419 static slsr_cand_t
kono
parents:
diff changeset
420 lookup_cand (cand_idx idx)
kono
parents:
diff changeset
421 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
422 return cand_vec[idx];
111
kono
parents:
diff changeset
423 }
kono
parents:
diff changeset
424
kono
parents:
diff changeset
425 /* Helper for hashing a candidate chain header. */
kono
parents:
diff changeset
426
kono
parents:
diff changeset
427 struct cand_chain_hasher : nofree_ptr_hash <cand_chain>
kono
parents:
diff changeset
428 {
kono
parents:
diff changeset
429 static inline hashval_t hash (const cand_chain *);
kono
parents:
diff changeset
430 static inline bool equal (const cand_chain *, const cand_chain *);
kono
parents:
diff changeset
431 };
kono
parents:
diff changeset
432
kono
parents:
diff changeset
433 inline hashval_t
kono
parents:
diff changeset
434 cand_chain_hasher::hash (const cand_chain *p)
kono
parents:
diff changeset
435 {
kono
parents:
diff changeset
436 tree base_expr = p->base_expr;
kono
parents:
diff changeset
437 return iterative_hash_expr (base_expr, 0);
kono
parents:
diff changeset
438 }
kono
parents:
diff changeset
439
kono
parents:
diff changeset
440 inline bool
kono
parents:
diff changeset
441 cand_chain_hasher::equal (const cand_chain *chain1, const cand_chain *chain2)
kono
parents:
diff changeset
442 {
kono
parents:
diff changeset
443 return operand_equal_p (chain1->base_expr, chain2->base_expr, 0);
kono
parents:
diff changeset
444 }
kono
parents:
diff changeset
445
kono
parents:
diff changeset
446 /* Hash table embodying a mapping from base exprs to chains of candidates. */
kono
parents:
diff changeset
447 static hash_table<cand_chain_hasher> *base_cand_map;
kono
parents:
diff changeset
448
kono
parents:
diff changeset
449 /* Pointer map used by tree_to_aff_combination_expand. */
kono
parents:
diff changeset
450 static hash_map<tree, name_expansion *> *name_expansions;
kono
parents:
diff changeset
451 /* Pointer map embodying a mapping from bases to alternative bases. */
kono
parents:
diff changeset
452 static hash_map<tree, tree> *alt_base_map;
kono
parents:
diff changeset
453
kono
parents:
diff changeset
454 /* Given BASE, use the tree affine combiniation facilities to
kono
parents:
diff changeset
455 find the underlying tree expression for BASE, with any
kono
parents:
diff changeset
456 immediate offset excluded.
kono
parents:
diff changeset
457
kono
parents:
diff changeset
458 N.B. we should eliminate this backtracking with better forward
kono
parents:
diff changeset
459 analysis in a future release. */
kono
parents:
diff changeset
460
kono
parents:
diff changeset
461 static tree
kono
parents:
diff changeset
462 get_alternative_base (tree base)
kono
parents:
diff changeset
463 {
kono
parents:
diff changeset
464 tree *result = alt_base_map->get (base);
kono
parents:
diff changeset
465
kono
parents:
diff changeset
466 if (result == NULL)
kono
parents:
diff changeset
467 {
kono
parents:
diff changeset
468 tree expr;
kono
parents:
diff changeset
469 aff_tree aff;
kono
parents:
diff changeset
470
kono
parents:
diff changeset
471 tree_to_aff_combination_expand (base, TREE_TYPE (base),
kono
parents:
diff changeset
472 &aff, &name_expansions);
kono
parents:
diff changeset
473 aff.offset = 0;
kono
parents:
diff changeset
474 expr = aff_combination_to_tree (&aff);
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 gcc_assert (!alt_base_map->put (base, base == expr ? NULL : expr));
kono
parents:
diff changeset
477
kono
parents:
diff changeset
478 return expr == base ? NULL : expr;
kono
parents:
diff changeset
479 }
kono
parents:
diff changeset
480
kono
parents:
diff changeset
481 return *result;
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 /* Look in the candidate table for a CAND_PHI that defines BASE and
kono
parents:
diff changeset
485 return it if found; otherwise return NULL. */
kono
parents:
diff changeset
486
kono
parents:
diff changeset
487 static cand_idx
kono
parents:
diff changeset
488 find_phi_def (tree base)
kono
parents:
diff changeset
489 {
kono
parents:
diff changeset
490 slsr_cand_t c;
kono
parents:
diff changeset
491
kono
parents:
diff changeset
492 if (TREE_CODE (base) != SSA_NAME)
kono
parents:
diff changeset
493 return 0;
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 c = base_cand_from_table (base);
kono
parents:
diff changeset
496
kono
parents:
diff changeset
497 if (!c || c->kind != CAND_PHI
kono
parents:
diff changeset
498 || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (c->cand_stmt)))
kono
parents:
diff changeset
499 return 0;
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 return c->cand_num;
kono
parents:
diff changeset
502 }
kono
parents:
diff changeset
503
kono
parents:
diff changeset
504 /* Determine whether all uses of NAME are directly or indirectly
kono
parents:
diff changeset
505 used by STMT. That is, we want to know whether if STMT goes
kono
parents:
diff changeset
506 dead, the definition of NAME also goes dead. */
kono
parents:
diff changeset
507 static bool
kono
parents:
diff changeset
508 uses_consumed_by_stmt (tree name, gimple *stmt, unsigned recurse = 0)
kono
parents:
diff changeset
509 {
kono
parents:
diff changeset
510 gimple *use_stmt;
kono
parents:
diff changeset
511 imm_use_iterator iter;
kono
parents:
diff changeset
512 bool retval = true;
kono
parents:
diff changeset
513
kono
parents:
diff changeset
514 FOR_EACH_IMM_USE_STMT (use_stmt, iter, name)
kono
parents:
diff changeset
515 {
kono
parents:
diff changeset
516 if (use_stmt == stmt || is_gimple_debug (use_stmt))
kono
parents:
diff changeset
517 continue;
kono
parents:
diff changeset
518
kono
parents:
diff changeset
519 if (!is_gimple_assign (use_stmt)
kono
parents:
diff changeset
520 || !gimple_get_lhs (use_stmt)
kono
parents:
diff changeset
521 || !is_gimple_reg (gimple_get_lhs (use_stmt))
kono
parents:
diff changeset
522 || recurse >= 10
kono
parents:
diff changeset
523 || !uses_consumed_by_stmt (gimple_get_lhs (use_stmt), stmt,
kono
parents:
diff changeset
524 recurse + 1))
kono
parents:
diff changeset
525 {
kono
parents:
diff changeset
526 retval = false;
kono
parents:
diff changeset
527 BREAK_FROM_IMM_USE_STMT (iter);
kono
parents:
diff changeset
528 }
kono
parents:
diff changeset
529 }
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 return retval;
kono
parents:
diff changeset
532 }
kono
parents:
diff changeset
533
kono
parents:
diff changeset
534 /* Helper routine for find_basis_for_candidate. May be called twice:
kono
parents:
diff changeset
535 once for the candidate's base expr, and optionally again either for
kono
parents:
diff changeset
536 the candidate's phi definition or for a CAND_REF's alternative base
kono
parents:
diff changeset
537 expression. */
kono
parents:
diff changeset
538
kono
parents:
diff changeset
539 static slsr_cand_t
kono
parents:
diff changeset
540 find_basis_for_base_expr (slsr_cand_t c, tree base_expr)
kono
parents:
diff changeset
541 {
kono
parents:
diff changeset
542 cand_chain mapping_key;
kono
parents:
diff changeset
543 cand_chain_t chain;
kono
parents:
diff changeset
544 slsr_cand_t basis = NULL;
kono
parents:
diff changeset
545
kono
parents:
diff changeset
546 // Limit potential of N^2 behavior for long candidate chains.
kono
parents:
diff changeset
547 int iters = 0;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
548 int max_iters = param_max_slsr_candidate_scan;
111
kono
parents:
diff changeset
549
kono
parents:
diff changeset
550 mapping_key.base_expr = base_expr;
kono
parents:
diff changeset
551 chain = base_cand_map->find (&mapping_key);
kono
parents:
diff changeset
552
kono
parents:
diff changeset
553 for (; chain && iters < max_iters; chain = chain->next, ++iters)
kono
parents:
diff changeset
554 {
kono
parents:
diff changeset
555 slsr_cand_t one_basis = chain->cand;
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 if (one_basis->kind != c->kind
kono
parents:
diff changeset
558 || one_basis->cand_stmt == c->cand_stmt
kono
parents:
diff changeset
559 || !operand_equal_p (one_basis->stride, c->stride, 0)
kono
parents:
diff changeset
560 || !types_compatible_p (one_basis->cand_type, c->cand_type)
kono
parents:
diff changeset
561 || !types_compatible_p (one_basis->stride_type, c->stride_type)
kono
parents:
diff changeset
562 || !dominated_by_p (CDI_DOMINATORS,
kono
parents:
diff changeset
563 gimple_bb (c->cand_stmt),
kono
parents:
diff changeset
564 gimple_bb (one_basis->cand_stmt)))
kono
parents:
diff changeset
565 continue;
kono
parents:
diff changeset
566
kono
parents:
diff changeset
567 tree lhs = gimple_assign_lhs (one_basis->cand_stmt);
kono
parents:
diff changeset
568 if (lhs && TREE_CODE (lhs) == SSA_NAME
kono
parents:
diff changeset
569 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs))
kono
parents:
diff changeset
570 continue;
kono
parents:
diff changeset
571
kono
parents:
diff changeset
572 if (!basis || basis->cand_num < one_basis->cand_num)
kono
parents:
diff changeset
573 basis = one_basis;
kono
parents:
diff changeset
574 }
kono
parents:
diff changeset
575
kono
parents:
diff changeset
576 return basis;
kono
parents:
diff changeset
577 }
kono
parents:
diff changeset
578
kono
parents:
diff changeset
579 /* Use the base expr from candidate C to look for possible candidates
kono
parents:
diff changeset
580 that can serve as a basis for C. Each potential basis must also
kono
parents:
diff changeset
581 appear in a block that dominates the candidate statement and have
kono
parents:
diff changeset
582 the same stride and type. If more than one possible basis exists,
kono
parents:
diff changeset
583 the one with highest index in the vector is chosen; this will be
kono
parents:
diff changeset
584 the most immediately dominating basis. */
kono
parents:
diff changeset
585
kono
parents:
diff changeset
586 static int
kono
parents:
diff changeset
587 find_basis_for_candidate (slsr_cand_t c)
kono
parents:
diff changeset
588 {
kono
parents:
diff changeset
589 slsr_cand_t basis = find_basis_for_base_expr (c, c->base_expr);
kono
parents:
diff changeset
590
kono
parents:
diff changeset
591 /* If a candidate doesn't have a basis using its base expression,
kono
parents:
diff changeset
592 it may have a basis hidden by one or more intervening phis. */
kono
parents:
diff changeset
593 if (!basis && c->def_phi)
kono
parents:
diff changeset
594 {
kono
parents:
diff changeset
595 basic_block basis_bb, phi_bb;
kono
parents:
diff changeset
596 slsr_cand_t phi_cand = lookup_cand (c->def_phi);
kono
parents:
diff changeset
597 basis = find_basis_for_base_expr (c, phi_cand->base_expr);
kono
parents:
diff changeset
598
kono
parents:
diff changeset
599 if (basis)
kono
parents:
diff changeset
600 {
kono
parents:
diff changeset
601 /* A hidden basis must dominate the phi-definition of the
kono
parents:
diff changeset
602 candidate's base name. */
kono
parents:
diff changeset
603 phi_bb = gimple_bb (phi_cand->cand_stmt);
kono
parents:
diff changeset
604 basis_bb = gimple_bb (basis->cand_stmt);
kono
parents:
diff changeset
605
kono
parents:
diff changeset
606 if (phi_bb == basis_bb
kono
parents:
diff changeset
607 || !dominated_by_p (CDI_DOMINATORS, phi_bb, basis_bb))
kono
parents:
diff changeset
608 {
kono
parents:
diff changeset
609 basis = NULL;
kono
parents:
diff changeset
610 c->basis = 0;
kono
parents:
diff changeset
611 }
kono
parents:
diff changeset
612
kono
parents:
diff changeset
613 /* If we found a hidden basis, estimate additional dead-code
kono
parents:
diff changeset
614 savings if the phi and its feeding statements can be removed. */
kono
parents:
diff changeset
615 tree feeding_var = gimple_phi_result (phi_cand->cand_stmt);
kono
parents:
diff changeset
616 if (basis && uses_consumed_by_stmt (feeding_var, c->cand_stmt))
kono
parents:
diff changeset
617 c->dead_savings += phi_cand->dead_savings;
kono
parents:
diff changeset
618 }
kono
parents:
diff changeset
619 }
kono
parents:
diff changeset
620
kono
parents:
diff changeset
621 if (flag_expensive_optimizations && !basis && c->kind == CAND_REF)
kono
parents:
diff changeset
622 {
kono
parents:
diff changeset
623 tree alt_base_expr = get_alternative_base (c->base_expr);
kono
parents:
diff changeset
624 if (alt_base_expr)
kono
parents:
diff changeset
625 basis = find_basis_for_base_expr (c, alt_base_expr);
kono
parents:
diff changeset
626 }
kono
parents:
diff changeset
627
kono
parents:
diff changeset
628 if (basis)
kono
parents:
diff changeset
629 {
kono
parents:
diff changeset
630 c->sibling = basis->dependent;
kono
parents:
diff changeset
631 basis->dependent = c->cand_num;
kono
parents:
diff changeset
632 return basis->cand_num;
kono
parents:
diff changeset
633 }
kono
parents:
diff changeset
634
kono
parents:
diff changeset
635 return 0;
kono
parents:
diff changeset
636 }
kono
parents:
diff changeset
637
kono
parents:
diff changeset
638 /* Record a mapping from BASE to C, indicating that C may potentially serve
kono
parents:
diff changeset
639 as a basis using that base expression. BASE may be the same as
kono
parents:
diff changeset
640 C->BASE_EXPR; alternatively BASE can be a different tree that share the
kono
parents:
diff changeset
641 underlining expression of C->BASE_EXPR. */
kono
parents:
diff changeset
642
kono
parents:
diff changeset
643 static void
kono
parents:
diff changeset
644 record_potential_basis (slsr_cand_t c, tree base)
kono
parents:
diff changeset
645 {
kono
parents:
diff changeset
646 cand_chain_t node;
kono
parents:
diff changeset
647 cand_chain **slot;
kono
parents:
diff changeset
648
kono
parents:
diff changeset
649 gcc_assert (base);
kono
parents:
diff changeset
650
kono
parents:
diff changeset
651 node = (cand_chain_t) obstack_alloc (&chain_obstack, sizeof (cand_chain));
kono
parents:
diff changeset
652 node->base_expr = base;
kono
parents:
diff changeset
653 node->cand = c;
kono
parents:
diff changeset
654 node->next = NULL;
kono
parents:
diff changeset
655 slot = base_cand_map->find_slot (node, INSERT);
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 if (*slot)
kono
parents:
diff changeset
658 {
kono
parents:
diff changeset
659 cand_chain_t head = (cand_chain_t) (*slot);
kono
parents:
diff changeset
660 node->next = head->next;
kono
parents:
diff changeset
661 head->next = node;
kono
parents:
diff changeset
662 }
kono
parents:
diff changeset
663 else
kono
parents:
diff changeset
664 *slot = node;
kono
parents:
diff changeset
665 }
kono
parents:
diff changeset
666
kono
parents:
diff changeset
667 /* Allocate storage for a new candidate and initialize its fields.
kono
parents:
diff changeset
668 Attempt to find a basis for the candidate.
kono
parents:
diff changeset
669
kono
parents:
diff changeset
670 For CAND_REF, an alternative base may also be recorded and used
kono
parents:
diff changeset
671 to find a basis. This helps cases where the expression hidden
kono
parents:
diff changeset
672 behind BASE (which is usually an SSA_NAME) has immediate offset,
kono
parents:
diff changeset
673 e.g.
kono
parents:
diff changeset
674
kono
parents:
diff changeset
675 a2[i][j] = 1;
kono
parents:
diff changeset
676 a2[i + 20][j] = 2; */
kono
parents:
diff changeset
677
kono
parents:
diff changeset
678 static slsr_cand_t
kono
parents:
diff changeset
679 alloc_cand_and_find_basis (enum cand_kind kind, gimple *gs, tree base,
kono
parents:
diff changeset
680 const widest_int &index, tree stride, tree ctype,
kono
parents:
diff changeset
681 tree stype, unsigned savings)
kono
parents:
diff changeset
682 {
kono
parents:
diff changeset
683 slsr_cand_t c = (slsr_cand_t) obstack_alloc (&cand_obstack,
kono
parents:
diff changeset
684 sizeof (slsr_cand));
kono
parents:
diff changeset
685 c->cand_stmt = gs;
kono
parents:
diff changeset
686 c->base_expr = base;
kono
parents:
diff changeset
687 c->stride = stride;
kono
parents:
diff changeset
688 c->index = index;
kono
parents:
diff changeset
689 c->cand_type = ctype;
kono
parents:
diff changeset
690 c->stride_type = stype;
kono
parents:
diff changeset
691 c->kind = kind;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
692 c->cand_num = cand_vec.length ();
111
kono
parents:
diff changeset
693 c->next_interp = 0;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
694 c->first_interp = c->cand_num;
111
kono
parents:
diff changeset
695 c->dependent = 0;
kono
parents:
diff changeset
696 c->sibling = 0;
kono
parents:
diff changeset
697 c->def_phi = kind == CAND_MULT ? find_phi_def (base) : 0;
kono
parents:
diff changeset
698 c->dead_savings = savings;
kono
parents:
diff changeset
699 c->visited = 0;
kono
parents:
diff changeset
700 c->cached_basis = NULL_TREE;
kono
parents:
diff changeset
701
kono
parents:
diff changeset
702 cand_vec.safe_push (c);
kono
parents:
diff changeset
703
kono
parents:
diff changeset
704 if (kind == CAND_PHI)
kono
parents:
diff changeset
705 c->basis = 0;
kono
parents:
diff changeset
706 else
kono
parents:
diff changeset
707 c->basis = find_basis_for_candidate (c);
kono
parents:
diff changeset
708
kono
parents:
diff changeset
709 record_potential_basis (c, base);
kono
parents:
diff changeset
710 if (flag_expensive_optimizations && kind == CAND_REF)
kono
parents:
diff changeset
711 {
kono
parents:
diff changeset
712 tree alt_base = get_alternative_base (base);
kono
parents:
diff changeset
713 if (alt_base)
kono
parents:
diff changeset
714 record_potential_basis (c, alt_base);
kono
parents:
diff changeset
715 }
kono
parents:
diff changeset
716
kono
parents:
diff changeset
717 return c;
kono
parents:
diff changeset
718 }
kono
parents:
diff changeset
719
kono
parents:
diff changeset
720 /* Determine the target cost of statement GS when compiling according
kono
parents:
diff changeset
721 to SPEED. */
kono
parents:
diff changeset
722
kono
parents:
diff changeset
723 static int
kono
parents:
diff changeset
724 stmt_cost (gimple *gs, bool speed)
kono
parents:
diff changeset
725 {
kono
parents:
diff changeset
726 tree lhs, rhs1, rhs2;
kono
parents:
diff changeset
727 machine_mode lhs_mode;
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 gcc_assert (is_gimple_assign (gs));
kono
parents:
diff changeset
730 lhs = gimple_assign_lhs (gs);
kono
parents:
diff changeset
731 rhs1 = gimple_assign_rhs1 (gs);
kono
parents:
diff changeset
732 lhs_mode = TYPE_MODE (TREE_TYPE (lhs));
kono
parents:
diff changeset
733
kono
parents:
diff changeset
734 switch (gimple_assign_rhs_code (gs))
kono
parents:
diff changeset
735 {
kono
parents:
diff changeset
736 case MULT_EXPR:
kono
parents:
diff changeset
737 rhs2 = gimple_assign_rhs2 (gs);
kono
parents:
diff changeset
738
kono
parents:
diff changeset
739 if (tree_fits_shwi_p (rhs2))
kono
parents:
diff changeset
740 return mult_by_coeff_cost (tree_to_shwi (rhs2), lhs_mode, speed);
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 gcc_assert (TREE_CODE (rhs1) != INTEGER_CST);
kono
parents:
diff changeset
743 return mul_cost (speed, lhs_mode);
kono
parents:
diff changeset
744
kono
parents:
diff changeset
745 case PLUS_EXPR:
kono
parents:
diff changeset
746 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
747 case MINUS_EXPR:
kono
parents:
diff changeset
748 return add_cost (speed, lhs_mode);
kono
parents:
diff changeset
749
kono
parents:
diff changeset
750 case NEGATE_EXPR:
kono
parents:
diff changeset
751 return neg_cost (speed, lhs_mode);
kono
parents:
diff changeset
752
kono
parents:
diff changeset
753 CASE_CONVERT:
kono
parents:
diff changeset
754 return convert_cost (lhs_mode, TYPE_MODE (TREE_TYPE (rhs1)), speed);
kono
parents:
diff changeset
755
kono
parents:
diff changeset
756 /* Note that we don't assign costs to copies that in most cases
kono
parents:
diff changeset
757 will go away. */
kono
parents:
diff changeset
758 case SSA_NAME:
kono
parents:
diff changeset
759 return 0;
kono
parents:
diff changeset
760
kono
parents:
diff changeset
761 default:
kono
parents:
diff changeset
762 ;
kono
parents:
diff changeset
763 }
kono
parents:
diff changeset
764
kono
parents:
diff changeset
765 gcc_unreachable ();
kono
parents:
diff changeset
766 return 0;
kono
parents:
diff changeset
767 }
kono
parents:
diff changeset
768
kono
parents:
diff changeset
769 /* Look up the defining statement for BASE_IN and return a pointer
kono
parents:
diff changeset
770 to its candidate in the candidate table, if any; otherwise NULL.
kono
parents:
diff changeset
771 Only CAND_ADD and CAND_MULT candidates are returned. */
kono
parents:
diff changeset
772
kono
parents:
diff changeset
773 static slsr_cand_t
kono
parents:
diff changeset
774 base_cand_from_table (tree base_in)
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 slsr_cand_t *result;
kono
parents:
diff changeset
777
kono
parents:
diff changeset
778 gimple *def = SSA_NAME_DEF_STMT (base_in);
kono
parents:
diff changeset
779 if (!def)
kono
parents:
diff changeset
780 return (slsr_cand_t) NULL;
kono
parents:
diff changeset
781
kono
parents:
diff changeset
782 result = stmt_cand_map->get (def);
kono
parents:
diff changeset
783
kono
parents:
diff changeset
784 if (result && (*result)->kind != CAND_REF)
kono
parents:
diff changeset
785 return *result;
kono
parents:
diff changeset
786
kono
parents:
diff changeset
787 return (slsr_cand_t) NULL;
kono
parents:
diff changeset
788 }
kono
parents:
diff changeset
789
kono
parents:
diff changeset
790 /* Add an entry to the statement-to-candidate mapping. */
kono
parents:
diff changeset
791
kono
parents:
diff changeset
792 static void
kono
parents:
diff changeset
793 add_cand_for_stmt (gimple *gs, slsr_cand_t c)
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 gcc_assert (!stmt_cand_map->put (gs, c));
kono
parents:
diff changeset
796 }
kono
parents:
diff changeset
797
kono
parents:
diff changeset
798 /* Given PHI which contains a phi statement, determine whether it
kono
parents:
diff changeset
799 satisfies all the requirements of a phi candidate. If so, create
kono
parents:
diff changeset
800 a candidate. Note that a CAND_PHI never has a basis itself, but
kono
parents:
diff changeset
801 is used to help find a basis for subsequent candidates. */
kono
parents:
diff changeset
802
kono
parents:
diff changeset
803 static void
kono
parents:
diff changeset
804 slsr_process_phi (gphi *phi, bool speed)
kono
parents:
diff changeset
805 {
kono
parents:
diff changeset
806 unsigned i;
kono
parents:
diff changeset
807 tree arg0_base = NULL_TREE, base_type;
kono
parents:
diff changeset
808 slsr_cand_t c;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
809 class loop *cand_loop = gimple_bb (phi)->loop_father;
111
kono
parents:
diff changeset
810 unsigned savings = 0;
kono
parents:
diff changeset
811
kono
parents:
diff changeset
812 /* A CAND_PHI requires each of its arguments to have the same
kono
parents:
diff changeset
813 derived base name. (See the module header commentary for a
kono
parents:
diff changeset
814 definition of derived base names.) Furthermore, all feeding
kono
parents:
diff changeset
815 definitions must be in the same position in the loop hierarchy
kono
parents:
diff changeset
816 as PHI. */
kono
parents:
diff changeset
817
kono
parents:
diff changeset
818 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
819 {
kono
parents:
diff changeset
820 slsr_cand_t arg_cand;
kono
parents:
diff changeset
821 tree arg = gimple_phi_arg_def (phi, i);
kono
parents:
diff changeset
822 tree derived_base_name = NULL_TREE;
kono
parents:
diff changeset
823 gimple *arg_stmt = NULL;
kono
parents:
diff changeset
824 basic_block arg_bb = NULL;
kono
parents:
diff changeset
825
kono
parents:
diff changeset
826 if (TREE_CODE (arg) != SSA_NAME)
kono
parents:
diff changeset
827 return;
kono
parents:
diff changeset
828
kono
parents:
diff changeset
829 arg_cand = base_cand_from_table (arg);
kono
parents:
diff changeset
830
kono
parents:
diff changeset
831 if (arg_cand)
kono
parents:
diff changeset
832 {
kono
parents:
diff changeset
833 while (arg_cand->kind != CAND_ADD && arg_cand->kind != CAND_PHI)
kono
parents:
diff changeset
834 {
kono
parents:
diff changeset
835 if (!arg_cand->next_interp)
kono
parents:
diff changeset
836 return;
kono
parents:
diff changeset
837
kono
parents:
diff changeset
838 arg_cand = lookup_cand (arg_cand->next_interp);
kono
parents:
diff changeset
839 }
kono
parents:
diff changeset
840
kono
parents:
diff changeset
841 if (!integer_onep (arg_cand->stride))
kono
parents:
diff changeset
842 return;
kono
parents:
diff changeset
843
kono
parents:
diff changeset
844 derived_base_name = arg_cand->base_expr;
kono
parents:
diff changeset
845 arg_stmt = arg_cand->cand_stmt;
kono
parents:
diff changeset
846 arg_bb = gimple_bb (arg_stmt);
kono
parents:
diff changeset
847
kono
parents:
diff changeset
848 /* Gather potential dead code savings if the phi statement
kono
parents:
diff changeset
849 can be removed later on. */
kono
parents:
diff changeset
850 if (uses_consumed_by_stmt (arg, phi))
kono
parents:
diff changeset
851 {
kono
parents:
diff changeset
852 if (gimple_code (arg_stmt) == GIMPLE_PHI)
kono
parents:
diff changeset
853 savings += arg_cand->dead_savings;
kono
parents:
diff changeset
854 else
kono
parents:
diff changeset
855 savings += stmt_cost (arg_stmt, speed);
kono
parents:
diff changeset
856 }
kono
parents:
diff changeset
857 }
kono
parents:
diff changeset
858 else if (SSA_NAME_IS_DEFAULT_DEF (arg))
kono
parents:
diff changeset
859 {
kono
parents:
diff changeset
860 derived_base_name = arg;
kono
parents:
diff changeset
861 arg_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
kono
parents:
diff changeset
862 }
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 if (!arg_bb || arg_bb->loop_father != cand_loop)
kono
parents:
diff changeset
865 return;
kono
parents:
diff changeset
866
kono
parents:
diff changeset
867 if (i == 0)
kono
parents:
diff changeset
868 arg0_base = derived_base_name;
kono
parents:
diff changeset
869 else if (!operand_equal_p (derived_base_name, arg0_base, 0))
kono
parents:
diff changeset
870 return;
kono
parents:
diff changeset
871 }
kono
parents:
diff changeset
872
kono
parents:
diff changeset
873 /* Create the candidate. "alloc_cand_and_find_basis" is named
kono
parents:
diff changeset
874 misleadingly for this case, as no basis will be sought for a
kono
parents:
diff changeset
875 CAND_PHI. */
kono
parents:
diff changeset
876 base_type = TREE_TYPE (arg0_base);
kono
parents:
diff changeset
877
kono
parents:
diff changeset
878 c = alloc_cand_and_find_basis (CAND_PHI, phi, arg0_base,
kono
parents:
diff changeset
879 0, integer_one_node, base_type,
kono
parents:
diff changeset
880 sizetype, savings);
kono
parents:
diff changeset
881
kono
parents:
diff changeset
882 /* Add the candidate to the statement-candidate mapping. */
kono
parents:
diff changeset
883 add_cand_for_stmt (phi, c);
kono
parents:
diff changeset
884 }
kono
parents:
diff changeset
885
kono
parents:
diff changeset
886 /* Given PBASE which is a pointer to tree, look up the defining
kono
parents:
diff changeset
887 statement for it and check whether the candidate is in the
kono
parents:
diff changeset
888 form of:
kono
parents:
diff changeset
889
kono
parents:
diff changeset
890 X = B + (1 * S), S is integer constant
kono
parents:
diff changeset
891 X = B + (i * S), S is integer one
kono
parents:
diff changeset
892
kono
parents:
diff changeset
893 If so, set PBASE to the candidate's base_expr and return double
kono
parents:
diff changeset
894 int (i * S).
kono
parents:
diff changeset
895 Otherwise, just return double int zero. */
kono
parents:
diff changeset
896
kono
parents:
diff changeset
897 static widest_int
kono
parents:
diff changeset
898 backtrace_base_for_ref (tree *pbase)
kono
parents:
diff changeset
899 {
kono
parents:
diff changeset
900 tree base_in = *pbase;
kono
parents:
diff changeset
901 slsr_cand_t base_cand;
kono
parents:
diff changeset
902
kono
parents:
diff changeset
903 STRIP_NOPS (base_in);
kono
parents:
diff changeset
904
kono
parents:
diff changeset
905 /* Strip off widening conversion(s) to handle cases where
kono
parents:
diff changeset
906 e.g. 'B' is widened from an 'int' in order to calculate
kono
parents:
diff changeset
907 a 64-bit address. */
kono
parents:
diff changeset
908 if (CONVERT_EXPR_P (base_in)
kono
parents:
diff changeset
909 && legal_cast_p_1 (TREE_TYPE (base_in),
kono
parents:
diff changeset
910 TREE_TYPE (TREE_OPERAND (base_in, 0))))
kono
parents:
diff changeset
911 base_in = get_unwidened (base_in, NULL_TREE);
kono
parents:
diff changeset
912
kono
parents:
diff changeset
913 if (TREE_CODE (base_in) != SSA_NAME)
kono
parents:
diff changeset
914 return 0;
kono
parents:
diff changeset
915
kono
parents:
diff changeset
916 base_cand = base_cand_from_table (base_in);
kono
parents:
diff changeset
917
kono
parents:
diff changeset
918 while (base_cand && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
919 {
kono
parents:
diff changeset
920 if (base_cand->kind == CAND_ADD
kono
parents:
diff changeset
921 && base_cand->index == 1
kono
parents:
diff changeset
922 && TREE_CODE (base_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
923 {
kono
parents:
diff changeset
924 /* X = B + (1 * S), S is integer constant. */
kono
parents:
diff changeset
925 *pbase = base_cand->base_expr;
kono
parents:
diff changeset
926 return wi::to_widest (base_cand->stride);
kono
parents:
diff changeset
927 }
kono
parents:
diff changeset
928 else if (base_cand->kind == CAND_ADD
kono
parents:
diff changeset
929 && TREE_CODE (base_cand->stride) == INTEGER_CST
kono
parents:
diff changeset
930 && integer_onep (base_cand->stride))
kono
parents:
diff changeset
931 {
kono
parents:
diff changeset
932 /* X = B + (i * S), S is integer one. */
kono
parents:
diff changeset
933 *pbase = base_cand->base_expr;
kono
parents:
diff changeset
934 return base_cand->index;
kono
parents:
diff changeset
935 }
kono
parents:
diff changeset
936
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
937 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
938 }
kono
parents:
diff changeset
939
kono
parents:
diff changeset
940 return 0;
kono
parents:
diff changeset
941 }
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943 /* Look for the following pattern:
kono
parents:
diff changeset
944
kono
parents:
diff changeset
945 *PBASE: MEM_REF (T1, C1)
kono
parents:
diff changeset
946
kono
parents:
diff changeset
947 *POFFSET: MULT_EXPR (T2, C3) [C2 is zero]
kono
parents:
diff changeset
948 or
kono
parents:
diff changeset
949 MULT_EXPR (PLUS_EXPR (T2, C2), C3)
kono
parents:
diff changeset
950 or
kono
parents:
diff changeset
951 MULT_EXPR (MINUS_EXPR (T2, -C2), C3)
kono
parents:
diff changeset
952
kono
parents:
diff changeset
953 *PINDEX: C4 * BITS_PER_UNIT
kono
parents:
diff changeset
954
kono
parents:
diff changeset
955 If not present, leave the input values unchanged and return FALSE.
kono
parents:
diff changeset
956 Otherwise, modify the input values as follows and return TRUE:
kono
parents:
diff changeset
957
kono
parents:
diff changeset
958 *PBASE: T1
kono
parents:
diff changeset
959 *POFFSET: MULT_EXPR (T2, C3)
kono
parents:
diff changeset
960 *PINDEX: C1 + (C2 * C3) + C4
kono
parents:
diff changeset
961
kono
parents:
diff changeset
962 When T2 is recorded by a CAND_ADD in the form of (T2' + C5), it
kono
parents:
diff changeset
963 will be further restructured to:
kono
parents:
diff changeset
964
kono
parents:
diff changeset
965 *PBASE: T1
kono
parents:
diff changeset
966 *POFFSET: MULT_EXPR (T2', C3)
kono
parents:
diff changeset
967 *PINDEX: C1 + (C2 * C3) + C4 + (C5 * C3) */
kono
parents:
diff changeset
968
kono
parents:
diff changeset
969 static bool
kono
parents:
diff changeset
970 restructure_reference (tree *pbase, tree *poffset, widest_int *pindex,
kono
parents:
diff changeset
971 tree *ptype)
kono
parents:
diff changeset
972 {
kono
parents:
diff changeset
973 tree base = *pbase, offset = *poffset;
kono
parents:
diff changeset
974 widest_int index = *pindex;
kono
parents:
diff changeset
975 tree mult_op0, t1, t2, type;
kono
parents:
diff changeset
976 widest_int c1, c2, c3, c4, c5;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
977 offset_int mem_offset;
111
kono
parents:
diff changeset
978
kono
parents:
diff changeset
979 if (!base
kono
parents:
diff changeset
980 || !offset
kono
parents:
diff changeset
981 || TREE_CODE (base) != MEM_REF
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
982 || !mem_ref_offset (base).is_constant (&mem_offset)
111
kono
parents:
diff changeset
983 || TREE_CODE (offset) != MULT_EXPR
kono
parents:
diff changeset
984 || TREE_CODE (TREE_OPERAND (offset, 1)) != INTEGER_CST
kono
parents:
diff changeset
985 || wi::umod_floor (index, BITS_PER_UNIT) != 0)
kono
parents:
diff changeset
986 return false;
kono
parents:
diff changeset
987
kono
parents:
diff changeset
988 t1 = TREE_OPERAND (base, 0);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
989 c1 = widest_int::from (mem_offset, SIGNED);
111
kono
parents:
diff changeset
990 type = TREE_TYPE (TREE_OPERAND (base, 1));
kono
parents:
diff changeset
991
kono
parents:
diff changeset
992 mult_op0 = TREE_OPERAND (offset, 0);
kono
parents:
diff changeset
993 c3 = wi::to_widest (TREE_OPERAND (offset, 1));
kono
parents:
diff changeset
994
kono
parents:
diff changeset
995 if (TREE_CODE (mult_op0) == PLUS_EXPR)
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
kono
parents:
diff changeset
998 {
kono
parents:
diff changeset
999 t2 = TREE_OPERAND (mult_op0, 0);
kono
parents:
diff changeset
1000 c2 = wi::to_widest (TREE_OPERAND (mult_op0, 1));
kono
parents:
diff changeset
1001 }
kono
parents:
diff changeset
1002 else
kono
parents:
diff changeset
1003 return false;
kono
parents:
diff changeset
1004
kono
parents:
diff changeset
1005 else if (TREE_CODE (mult_op0) == MINUS_EXPR)
kono
parents:
diff changeset
1006
kono
parents:
diff changeset
1007 if (TREE_CODE (TREE_OPERAND (mult_op0, 1)) == INTEGER_CST)
kono
parents:
diff changeset
1008 {
kono
parents:
diff changeset
1009 t2 = TREE_OPERAND (mult_op0, 0);
kono
parents:
diff changeset
1010 c2 = -wi::to_widest (TREE_OPERAND (mult_op0, 1));
kono
parents:
diff changeset
1011 }
kono
parents:
diff changeset
1012 else
kono
parents:
diff changeset
1013 return false;
kono
parents:
diff changeset
1014
kono
parents:
diff changeset
1015 else
kono
parents:
diff changeset
1016 {
kono
parents:
diff changeset
1017 t2 = mult_op0;
kono
parents:
diff changeset
1018 c2 = 0;
kono
parents:
diff changeset
1019 }
kono
parents:
diff changeset
1020
kono
parents:
diff changeset
1021 c4 = index >> LOG2_BITS_PER_UNIT;
kono
parents:
diff changeset
1022 c5 = backtrace_base_for_ref (&t2);
kono
parents:
diff changeset
1023
kono
parents:
diff changeset
1024 *pbase = t1;
kono
parents:
diff changeset
1025 *poffset = fold_build2 (MULT_EXPR, sizetype, fold_convert (sizetype, t2),
kono
parents:
diff changeset
1026 wide_int_to_tree (sizetype, c3));
kono
parents:
diff changeset
1027 *pindex = c1 + c2 * c3 + c4 + c5 * c3;
kono
parents:
diff changeset
1028 *ptype = type;
kono
parents:
diff changeset
1029
kono
parents:
diff changeset
1030 return true;
kono
parents:
diff changeset
1031 }
kono
parents:
diff changeset
1032
kono
parents:
diff changeset
1033 /* Given GS which contains a data reference, create a CAND_REF entry in
kono
parents:
diff changeset
1034 the candidate table and attempt to find a basis. */
kono
parents:
diff changeset
1035
kono
parents:
diff changeset
1036 static void
kono
parents:
diff changeset
1037 slsr_process_ref (gimple *gs)
kono
parents:
diff changeset
1038 {
kono
parents:
diff changeset
1039 tree ref_expr, base, offset, type;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1040 poly_int64 bitsize, bitpos;
111
kono
parents:
diff changeset
1041 machine_mode mode;
kono
parents:
diff changeset
1042 int unsignedp, reversep, volatilep;
kono
parents:
diff changeset
1043 slsr_cand_t c;
kono
parents:
diff changeset
1044
kono
parents:
diff changeset
1045 if (gimple_vdef (gs))
kono
parents:
diff changeset
1046 ref_expr = gimple_assign_lhs (gs);
kono
parents:
diff changeset
1047 else
kono
parents:
diff changeset
1048 ref_expr = gimple_assign_rhs1 (gs);
kono
parents:
diff changeset
1049
kono
parents:
diff changeset
1050 if (!handled_component_p (ref_expr)
kono
parents:
diff changeset
1051 || TREE_CODE (ref_expr) == BIT_FIELD_REF
kono
parents:
diff changeset
1052 || (TREE_CODE (ref_expr) == COMPONENT_REF
kono
parents:
diff changeset
1053 && DECL_BIT_FIELD (TREE_OPERAND (ref_expr, 1))))
kono
parents:
diff changeset
1054 return;
kono
parents:
diff changeset
1055
kono
parents:
diff changeset
1056 base = get_inner_reference (ref_expr, &bitsize, &bitpos, &offset, &mode,
kono
parents:
diff changeset
1057 &unsignedp, &reversep, &volatilep);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1058 HOST_WIDE_INT cbitpos;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1059 if (reversep || !bitpos.is_constant (&cbitpos))
111
kono
parents:
diff changeset
1060 return;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1061 widest_int index = cbitpos;
111
kono
parents:
diff changeset
1062
kono
parents:
diff changeset
1063 if (!restructure_reference (&base, &offset, &index, &type))
kono
parents:
diff changeset
1064 return;
kono
parents:
diff changeset
1065
kono
parents:
diff changeset
1066 c = alloc_cand_and_find_basis (CAND_REF, gs, base, index, offset,
kono
parents:
diff changeset
1067 type, sizetype, 0);
kono
parents:
diff changeset
1068
kono
parents:
diff changeset
1069 /* Add the candidate to the statement-candidate mapping. */
kono
parents:
diff changeset
1070 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1071 }
kono
parents:
diff changeset
1072
kono
parents:
diff changeset
1073 /* Create a candidate entry for a statement GS, where GS multiplies
kono
parents:
diff changeset
1074 two SSA names BASE_IN and STRIDE_IN. Propagate any known information
kono
parents:
diff changeset
1075 about the two SSA names into the new candidate. Return the new
kono
parents:
diff changeset
1076 candidate. */
kono
parents:
diff changeset
1077
kono
parents:
diff changeset
1078 static slsr_cand_t
kono
parents:
diff changeset
1079 create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
kono
parents:
diff changeset
1080 {
kono
parents:
diff changeset
1081 tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
kono
parents:
diff changeset
1082 tree stype = NULL_TREE;
kono
parents:
diff changeset
1083 widest_int index;
kono
parents:
diff changeset
1084 unsigned savings = 0;
kono
parents:
diff changeset
1085 slsr_cand_t c;
kono
parents:
diff changeset
1086 slsr_cand_t base_cand = base_cand_from_table (base_in);
kono
parents:
diff changeset
1087
kono
parents:
diff changeset
1088 /* Look at all interpretations of the base candidate, if necessary,
kono
parents:
diff changeset
1089 to find information to propagate into this candidate. */
kono
parents:
diff changeset
1090 while (base_cand && !base && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092
kono
parents:
diff changeset
1093 if (base_cand->kind == CAND_MULT && integer_onep (base_cand->stride))
kono
parents:
diff changeset
1094 {
kono
parents:
diff changeset
1095 /* Y = (B + i') * 1
kono
parents:
diff changeset
1096 X = Y * Z
kono
parents:
diff changeset
1097 ================
kono
parents:
diff changeset
1098 X = (B + i') * Z */
kono
parents:
diff changeset
1099 base = base_cand->base_expr;
kono
parents:
diff changeset
1100 index = base_cand->index;
kono
parents:
diff changeset
1101 stride = stride_in;
kono
parents:
diff changeset
1102 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1103 stype = TREE_TYPE (stride_in);
kono
parents:
diff changeset
1104 if (has_single_use (base_in))
kono
parents:
diff changeset
1105 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1106 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1107 }
kono
parents:
diff changeset
1108 else if (base_cand->kind == CAND_ADD
kono
parents:
diff changeset
1109 && TREE_CODE (base_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
1110 {
kono
parents:
diff changeset
1111 /* Y = B + (i' * S), S constant
kono
parents:
diff changeset
1112 X = Y * Z
kono
parents:
diff changeset
1113 ============================
kono
parents:
diff changeset
1114 X = B + ((i' * S) * Z) */
kono
parents:
diff changeset
1115 base = base_cand->base_expr;
kono
parents:
diff changeset
1116 index = base_cand->index * wi::to_widest (base_cand->stride);
kono
parents:
diff changeset
1117 stride = stride_in;
kono
parents:
diff changeset
1118 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1119 stype = TREE_TYPE (stride_in);
kono
parents:
diff changeset
1120 if (has_single_use (base_in))
kono
parents:
diff changeset
1121 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1122 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1123 }
kono
parents:
diff changeset
1124
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1125 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1126 }
kono
parents:
diff changeset
1127
kono
parents:
diff changeset
1128 if (!base)
kono
parents:
diff changeset
1129 {
kono
parents:
diff changeset
1130 /* No interpretations had anything useful to propagate, so
kono
parents:
diff changeset
1131 produce X = (Y + 0) * Z. */
kono
parents:
diff changeset
1132 base = base_in;
kono
parents:
diff changeset
1133 index = 0;
kono
parents:
diff changeset
1134 stride = stride_in;
kono
parents:
diff changeset
1135 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1136 stype = TREE_TYPE (stride_in);
kono
parents:
diff changeset
1137 }
kono
parents:
diff changeset
1138
kono
parents:
diff changeset
1139 c = alloc_cand_and_find_basis (CAND_MULT, gs, base, index, stride,
kono
parents:
diff changeset
1140 ctype, stype, savings);
kono
parents:
diff changeset
1141 return c;
kono
parents:
diff changeset
1142 }
kono
parents:
diff changeset
1143
kono
parents:
diff changeset
1144 /* Create a candidate entry for a statement GS, where GS multiplies
kono
parents:
diff changeset
1145 SSA name BASE_IN by constant STRIDE_IN. Propagate any known
kono
parents:
diff changeset
1146 information about BASE_IN into the new candidate. Return the new
kono
parents:
diff changeset
1147 candidate. */
kono
parents:
diff changeset
1148
kono
parents:
diff changeset
1149 static slsr_cand_t
kono
parents:
diff changeset
1150 create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
kono
parents:
diff changeset
1151 {
kono
parents:
diff changeset
1152 tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
kono
parents:
diff changeset
1153 widest_int index, temp;
kono
parents:
diff changeset
1154 unsigned savings = 0;
kono
parents:
diff changeset
1155 slsr_cand_t c;
kono
parents:
diff changeset
1156 slsr_cand_t base_cand = base_cand_from_table (base_in);
kono
parents:
diff changeset
1157
kono
parents:
diff changeset
1158 /* Look at all interpretations of the base candidate, if necessary,
kono
parents:
diff changeset
1159 to find information to propagate into this candidate. */
kono
parents:
diff changeset
1160 while (base_cand && !base && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1161 {
kono
parents:
diff changeset
1162 if (base_cand->kind == CAND_MULT
kono
parents:
diff changeset
1163 && TREE_CODE (base_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
1164 {
kono
parents:
diff changeset
1165 /* Y = (B + i') * S, S constant
kono
parents:
diff changeset
1166 X = Y * c
kono
parents:
diff changeset
1167 ============================
kono
parents:
diff changeset
1168 X = (B + i') * (S * c) */
kono
parents:
diff changeset
1169 temp = wi::to_widest (base_cand->stride) * wi::to_widest (stride_in);
kono
parents:
diff changeset
1170 if (wi::fits_to_tree_p (temp, TREE_TYPE (stride_in)))
kono
parents:
diff changeset
1171 {
kono
parents:
diff changeset
1172 base = base_cand->base_expr;
kono
parents:
diff changeset
1173 index = base_cand->index;
kono
parents:
diff changeset
1174 stride = wide_int_to_tree (TREE_TYPE (stride_in), temp);
kono
parents:
diff changeset
1175 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1176 if (has_single_use (base_in))
kono
parents:
diff changeset
1177 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1178 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1179 }
kono
parents:
diff changeset
1180 }
kono
parents:
diff changeset
1181 else if (base_cand->kind == CAND_ADD && integer_onep (base_cand->stride))
kono
parents:
diff changeset
1182 {
kono
parents:
diff changeset
1183 /* Y = B + (i' * 1)
kono
parents:
diff changeset
1184 X = Y * c
kono
parents:
diff changeset
1185 ===========================
kono
parents:
diff changeset
1186 X = (B + i') * c */
kono
parents:
diff changeset
1187 base = base_cand->base_expr;
kono
parents:
diff changeset
1188 index = base_cand->index;
kono
parents:
diff changeset
1189 stride = stride_in;
kono
parents:
diff changeset
1190 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1191 if (has_single_use (base_in))
kono
parents:
diff changeset
1192 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1193 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1194 }
kono
parents:
diff changeset
1195 else if (base_cand->kind == CAND_ADD
kono
parents:
diff changeset
1196 && base_cand->index == 1
kono
parents:
diff changeset
1197 && TREE_CODE (base_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
1198 {
kono
parents:
diff changeset
1199 /* Y = B + (1 * S), S constant
kono
parents:
diff changeset
1200 X = Y * c
kono
parents:
diff changeset
1201 ===========================
kono
parents:
diff changeset
1202 X = (B + S) * c */
kono
parents:
diff changeset
1203 base = base_cand->base_expr;
kono
parents:
diff changeset
1204 index = wi::to_widest (base_cand->stride);
kono
parents:
diff changeset
1205 stride = stride_in;
kono
parents:
diff changeset
1206 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1207 if (has_single_use (base_in))
kono
parents:
diff changeset
1208 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1209 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1210 }
kono
parents:
diff changeset
1211
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1212 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1213 }
kono
parents:
diff changeset
1214
kono
parents:
diff changeset
1215 if (!base)
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 /* No interpretations had anything useful to propagate, so
kono
parents:
diff changeset
1218 produce X = (Y + 0) * c. */
kono
parents:
diff changeset
1219 base = base_in;
kono
parents:
diff changeset
1220 index = 0;
kono
parents:
diff changeset
1221 stride = stride_in;
kono
parents:
diff changeset
1222 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1223 }
kono
parents:
diff changeset
1224
kono
parents:
diff changeset
1225 c = alloc_cand_and_find_basis (CAND_MULT, gs, base, index, stride,
kono
parents:
diff changeset
1226 ctype, sizetype, savings);
kono
parents:
diff changeset
1227 return c;
kono
parents:
diff changeset
1228 }
kono
parents:
diff changeset
1229
kono
parents:
diff changeset
1230 /* Given GS which is a multiply of scalar integers, make an appropriate
kono
parents:
diff changeset
1231 entry in the candidate table. If this is a multiply of two SSA names,
kono
parents:
diff changeset
1232 create two CAND_MULT interpretations and attempt to find a basis for
kono
parents:
diff changeset
1233 each of them. Otherwise, create a single CAND_MULT and attempt to
kono
parents:
diff changeset
1234 find a basis. */
kono
parents:
diff changeset
1235
kono
parents:
diff changeset
1236 static void
kono
parents:
diff changeset
1237 slsr_process_mul (gimple *gs, tree rhs1, tree rhs2, bool speed)
kono
parents:
diff changeset
1238 {
kono
parents:
diff changeset
1239 slsr_cand_t c, c2;
kono
parents:
diff changeset
1240
kono
parents:
diff changeset
1241 /* If this is a multiply of an SSA name with itself, it is highly
kono
parents:
diff changeset
1242 unlikely that we will get a strength reduction opportunity, so
kono
parents:
diff changeset
1243 don't record it as a candidate. This simplifies the logic for
kono
parents:
diff changeset
1244 finding a basis, so if this is removed that must be considered. */
kono
parents:
diff changeset
1245 if (rhs1 == rhs2)
kono
parents:
diff changeset
1246 return;
kono
parents:
diff changeset
1247
kono
parents:
diff changeset
1248 if (TREE_CODE (rhs2) == SSA_NAME)
kono
parents:
diff changeset
1249 {
kono
parents:
diff changeset
1250 /* Record an interpretation of this statement in the candidate table
kono
parents:
diff changeset
1251 assuming RHS1 is the base expression and RHS2 is the stride. */
kono
parents:
diff changeset
1252 c = create_mul_ssa_cand (gs, rhs1, rhs2, speed);
kono
parents:
diff changeset
1253
kono
parents:
diff changeset
1254 /* Add the first interpretation to the statement-candidate mapping. */
kono
parents:
diff changeset
1255 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1256
kono
parents:
diff changeset
1257 /* Record another interpretation of this statement assuming RHS1
kono
parents:
diff changeset
1258 is the stride and RHS2 is the base expression. */
kono
parents:
diff changeset
1259 c2 = create_mul_ssa_cand (gs, rhs2, rhs1, speed);
kono
parents:
diff changeset
1260 c->next_interp = c2->cand_num;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1261 c2->first_interp = c->cand_num;
111
kono
parents:
diff changeset
1262 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1263 else if (TREE_CODE (rhs2) == INTEGER_CST && !integer_zerop (rhs2))
111
kono
parents:
diff changeset
1264 {
kono
parents:
diff changeset
1265 /* Record an interpretation for the multiply-immediate. */
kono
parents:
diff changeset
1266 c = create_mul_imm_cand (gs, rhs1, rhs2, speed);
kono
parents:
diff changeset
1267
kono
parents:
diff changeset
1268 /* Add the interpretation to the statement-candidate mapping. */
kono
parents:
diff changeset
1269 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1270 }
kono
parents:
diff changeset
1271 }
kono
parents:
diff changeset
1272
kono
parents:
diff changeset
1273 /* Create a candidate entry for a statement GS, where GS adds two
kono
parents:
diff changeset
1274 SSA names BASE_IN and ADDEND_IN if SUBTRACT_P is false, and
kono
parents:
diff changeset
1275 subtracts ADDEND_IN from BASE_IN otherwise. Propagate any known
kono
parents:
diff changeset
1276 information about the two SSA names into the new candidate.
kono
parents:
diff changeset
1277 Return the new candidate. */
kono
parents:
diff changeset
1278
kono
parents:
diff changeset
1279 static slsr_cand_t
kono
parents:
diff changeset
1280 create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
kono
parents:
diff changeset
1281 bool subtract_p, bool speed)
kono
parents:
diff changeset
1282 {
kono
parents:
diff changeset
1283 tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
kono
parents:
diff changeset
1284 tree stype = NULL_TREE;
kono
parents:
diff changeset
1285 widest_int index;
kono
parents:
diff changeset
1286 unsigned savings = 0;
kono
parents:
diff changeset
1287 slsr_cand_t c;
kono
parents:
diff changeset
1288 slsr_cand_t base_cand = base_cand_from_table (base_in);
kono
parents:
diff changeset
1289 slsr_cand_t addend_cand = base_cand_from_table (addend_in);
kono
parents:
diff changeset
1290
kono
parents:
diff changeset
1291 /* The most useful transformation is a multiply-immediate feeding
kono
parents:
diff changeset
1292 an add or subtract. Look for that first. */
kono
parents:
diff changeset
1293 while (addend_cand && !base && addend_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1294 {
kono
parents:
diff changeset
1295 if (addend_cand->kind == CAND_MULT
kono
parents:
diff changeset
1296 && addend_cand->index == 0
kono
parents:
diff changeset
1297 && TREE_CODE (addend_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
1298 {
kono
parents:
diff changeset
1299 /* Z = (B + 0) * S, S constant
kono
parents:
diff changeset
1300 X = Y +/- Z
kono
parents:
diff changeset
1301 ===========================
kono
parents:
diff changeset
1302 X = Y + ((+/-1 * S) * B) */
kono
parents:
diff changeset
1303 base = base_in;
kono
parents:
diff changeset
1304 index = wi::to_widest (addend_cand->stride);
kono
parents:
diff changeset
1305 if (subtract_p)
kono
parents:
diff changeset
1306 index = -index;
kono
parents:
diff changeset
1307 stride = addend_cand->base_expr;
kono
parents:
diff changeset
1308 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1309 stype = addend_cand->cand_type;
kono
parents:
diff changeset
1310 if (has_single_use (addend_in))
kono
parents:
diff changeset
1311 savings = (addend_cand->dead_savings
kono
parents:
diff changeset
1312 + stmt_cost (addend_cand->cand_stmt, speed));
kono
parents:
diff changeset
1313 }
kono
parents:
diff changeset
1314
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1315 addend_cand = lookup_cand (addend_cand->next_interp);
111
kono
parents:
diff changeset
1316 }
kono
parents:
diff changeset
1317
kono
parents:
diff changeset
1318 while (base_cand && !base && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1319 {
kono
parents:
diff changeset
1320 if (base_cand->kind == CAND_ADD
kono
parents:
diff changeset
1321 && (base_cand->index == 0
kono
parents:
diff changeset
1322 || operand_equal_p (base_cand->stride,
kono
parents:
diff changeset
1323 integer_zero_node, 0)))
kono
parents:
diff changeset
1324 {
kono
parents:
diff changeset
1325 /* Y = B + (i' * S), i' * S = 0
kono
parents:
diff changeset
1326 X = Y +/- Z
kono
parents:
diff changeset
1327 ============================
kono
parents:
diff changeset
1328 X = B + (+/-1 * Z) */
kono
parents:
diff changeset
1329 base = base_cand->base_expr;
kono
parents:
diff changeset
1330 index = subtract_p ? -1 : 1;
kono
parents:
diff changeset
1331 stride = addend_in;
kono
parents:
diff changeset
1332 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1333 stype = (TREE_CODE (addend_in) == INTEGER_CST ? sizetype
kono
parents:
diff changeset
1334 : TREE_TYPE (addend_in));
kono
parents:
diff changeset
1335 if (has_single_use (base_in))
kono
parents:
diff changeset
1336 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1337 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1338 }
kono
parents:
diff changeset
1339 else if (subtract_p)
kono
parents:
diff changeset
1340 {
kono
parents:
diff changeset
1341 slsr_cand_t subtrahend_cand = base_cand_from_table (addend_in);
kono
parents:
diff changeset
1342
kono
parents:
diff changeset
1343 while (subtrahend_cand && !base && subtrahend_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1344 {
kono
parents:
diff changeset
1345 if (subtrahend_cand->kind == CAND_MULT
kono
parents:
diff changeset
1346 && subtrahend_cand->index == 0
kono
parents:
diff changeset
1347 && TREE_CODE (subtrahend_cand->stride) == INTEGER_CST)
kono
parents:
diff changeset
1348 {
kono
parents:
diff changeset
1349 /* Z = (B + 0) * S, S constant
kono
parents:
diff changeset
1350 X = Y - Z
kono
parents:
diff changeset
1351 ===========================
kono
parents:
diff changeset
1352 Value: X = Y + ((-1 * S) * B) */
kono
parents:
diff changeset
1353 base = base_in;
kono
parents:
diff changeset
1354 index = wi::to_widest (subtrahend_cand->stride);
kono
parents:
diff changeset
1355 index = -index;
kono
parents:
diff changeset
1356 stride = subtrahend_cand->base_expr;
kono
parents:
diff changeset
1357 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1358 stype = subtrahend_cand->cand_type;
kono
parents:
diff changeset
1359 if (has_single_use (addend_in))
kono
parents:
diff changeset
1360 savings = (subtrahend_cand->dead_savings
kono
parents:
diff changeset
1361 + stmt_cost (subtrahend_cand->cand_stmt, speed));
kono
parents:
diff changeset
1362 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1363
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1364 subtrahend_cand = lookup_cand (subtrahend_cand->next_interp);
111
kono
parents:
diff changeset
1365 }
kono
parents:
diff changeset
1366 }
kono
parents:
diff changeset
1367
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1368 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1369 }
kono
parents:
diff changeset
1370
kono
parents:
diff changeset
1371 if (!base)
kono
parents:
diff changeset
1372 {
kono
parents:
diff changeset
1373 /* No interpretations had anything useful to propagate, so
kono
parents:
diff changeset
1374 produce X = Y + (1 * Z). */
kono
parents:
diff changeset
1375 base = base_in;
kono
parents:
diff changeset
1376 index = subtract_p ? -1 : 1;
kono
parents:
diff changeset
1377 stride = addend_in;
kono
parents:
diff changeset
1378 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1379 stype = (TREE_CODE (addend_in) == INTEGER_CST ? sizetype
kono
parents:
diff changeset
1380 : TREE_TYPE (addend_in));
kono
parents:
diff changeset
1381 }
kono
parents:
diff changeset
1382
kono
parents:
diff changeset
1383 c = alloc_cand_and_find_basis (CAND_ADD, gs, base, index, stride,
kono
parents:
diff changeset
1384 ctype, stype, savings);
kono
parents:
diff changeset
1385 return c;
kono
parents:
diff changeset
1386 }
kono
parents:
diff changeset
1387
kono
parents:
diff changeset
1388 /* Create a candidate entry for a statement GS, where GS adds SSA
kono
parents:
diff changeset
1389 name BASE_IN to constant INDEX_IN. Propagate any known information
kono
parents:
diff changeset
1390 about BASE_IN into the new candidate. Return the new candidate. */
kono
parents:
diff changeset
1391
kono
parents:
diff changeset
1392 static slsr_cand_t
kono
parents:
diff changeset
1393 create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
kono
parents:
diff changeset
1394 bool speed)
kono
parents:
diff changeset
1395 {
kono
parents:
diff changeset
1396 enum cand_kind kind = CAND_ADD;
kono
parents:
diff changeset
1397 tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
kono
parents:
diff changeset
1398 tree stype = NULL_TREE;
kono
parents:
diff changeset
1399 widest_int index, multiple;
kono
parents:
diff changeset
1400 unsigned savings = 0;
kono
parents:
diff changeset
1401 slsr_cand_t c;
kono
parents:
diff changeset
1402 slsr_cand_t base_cand = base_cand_from_table (base_in);
kono
parents:
diff changeset
1403
kono
parents:
diff changeset
1404 while (base_cand && !base && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1405 {
kono
parents:
diff changeset
1406 signop sign = TYPE_SIGN (TREE_TYPE (base_cand->stride));
kono
parents:
diff changeset
1407
kono
parents:
diff changeset
1408 if (TREE_CODE (base_cand->stride) == INTEGER_CST
kono
parents:
diff changeset
1409 && wi::multiple_of_p (index_in, wi::to_widest (base_cand->stride),
kono
parents:
diff changeset
1410 sign, &multiple))
kono
parents:
diff changeset
1411 {
kono
parents:
diff changeset
1412 /* Y = (B + i') * S, S constant, c = kS for some integer k
kono
parents:
diff changeset
1413 X = Y + c
kono
parents:
diff changeset
1414 ============================
kono
parents:
diff changeset
1415 X = (B + (i'+ k)) * S
kono
parents:
diff changeset
1416 OR
kono
parents:
diff changeset
1417 Y = B + (i' * S), S constant, c = kS for some integer k
kono
parents:
diff changeset
1418 X = Y + c
kono
parents:
diff changeset
1419 ============================
kono
parents:
diff changeset
1420 X = (B + (i'+ k)) * S */
kono
parents:
diff changeset
1421 kind = base_cand->kind;
kono
parents:
diff changeset
1422 base = base_cand->base_expr;
kono
parents:
diff changeset
1423 index = base_cand->index + multiple;
kono
parents:
diff changeset
1424 stride = base_cand->stride;
kono
parents:
diff changeset
1425 ctype = base_cand->cand_type;
kono
parents:
diff changeset
1426 stype = base_cand->stride_type;
kono
parents:
diff changeset
1427 if (has_single_use (base_in))
kono
parents:
diff changeset
1428 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1429 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1430 }
kono
parents:
diff changeset
1431
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1432 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1433 }
kono
parents:
diff changeset
1434
kono
parents:
diff changeset
1435 if (!base)
kono
parents:
diff changeset
1436 {
kono
parents:
diff changeset
1437 /* No interpretations had anything useful to propagate, so
kono
parents:
diff changeset
1438 produce X = Y + (c * 1). */
kono
parents:
diff changeset
1439 kind = CAND_ADD;
kono
parents:
diff changeset
1440 base = base_in;
kono
parents:
diff changeset
1441 index = index_in;
kono
parents:
diff changeset
1442 stride = integer_one_node;
kono
parents:
diff changeset
1443 ctype = TREE_TYPE (base_in);
kono
parents:
diff changeset
1444 stype = sizetype;
kono
parents:
diff changeset
1445 }
kono
parents:
diff changeset
1446
kono
parents:
diff changeset
1447 c = alloc_cand_and_find_basis (kind, gs, base, index, stride,
kono
parents:
diff changeset
1448 ctype, stype, savings);
kono
parents:
diff changeset
1449 return c;
kono
parents:
diff changeset
1450 }
kono
parents:
diff changeset
1451
kono
parents:
diff changeset
1452 /* Given GS which is an add or subtract of scalar integers or pointers,
kono
parents:
diff changeset
1453 make at least one appropriate entry in the candidate table. */
kono
parents:
diff changeset
1454
kono
parents:
diff changeset
1455 static void
kono
parents:
diff changeset
1456 slsr_process_add (gimple *gs, tree rhs1, tree rhs2, bool speed)
kono
parents:
diff changeset
1457 {
kono
parents:
diff changeset
1458 bool subtract_p = gimple_assign_rhs_code (gs) == MINUS_EXPR;
kono
parents:
diff changeset
1459 slsr_cand_t c = NULL, c2;
kono
parents:
diff changeset
1460
kono
parents:
diff changeset
1461 if (TREE_CODE (rhs2) == SSA_NAME)
kono
parents:
diff changeset
1462 {
kono
parents:
diff changeset
1463 /* First record an interpretation assuming RHS1 is the base expression
kono
parents:
diff changeset
1464 and RHS2 is the stride. But it doesn't make sense for the
kono
parents:
diff changeset
1465 stride to be a pointer, so don't record a candidate in that case. */
kono
parents:
diff changeset
1466 if (!POINTER_TYPE_P (TREE_TYPE (rhs2)))
kono
parents:
diff changeset
1467 {
kono
parents:
diff changeset
1468 c = create_add_ssa_cand (gs, rhs1, rhs2, subtract_p, speed);
kono
parents:
diff changeset
1469
kono
parents:
diff changeset
1470 /* Add the first interpretation to the statement-candidate
kono
parents:
diff changeset
1471 mapping. */
kono
parents:
diff changeset
1472 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1473 }
kono
parents:
diff changeset
1474
kono
parents:
diff changeset
1475 /* If the two RHS operands are identical, or this is a subtract,
kono
parents:
diff changeset
1476 we're done. */
kono
parents:
diff changeset
1477 if (operand_equal_p (rhs1, rhs2, 0) || subtract_p)
kono
parents:
diff changeset
1478 return;
kono
parents:
diff changeset
1479
kono
parents:
diff changeset
1480 /* Otherwise, record another interpretation assuming RHS2 is the
kono
parents:
diff changeset
1481 base expression and RHS1 is the stride, again provided that the
kono
parents:
diff changeset
1482 stride is not a pointer. */
kono
parents:
diff changeset
1483 if (!POINTER_TYPE_P (TREE_TYPE (rhs1)))
kono
parents:
diff changeset
1484 {
kono
parents:
diff changeset
1485 c2 = create_add_ssa_cand (gs, rhs2, rhs1, false, speed);
kono
parents:
diff changeset
1486 if (c)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1487 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1488 c->next_interp = c2->cand_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1489 c2->first_interp = c->cand_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1490 }
111
kono
parents:
diff changeset
1491 else
kono
parents:
diff changeset
1492 add_cand_for_stmt (gs, c2);
kono
parents:
diff changeset
1493 }
kono
parents:
diff changeset
1494 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1495 else if (TREE_CODE (rhs2) == INTEGER_CST)
111
kono
parents:
diff changeset
1496 {
kono
parents:
diff changeset
1497 /* Record an interpretation for the add-immediate. */
kono
parents:
diff changeset
1498 widest_int index = wi::to_widest (rhs2);
kono
parents:
diff changeset
1499 if (subtract_p)
kono
parents:
diff changeset
1500 index = -index;
kono
parents:
diff changeset
1501
kono
parents:
diff changeset
1502 c = create_add_imm_cand (gs, rhs1, index, speed);
kono
parents:
diff changeset
1503
kono
parents:
diff changeset
1504 /* Add the interpretation to the statement-candidate mapping. */
kono
parents:
diff changeset
1505 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1506 }
kono
parents:
diff changeset
1507 }
kono
parents:
diff changeset
1508
kono
parents:
diff changeset
1509 /* Given GS which is a negate of a scalar integer, make an appropriate
kono
parents:
diff changeset
1510 entry in the candidate table. A negate is equivalent to a multiply
kono
parents:
diff changeset
1511 by -1. */
kono
parents:
diff changeset
1512
kono
parents:
diff changeset
1513 static void
kono
parents:
diff changeset
1514 slsr_process_neg (gimple *gs, tree rhs1, bool speed)
kono
parents:
diff changeset
1515 {
kono
parents:
diff changeset
1516 /* Record a CAND_MULT interpretation for the multiply by -1. */
kono
parents:
diff changeset
1517 slsr_cand_t c = create_mul_imm_cand (gs, rhs1, integer_minus_one_node, speed);
kono
parents:
diff changeset
1518
kono
parents:
diff changeset
1519 /* Add the interpretation to the statement-candidate mapping. */
kono
parents:
diff changeset
1520 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1521 }
kono
parents:
diff changeset
1522
kono
parents:
diff changeset
1523 /* Help function for legal_cast_p, operating on two trees. Checks
kono
parents:
diff changeset
1524 whether it's allowable to cast from RHS to LHS. See legal_cast_p
kono
parents:
diff changeset
1525 for more details. */
kono
parents:
diff changeset
1526
kono
parents:
diff changeset
1527 static bool
kono
parents:
diff changeset
1528 legal_cast_p_1 (tree lhs_type, tree rhs_type)
kono
parents:
diff changeset
1529 {
kono
parents:
diff changeset
1530 unsigned lhs_size, rhs_size;
kono
parents:
diff changeset
1531 bool lhs_wraps, rhs_wraps;
kono
parents:
diff changeset
1532
kono
parents:
diff changeset
1533 lhs_size = TYPE_PRECISION (lhs_type);
kono
parents:
diff changeset
1534 rhs_size = TYPE_PRECISION (rhs_type);
kono
parents:
diff changeset
1535 lhs_wraps = ANY_INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS (lhs_type);
kono
parents:
diff changeset
1536 rhs_wraps = ANY_INTEGRAL_TYPE_P (rhs_type) && TYPE_OVERFLOW_WRAPS (rhs_type);
kono
parents:
diff changeset
1537
kono
parents:
diff changeset
1538 if (lhs_size < rhs_size
kono
parents:
diff changeset
1539 || (rhs_wraps && !lhs_wraps)
kono
parents:
diff changeset
1540 || (rhs_wraps && lhs_wraps && rhs_size != lhs_size))
kono
parents:
diff changeset
1541 return false;
kono
parents:
diff changeset
1542
kono
parents:
diff changeset
1543 return true;
kono
parents:
diff changeset
1544 }
kono
parents:
diff changeset
1545
kono
parents:
diff changeset
1546 /* Return TRUE if GS is a statement that defines an SSA name from
kono
parents:
diff changeset
1547 a conversion and is legal for us to combine with an add and multiply
kono
parents:
diff changeset
1548 in the candidate table. For example, suppose we have:
kono
parents:
diff changeset
1549
kono
parents:
diff changeset
1550 A = B + i;
kono
parents:
diff changeset
1551 C = (type) A;
kono
parents:
diff changeset
1552 D = C * S;
kono
parents:
diff changeset
1553
kono
parents:
diff changeset
1554 Without the type-cast, we would create a CAND_MULT for D with base B,
kono
parents:
diff changeset
1555 index i, and stride S. We want to record this candidate only if it
kono
parents:
diff changeset
1556 is equivalent to apply the type cast following the multiply:
kono
parents:
diff changeset
1557
kono
parents:
diff changeset
1558 A = B + i;
kono
parents:
diff changeset
1559 E = A * S;
kono
parents:
diff changeset
1560 D = (type) E;
kono
parents:
diff changeset
1561
kono
parents:
diff changeset
1562 We will record the type with the candidate for D. This allows us
kono
parents:
diff changeset
1563 to use a similar previous candidate as a basis. If we have earlier seen
kono
parents:
diff changeset
1564
kono
parents:
diff changeset
1565 A' = B + i';
kono
parents:
diff changeset
1566 C' = (type) A';
kono
parents:
diff changeset
1567 D' = C' * S;
kono
parents:
diff changeset
1568
kono
parents:
diff changeset
1569 we can replace D with
kono
parents:
diff changeset
1570
kono
parents:
diff changeset
1571 D = D' + (i - i') * S;
kono
parents:
diff changeset
1572
kono
parents:
diff changeset
1573 But if moving the type-cast would change semantics, we mustn't do this.
kono
parents:
diff changeset
1574
kono
parents:
diff changeset
1575 This is legitimate for casts from a non-wrapping integral type to
kono
parents:
diff changeset
1576 any integral type of the same or larger size. It is not legitimate
kono
parents:
diff changeset
1577 to convert a wrapping type to a non-wrapping type, or to a wrapping
kono
parents:
diff changeset
1578 type of a different size. I.e., with a wrapping type, we must
kono
parents:
diff changeset
1579 assume that the addition B + i could wrap, in which case performing
kono
parents:
diff changeset
1580 the multiply before or after one of the "illegal" type casts will
kono
parents:
diff changeset
1581 have different semantics. */
kono
parents:
diff changeset
1582
kono
parents:
diff changeset
1583 static bool
kono
parents:
diff changeset
1584 legal_cast_p (gimple *gs, tree rhs)
kono
parents:
diff changeset
1585 {
kono
parents:
diff changeset
1586 if (!is_gimple_assign (gs)
kono
parents:
diff changeset
1587 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (gs)))
kono
parents:
diff changeset
1588 return false;
kono
parents:
diff changeset
1589
kono
parents:
diff changeset
1590 return legal_cast_p_1 (TREE_TYPE (gimple_assign_lhs (gs)), TREE_TYPE (rhs));
kono
parents:
diff changeset
1591 }
kono
parents:
diff changeset
1592
kono
parents:
diff changeset
1593 /* Given GS which is a cast to a scalar integer type, determine whether
kono
parents:
diff changeset
1594 the cast is legal for strength reduction. If so, make at least one
kono
parents:
diff changeset
1595 appropriate entry in the candidate table. */
kono
parents:
diff changeset
1596
kono
parents:
diff changeset
1597 static void
kono
parents:
diff changeset
1598 slsr_process_cast (gimple *gs, tree rhs1, bool speed)
kono
parents:
diff changeset
1599 {
kono
parents:
diff changeset
1600 tree lhs, ctype;
kono
parents:
diff changeset
1601 slsr_cand_t base_cand, c = NULL, c2;
kono
parents:
diff changeset
1602 unsigned savings = 0;
kono
parents:
diff changeset
1603
kono
parents:
diff changeset
1604 if (!legal_cast_p (gs, rhs1))
kono
parents:
diff changeset
1605 return;
kono
parents:
diff changeset
1606
kono
parents:
diff changeset
1607 lhs = gimple_assign_lhs (gs);
kono
parents:
diff changeset
1608 base_cand = base_cand_from_table (rhs1);
kono
parents:
diff changeset
1609 ctype = TREE_TYPE (lhs);
kono
parents:
diff changeset
1610
kono
parents:
diff changeset
1611 if (base_cand && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1612 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1613 slsr_cand_t first_cand = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1614
111
kono
parents:
diff changeset
1615 while (base_cand)
kono
parents:
diff changeset
1616 {
kono
parents:
diff changeset
1617 /* Propagate all data from the base candidate except the type,
kono
parents:
diff changeset
1618 which comes from the cast, and the base candidate's cast,
kono
parents:
diff changeset
1619 which is no longer applicable. */
kono
parents:
diff changeset
1620 if (has_single_use (rhs1))
kono
parents:
diff changeset
1621 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1622 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1623
kono
parents:
diff changeset
1624 c = alloc_cand_and_find_basis (base_cand->kind, gs,
kono
parents:
diff changeset
1625 base_cand->base_expr,
kono
parents:
diff changeset
1626 base_cand->index, base_cand->stride,
kono
parents:
diff changeset
1627 ctype, base_cand->stride_type,
kono
parents:
diff changeset
1628 savings);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1629 if (!first_cand)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1630 first_cand = c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1631
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1632 if (first_cand != c)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1633 c->first_interp = first_cand->cand_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1634
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1635 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1636 }
kono
parents:
diff changeset
1637 }
kono
parents:
diff changeset
1638 else
kono
parents:
diff changeset
1639 {
kono
parents:
diff changeset
1640 /* If nothing is known about the RHS, create fresh CAND_ADD and
kono
parents:
diff changeset
1641 CAND_MULT interpretations:
kono
parents:
diff changeset
1642
kono
parents:
diff changeset
1643 X = Y + (0 * 1)
kono
parents:
diff changeset
1644 X = (Y + 0) * 1
kono
parents:
diff changeset
1645
kono
parents:
diff changeset
1646 The first of these is somewhat arbitrary, but the choice of
kono
parents:
diff changeset
1647 1 for the stride simplifies the logic for propagating casts
kono
parents:
diff changeset
1648 into their uses. */
kono
parents:
diff changeset
1649 c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 0,
kono
parents:
diff changeset
1650 integer_one_node, ctype, sizetype, 0);
kono
parents:
diff changeset
1651 c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 0,
kono
parents:
diff changeset
1652 integer_one_node, ctype, sizetype, 0);
kono
parents:
diff changeset
1653 c->next_interp = c2->cand_num;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1654 c2->first_interp = c->cand_num;
111
kono
parents:
diff changeset
1655 }
kono
parents:
diff changeset
1656
kono
parents:
diff changeset
1657 /* Add the first (or only) interpretation to the statement-candidate
kono
parents:
diff changeset
1658 mapping. */
kono
parents:
diff changeset
1659 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1660 }
kono
parents:
diff changeset
1661
kono
parents:
diff changeset
1662 /* Given GS which is a copy of a scalar integer type, make at least one
kono
parents:
diff changeset
1663 appropriate entry in the candidate table.
kono
parents:
diff changeset
1664
kono
parents:
diff changeset
1665 This interface is included for completeness, but is unnecessary
kono
parents:
diff changeset
1666 if this pass immediately follows a pass that performs copy
kono
parents:
diff changeset
1667 propagation, such as DOM. */
kono
parents:
diff changeset
1668
kono
parents:
diff changeset
1669 static void
kono
parents:
diff changeset
1670 slsr_process_copy (gimple *gs, tree rhs1, bool speed)
kono
parents:
diff changeset
1671 {
kono
parents:
diff changeset
1672 slsr_cand_t base_cand, c = NULL, c2;
kono
parents:
diff changeset
1673 unsigned savings = 0;
kono
parents:
diff changeset
1674
kono
parents:
diff changeset
1675 base_cand = base_cand_from_table (rhs1);
kono
parents:
diff changeset
1676
kono
parents:
diff changeset
1677 if (base_cand && base_cand->kind != CAND_PHI)
kono
parents:
diff changeset
1678 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1679 slsr_cand_t first_cand = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1680
111
kono
parents:
diff changeset
1681 while (base_cand)
kono
parents:
diff changeset
1682 {
kono
parents:
diff changeset
1683 /* Propagate all data from the base candidate. */
kono
parents:
diff changeset
1684 if (has_single_use (rhs1))
kono
parents:
diff changeset
1685 savings = (base_cand->dead_savings
kono
parents:
diff changeset
1686 + stmt_cost (base_cand->cand_stmt, speed));
kono
parents:
diff changeset
1687
kono
parents:
diff changeset
1688 c = alloc_cand_and_find_basis (base_cand->kind, gs,
kono
parents:
diff changeset
1689 base_cand->base_expr,
kono
parents:
diff changeset
1690 base_cand->index, base_cand->stride,
kono
parents:
diff changeset
1691 base_cand->cand_type,
kono
parents:
diff changeset
1692 base_cand->stride_type, savings);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1693 if (!first_cand)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1694 first_cand = c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1695
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1696 if (first_cand != c)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1697 c->first_interp = first_cand->cand_num;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1698
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1699 base_cand = lookup_cand (base_cand->next_interp);
111
kono
parents:
diff changeset
1700 }
kono
parents:
diff changeset
1701 }
kono
parents:
diff changeset
1702 else
kono
parents:
diff changeset
1703 {
kono
parents:
diff changeset
1704 /* If nothing is known about the RHS, create fresh CAND_ADD and
kono
parents:
diff changeset
1705 CAND_MULT interpretations:
kono
parents:
diff changeset
1706
kono
parents:
diff changeset
1707 X = Y + (0 * 1)
kono
parents:
diff changeset
1708 X = (Y + 0) * 1
kono
parents:
diff changeset
1709
kono
parents:
diff changeset
1710 The first of these is somewhat arbitrary, but the choice of
kono
parents:
diff changeset
1711 1 for the stride simplifies the logic for propagating casts
kono
parents:
diff changeset
1712 into their uses. */
kono
parents:
diff changeset
1713 c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 0,
kono
parents:
diff changeset
1714 integer_one_node, TREE_TYPE (rhs1),
kono
parents:
diff changeset
1715 sizetype, 0);
kono
parents:
diff changeset
1716 c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 0,
kono
parents:
diff changeset
1717 integer_one_node, TREE_TYPE (rhs1),
kono
parents:
diff changeset
1718 sizetype, 0);
kono
parents:
diff changeset
1719 c->next_interp = c2->cand_num;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1720 c2->first_interp = c->cand_num;
111
kono
parents:
diff changeset
1721 }
kono
parents:
diff changeset
1722
kono
parents:
diff changeset
1723 /* Add the first (or only) interpretation to the statement-candidate
kono
parents:
diff changeset
1724 mapping. */
kono
parents:
diff changeset
1725 add_cand_for_stmt (gs, c);
kono
parents:
diff changeset
1726 }
kono
parents:
diff changeset
1727
kono
parents:
diff changeset
1728 class find_candidates_dom_walker : public dom_walker
kono
parents:
diff changeset
1729 {
kono
parents:
diff changeset
1730 public:
kono
parents:
diff changeset
1731 find_candidates_dom_walker (cdi_direction direction)
kono
parents:
diff changeset
1732 : dom_walker (direction) {}
kono
parents:
diff changeset
1733 virtual edge before_dom_children (basic_block);
kono
parents:
diff changeset
1734 };
kono
parents:
diff changeset
1735
kono
parents:
diff changeset
1736 /* Find strength-reduction candidates in block BB. */
kono
parents:
diff changeset
1737
kono
parents:
diff changeset
1738 edge
kono
parents:
diff changeset
1739 find_candidates_dom_walker::before_dom_children (basic_block bb)
kono
parents:
diff changeset
1740 {
kono
parents:
diff changeset
1741 bool speed = optimize_bb_for_speed_p (bb);
kono
parents:
diff changeset
1742
kono
parents:
diff changeset
1743 for (gphi_iterator gsi = gsi_start_phis (bb); !gsi_end_p (gsi);
kono
parents:
diff changeset
1744 gsi_next (&gsi))
kono
parents:
diff changeset
1745 slsr_process_phi (gsi.phi (), speed);
kono
parents:
diff changeset
1746
kono
parents:
diff changeset
1747 for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);
kono
parents:
diff changeset
1748 gsi_next (&gsi))
kono
parents:
diff changeset
1749 {
kono
parents:
diff changeset
1750 gimple *gs = gsi_stmt (gsi);
kono
parents:
diff changeset
1751
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1752 if (stmt_could_throw_p (cfun, gs))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1753 continue;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1754
111
kono
parents:
diff changeset
1755 if (gimple_vuse (gs) && gimple_assign_single_p (gs))
kono
parents:
diff changeset
1756 slsr_process_ref (gs);
kono
parents:
diff changeset
1757
kono
parents:
diff changeset
1758 else if (is_gimple_assign (gs)
kono
parents:
diff changeset
1759 && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (gs)))
kono
parents:
diff changeset
1760 || POINTER_TYPE_P (TREE_TYPE (gimple_assign_lhs (gs)))))
kono
parents:
diff changeset
1761 {
kono
parents:
diff changeset
1762 tree rhs1 = NULL_TREE, rhs2 = NULL_TREE;
kono
parents:
diff changeset
1763
kono
parents:
diff changeset
1764 switch (gimple_assign_rhs_code (gs))
kono
parents:
diff changeset
1765 {
kono
parents:
diff changeset
1766 case MULT_EXPR:
kono
parents:
diff changeset
1767 case PLUS_EXPR:
kono
parents:
diff changeset
1768 rhs1 = gimple_assign_rhs1 (gs);
kono
parents:
diff changeset
1769 rhs2 = gimple_assign_rhs2 (gs);
kono
parents:
diff changeset
1770 /* Should never happen, but currently some buggy situations
kono
parents:
diff changeset
1771 in earlier phases put constants in rhs1. */
kono
parents:
diff changeset
1772 if (TREE_CODE (rhs1) != SSA_NAME)
kono
parents:
diff changeset
1773 continue;
kono
parents:
diff changeset
1774 break;
kono
parents:
diff changeset
1775
kono
parents:
diff changeset
1776 /* Possible future opportunity: rhs1 of a ptr+ can be
kono
parents:
diff changeset
1777 an ADDR_EXPR. */
kono
parents:
diff changeset
1778 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
1779 case MINUS_EXPR:
kono
parents:
diff changeset
1780 rhs2 = gimple_assign_rhs2 (gs);
kono
parents:
diff changeset
1781 gcc_fallthrough ();
kono
parents:
diff changeset
1782
kono
parents:
diff changeset
1783 CASE_CONVERT:
kono
parents:
diff changeset
1784 case SSA_NAME:
kono
parents:
diff changeset
1785 case NEGATE_EXPR:
kono
parents:
diff changeset
1786 rhs1 = gimple_assign_rhs1 (gs);
kono
parents:
diff changeset
1787 if (TREE_CODE (rhs1) != SSA_NAME)
kono
parents:
diff changeset
1788 continue;
kono
parents:
diff changeset
1789 break;
kono
parents:
diff changeset
1790
kono
parents:
diff changeset
1791 default:
kono
parents:
diff changeset
1792 ;
kono
parents:
diff changeset
1793 }
kono
parents:
diff changeset
1794
kono
parents:
diff changeset
1795 switch (gimple_assign_rhs_code (gs))
kono
parents:
diff changeset
1796 {
kono
parents:
diff changeset
1797 case MULT_EXPR:
kono
parents:
diff changeset
1798 slsr_process_mul (gs, rhs1, rhs2, speed);
kono
parents:
diff changeset
1799 break;
kono
parents:
diff changeset
1800
kono
parents:
diff changeset
1801 case PLUS_EXPR:
kono
parents:
diff changeset
1802 case POINTER_PLUS_EXPR:
kono
parents:
diff changeset
1803 case MINUS_EXPR:
kono
parents:
diff changeset
1804 slsr_process_add (gs, rhs1, rhs2, speed);
kono
parents:
diff changeset
1805 break;
kono
parents:
diff changeset
1806
kono
parents:
diff changeset
1807 case NEGATE_EXPR:
kono
parents:
diff changeset
1808 slsr_process_neg (gs, rhs1, speed);
kono
parents:
diff changeset
1809 break;
kono
parents:
diff changeset
1810
kono
parents:
diff changeset
1811 CASE_CONVERT:
kono
parents:
diff changeset
1812 slsr_process_cast (gs, rhs1, speed);
kono
parents:
diff changeset
1813 break;
kono
parents:
diff changeset
1814
kono
parents:
diff changeset
1815 case SSA_NAME:
kono
parents:
diff changeset
1816 slsr_process_copy (gs, rhs1, speed);
kono
parents:
diff changeset
1817 break;
kono
parents:
diff changeset
1818
kono
parents:
diff changeset
1819 default:
kono
parents:
diff changeset
1820 ;
kono
parents:
diff changeset
1821 }
kono
parents:
diff changeset
1822 }
kono
parents:
diff changeset
1823 }
kono
parents:
diff changeset
1824 return NULL;
kono
parents:
diff changeset
1825 }
kono
parents:
diff changeset
1826
kono
parents:
diff changeset
1827 /* Dump a candidate for debug. */
kono
parents:
diff changeset
1828
kono
parents:
diff changeset
1829 static void
kono
parents:
diff changeset
1830 dump_candidate (slsr_cand_t c)
kono
parents:
diff changeset
1831 {
kono
parents:
diff changeset
1832 fprintf (dump_file, "%3d [%d] ", c->cand_num,
kono
parents:
diff changeset
1833 gimple_bb (c->cand_stmt)->index);
kono
parents:
diff changeset
1834 print_gimple_stmt (dump_file, c->cand_stmt, 0);
kono
parents:
diff changeset
1835 switch (c->kind)
kono
parents:
diff changeset
1836 {
kono
parents:
diff changeset
1837 case CAND_MULT:
kono
parents:
diff changeset
1838 fputs (" MULT : (", dump_file);
kono
parents:
diff changeset
1839 print_generic_expr (dump_file, c->base_expr);
kono
parents:
diff changeset
1840 fputs (" + ", dump_file);
kono
parents:
diff changeset
1841 print_decs (c->index, dump_file);
kono
parents:
diff changeset
1842 fputs (") * ", dump_file);
kono
parents:
diff changeset
1843 if (TREE_CODE (c->stride) != INTEGER_CST
kono
parents:
diff changeset
1844 && c->stride_type != TREE_TYPE (c->stride))
kono
parents:
diff changeset
1845 {
kono
parents:
diff changeset
1846 fputs ("(", dump_file);
kono
parents:
diff changeset
1847 print_generic_expr (dump_file, c->stride_type);
kono
parents:
diff changeset
1848 fputs (")", dump_file);
kono
parents:
diff changeset
1849 }
kono
parents:
diff changeset
1850 print_generic_expr (dump_file, c->stride);
kono
parents:
diff changeset
1851 fputs (" : ", dump_file);
kono
parents:
diff changeset
1852 break;
kono
parents:
diff changeset
1853 case CAND_ADD:
kono
parents:
diff changeset
1854 fputs (" ADD : ", dump_file);
kono
parents:
diff changeset
1855 print_generic_expr (dump_file, c->base_expr);
kono
parents:
diff changeset
1856 fputs (" + (", dump_file);
kono
parents:
diff changeset
1857 print_decs (c->index, dump_file);
kono
parents:
diff changeset
1858 fputs (" * ", dump_file);
kono
parents:
diff changeset
1859 if (TREE_CODE (c->stride) != INTEGER_CST
kono
parents:
diff changeset
1860 && c->stride_type != TREE_TYPE (c->stride))
kono
parents:
diff changeset
1861 {
kono
parents:
diff changeset
1862 fputs ("(", dump_file);
kono
parents:
diff changeset
1863 print_generic_expr (dump_file, c->stride_type);
kono
parents:
diff changeset
1864 fputs (")", dump_file);
kono
parents:
diff changeset
1865 }
kono
parents:
diff changeset
1866 print_generic_expr (dump_file, c->stride);
kono
parents:
diff changeset
1867 fputs (") : ", dump_file);
kono
parents:
diff changeset
1868 break;
kono
parents:
diff changeset
1869 case CAND_REF:
kono
parents:
diff changeset
1870 fputs (" REF : ", dump_file);
kono
parents:
diff changeset
1871 print_generic_expr (dump_file, c->base_expr);
kono
parents:
diff changeset
1872 fputs (" + (", dump_file);
kono
parents:
diff changeset
1873 print_generic_expr (dump_file, c->stride);
kono
parents:
diff changeset
1874 fputs (") + ", dump_file);
kono
parents:
diff changeset
1875 print_decs (c->index, dump_file);
kono
parents:
diff changeset
1876 fputs (" : ", dump_file);
kono
parents:
diff changeset
1877 break;
kono
parents:
diff changeset
1878 case CAND_PHI:
kono
parents:
diff changeset
1879 fputs (" PHI : ", dump_file);
kono
parents:
diff changeset
1880 print_generic_expr (dump_file, c->base_expr);
kono
parents:
diff changeset
1881 fputs (" + (unknown * ", dump_file);
kono
parents:
diff changeset
1882 print_generic_expr (dump_file, c->stride);
kono
parents:
diff changeset
1883 fputs (") : ", dump_file);
kono
parents:
diff changeset
1884 break;
kono
parents:
diff changeset
1885 default:
kono
parents:
diff changeset
1886 gcc_unreachable ();
kono
parents:
diff changeset
1887 }
kono
parents:
diff changeset
1888 print_generic_expr (dump_file, c->cand_type);
kono
parents:
diff changeset
1889 fprintf (dump_file, "\n basis: %d dependent: %d sibling: %d\n",
kono
parents:
diff changeset
1890 c->basis, c->dependent, c->sibling);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1891 fprintf (dump_file,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1892 " next-interp: %d first-interp: %d dead-savings: %d\n",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1893 c->next_interp, c->first_interp, c->dead_savings);
111
kono
parents:
diff changeset
1894 if (c->def_phi)
kono
parents:
diff changeset
1895 fprintf (dump_file, " phi: %d\n", c->def_phi);
kono
parents:
diff changeset
1896 fputs ("\n", dump_file);
kono
parents:
diff changeset
1897 }
kono
parents:
diff changeset
1898
kono
parents:
diff changeset
1899 /* Dump the candidate vector for debug. */
kono
parents:
diff changeset
1900
kono
parents:
diff changeset
1901 static void
kono
parents:
diff changeset
1902 dump_cand_vec (void)
kono
parents:
diff changeset
1903 {
kono
parents:
diff changeset
1904 unsigned i;
kono
parents:
diff changeset
1905 slsr_cand_t c;
kono
parents:
diff changeset
1906
kono
parents:
diff changeset
1907 fprintf (dump_file, "\nStrength reduction candidate vector:\n\n");
kono
parents:
diff changeset
1908
kono
parents:
diff changeset
1909 FOR_EACH_VEC_ELT (cand_vec, i, c)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1910 if (c != NULL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1911 dump_candidate (c);
111
kono
parents:
diff changeset
1912 }
kono
parents:
diff changeset
1913
kono
parents:
diff changeset
1914 /* Callback used to dump the candidate chains hash table. */
kono
parents:
diff changeset
1915
kono
parents:
diff changeset
1916 int
kono
parents:
diff changeset
1917 ssa_base_cand_dump_callback (cand_chain **slot, void *ignored ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
1918 {
kono
parents:
diff changeset
1919 const_cand_chain_t chain = *slot;
kono
parents:
diff changeset
1920 cand_chain_t p;
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 print_generic_expr (dump_file, chain->base_expr);
kono
parents:
diff changeset
1923 fprintf (dump_file, " -> %d", chain->cand->cand_num);
kono
parents:
diff changeset
1924
kono
parents:
diff changeset
1925 for (p = chain->next; p; p = p->next)
kono
parents:
diff changeset
1926 fprintf (dump_file, " -> %d", p->cand->cand_num);
kono
parents:
diff changeset
1927
kono
parents:
diff changeset
1928 fputs ("\n", dump_file);
kono
parents:
diff changeset
1929 return 1;
kono
parents:
diff changeset
1930 }
kono
parents:
diff changeset
1931
kono
parents:
diff changeset
1932 /* Dump the candidate chains. */
kono
parents:
diff changeset
1933
kono
parents:
diff changeset
1934 static void
kono
parents:
diff changeset
1935 dump_cand_chains (void)
kono
parents:
diff changeset
1936 {
kono
parents:
diff changeset
1937 fprintf (dump_file, "\nStrength reduction candidate chains:\n\n");
kono
parents:
diff changeset
1938 base_cand_map->traverse_noresize <void *, ssa_base_cand_dump_callback>
kono
parents:
diff changeset
1939 (NULL);
kono
parents:
diff changeset
1940 fputs ("\n", dump_file);
kono
parents:
diff changeset
1941 }
kono
parents:
diff changeset
1942
kono
parents:
diff changeset
1943 /* Dump the increment vector for debug. */
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 static void
kono
parents:
diff changeset
1946 dump_incr_vec (void)
kono
parents:
diff changeset
1947 {
kono
parents:
diff changeset
1948 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
1949 {
kono
parents:
diff changeset
1950 unsigned i;
kono
parents:
diff changeset
1951
kono
parents:
diff changeset
1952 fprintf (dump_file, "\nIncrement vector:\n\n");
kono
parents:
diff changeset
1953
kono
parents:
diff changeset
1954 for (i = 0; i < incr_vec_len; i++)
kono
parents:
diff changeset
1955 {
kono
parents:
diff changeset
1956 fprintf (dump_file, "%3d increment: ", i);
kono
parents:
diff changeset
1957 print_decs (incr_vec[i].incr, dump_file);
kono
parents:
diff changeset
1958 fprintf (dump_file, "\n count: %d", incr_vec[i].count);
kono
parents:
diff changeset
1959 fprintf (dump_file, "\n cost: %d", incr_vec[i].cost);
kono
parents:
diff changeset
1960 fputs ("\n initializer: ", dump_file);
kono
parents:
diff changeset
1961 print_generic_expr (dump_file, incr_vec[i].initializer);
kono
parents:
diff changeset
1962 fputs ("\n\n", dump_file);
kono
parents:
diff changeset
1963 }
kono
parents:
diff changeset
1964 }
kono
parents:
diff changeset
1965 }
kono
parents:
diff changeset
1966
kono
parents:
diff changeset
1967 /* Replace *EXPR in candidate C with an equivalent strength-reduced
kono
parents:
diff changeset
1968 data reference. */
kono
parents:
diff changeset
1969
kono
parents:
diff changeset
1970 static void
kono
parents:
diff changeset
1971 replace_ref (tree *expr, slsr_cand_t c)
kono
parents:
diff changeset
1972 {
kono
parents:
diff changeset
1973 tree add_expr, mem_ref, acc_type = TREE_TYPE (*expr);
kono
parents:
diff changeset
1974 unsigned HOST_WIDE_INT misalign;
kono
parents:
diff changeset
1975 unsigned align;
kono
parents:
diff changeset
1976
kono
parents:
diff changeset
1977 /* Ensure the memory reference carries the minimum alignment
kono
parents:
diff changeset
1978 requirement for the data type. See PR58041. */
kono
parents:
diff changeset
1979 get_object_alignment_1 (*expr, &align, &misalign);
kono
parents:
diff changeset
1980 if (misalign != 0)
kono
parents:
diff changeset
1981 align = least_bit_hwi (misalign);
kono
parents:
diff changeset
1982 if (align < TYPE_ALIGN (acc_type))
kono
parents:
diff changeset
1983 acc_type = build_aligned_type (acc_type, align);
kono
parents:
diff changeset
1984
kono
parents:
diff changeset
1985 add_expr = fold_build2 (POINTER_PLUS_EXPR, c->cand_type,
kono
parents:
diff changeset
1986 c->base_expr, c->stride);
kono
parents:
diff changeset
1987 mem_ref = fold_build2 (MEM_REF, acc_type, add_expr,
kono
parents:
diff changeset
1988 wide_int_to_tree (c->cand_type, c->index));
kono
parents:
diff changeset
1989
kono
parents:
diff changeset
1990 /* Gimplify the base addressing expression for the new MEM_REF tree. */
kono
parents:
diff changeset
1991 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
kono
parents:
diff changeset
1992 TREE_OPERAND (mem_ref, 0)
kono
parents:
diff changeset
1993 = force_gimple_operand_gsi (&gsi, TREE_OPERAND (mem_ref, 0),
kono
parents:
diff changeset
1994 /*simple_p=*/true, NULL,
kono
parents:
diff changeset
1995 /*before=*/true, GSI_SAME_STMT);
kono
parents:
diff changeset
1996 copy_ref_info (mem_ref, *expr);
kono
parents:
diff changeset
1997 *expr = mem_ref;
kono
parents:
diff changeset
1998 update_stmt (c->cand_stmt);
kono
parents:
diff changeset
1999 }
kono
parents:
diff changeset
2000
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2001 /* Return true if CAND_REF candidate C is a valid memory reference. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2002
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2003 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2004 valid_mem_ref_cand_p (slsr_cand_t c)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2005 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2006 if (TREE_CODE (TREE_OPERAND (c->stride, 1)) != INTEGER_CST)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2007 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2008
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2009 struct mem_address addr
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2010 = { NULL_TREE, c->base_expr, TREE_OPERAND (c->stride, 0),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2011 TREE_OPERAND (c->stride, 1), wide_int_to_tree (sizetype, c->index) };
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2012
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2013 return
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2014 valid_mem_ref_p (TYPE_MODE (c->cand_type), TYPE_ADDR_SPACE (c->cand_type),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2015 &addr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2016 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2017
111
kono
parents:
diff changeset
2018 /* Replace CAND_REF candidate C, each sibling of candidate C, and each
kono
parents:
diff changeset
2019 dependent of candidate C with an equivalent strength-reduced data
kono
parents:
diff changeset
2020 reference. */
kono
parents:
diff changeset
2021
kono
parents:
diff changeset
2022 static void
kono
parents:
diff changeset
2023 replace_refs (slsr_cand_t c)
kono
parents:
diff changeset
2024 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2025 /* Replacing a chain of only 2 candidates which are valid memory references
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2026 is generally counter-productive because you cannot recoup the additional
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2027 calculation added in front of them. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2028 if (c->basis == 0
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2029 && c->dependent
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2030 && !lookup_cand (c->dependent)->dependent
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2031 && valid_mem_ref_cand_p (c)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2032 && valid_mem_ref_cand_p (lookup_cand (c->dependent)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2033 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2034
111
kono
parents:
diff changeset
2035 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2036 {
kono
parents:
diff changeset
2037 fputs ("Replacing reference: ", dump_file);
kono
parents:
diff changeset
2038 print_gimple_stmt (dump_file, c->cand_stmt, 0);
kono
parents:
diff changeset
2039 }
kono
parents:
diff changeset
2040
kono
parents:
diff changeset
2041 if (gimple_vdef (c->cand_stmt))
kono
parents:
diff changeset
2042 {
kono
parents:
diff changeset
2043 tree *lhs = gimple_assign_lhs_ptr (c->cand_stmt);
kono
parents:
diff changeset
2044 replace_ref (lhs, c);
kono
parents:
diff changeset
2045 }
kono
parents:
diff changeset
2046 else
kono
parents:
diff changeset
2047 {
kono
parents:
diff changeset
2048 tree *rhs = gimple_assign_rhs1_ptr (c->cand_stmt);
kono
parents:
diff changeset
2049 replace_ref (rhs, c);
kono
parents:
diff changeset
2050 }
kono
parents:
diff changeset
2051
kono
parents:
diff changeset
2052 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2053 {
kono
parents:
diff changeset
2054 fputs ("With: ", dump_file);
kono
parents:
diff changeset
2055 print_gimple_stmt (dump_file, c->cand_stmt, 0);
kono
parents:
diff changeset
2056 fputs ("\n", dump_file);
kono
parents:
diff changeset
2057 }
kono
parents:
diff changeset
2058
kono
parents:
diff changeset
2059 if (c->sibling)
kono
parents:
diff changeset
2060 replace_refs (lookup_cand (c->sibling));
kono
parents:
diff changeset
2061
kono
parents:
diff changeset
2062 if (c->dependent)
kono
parents:
diff changeset
2063 replace_refs (lookup_cand (c->dependent));
kono
parents:
diff changeset
2064 }
kono
parents:
diff changeset
2065
kono
parents:
diff changeset
2066 /* Return TRUE if candidate C is dependent upon a PHI. */
kono
parents:
diff changeset
2067
kono
parents:
diff changeset
2068 static bool
kono
parents:
diff changeset
2069 phi_dependent_cand_p (slsr_cand_t c)
kono
parents:
diff changeset
2070 {
kono
parents:
diff changeset
2071 /* A candidate is not necessarily dependent upon a PHI just because
kono
parents:
diff changeset
2072 it has a phi definition for its base name. It may have a basis
kono
parents:
diff changeset
2073 that relies upon the same phi definition, in which case the PHI
kono
parents:
diff changeset
2074 is irrelevant to this candidate. */
kono
parents:
diff changeset
2075 return (c->def_phi
kono
parents:
diff changeset
2076 && c->basis
kono
parents:
diff changeset
2077 && lookup_cand (c->basis)->def_phi != c->def_phi);
kono
parents:
diff changeset
2078 }
kono
parents:
diff changeset
2079
kono
parents:
diff changeset
2080 /* Calculate the increment required for candidate C relative to
kono
parents:
diff changeset
2081 its basis. */
kono
parents:
diff changeset
2082
kono
parents:
diff changeset
2083 static widest_int
kono
parents:
diff changeset
2084 cand_increment (slsr_cand_t c)
kono
parents:
diff changeset
2085 {
kono
parents:
diff changeset
2086 slsr_cand_t basis;
kono
parents:
diff changeset
2087
kono
parents:
diff changeset
2088 /* If the candidate doesn't have a basis, just return its own
kono
parents:
diff changeset
2089 index. This is useful in record_increments to help us find
kono
parents:
diff changeset
2090 an existing initializer. Also, if the candidate's basis is
kono
parents:
diff changeset
2091 hidden by a phi, then its own index will be the increment
kono
parents:
diff changeset
2092 from the newly introduced phi basis. */
kono
parents:
diff changeset
2093 if (!c->basis || phi_dependent_cand_p (c))
kono
parents:
diff changeset
2094 return c->index;
kono
parents:
diff changeset
2095
kono
parents:
diff changeset
2096 basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2097 gcc_assert (operand_equal_p (c->base_expr, basis->base_expr, 0));
kono
parents:
diff changeset
2098 return c->index - basis->index;
kono
parents:
diff changeset
2099 }
kono
parents:
diff changeset
2100
kono
parents:
diff changeset
2101 /* Calculate the increment required for candidate C relative to
kono
parents:
diff changeset
2102 its basis. If we aren't going to generate pointer arithmetic
kono
parents:
diff changeset
2103 for this candidate, return the absolute value of that increment
kono
parents:
diff changeset
2104 instead. */
kono
parents:
diff changeset
2105
kono
parents:
diff changeset
2106 static inline widest_int
kono
parents:
diff changeset
2107 cand_abs_increment (slsr_cand_t c)
kono
parents:
diff changeset
2108 {
kono
parents:
diff changeset
2109 widest_int increment = cand_increment (c);
kono
parents:
diff changeset
2110
kono
parents:
diff changeset
2111 if (!address_arithmetic_p && wi::neg_p (increment))
kono
parents:
diff changeset
2112 increment = -increment;
kono
parents:
diff changeset
2113
kono
parents:
diff changeset
2114 return increment;
kono
parents:
diff changeset
2115 }
kono
parents:
diff changeset
2116
kono
parents:
diff changeset
2117 /* Return TRUE iff candidate C has already been replaced under
kono
parents:
diff changeset
2118 another interpretation. */
kono
parents:
diff changeset
2119
kono
parents:
diff changeset
2120 static inline bool
kono
parents:
diff changeset
2121 cand_already_replaced (slsr_cand_t c)
kono
parents:
diff changeset
2122 {
kono
parents:
diff changeset
2123 return (gimple_bb (c->cand_stmt) == 0);
kono
parents:
diff changeset
2124 }
kono
parents:
diff changeset
2125
kono
parents:
diff changeset
2126 /* Common logic used by replace_unconditional_candidate and
kono
parents:
diff changeset
2127 replace_conditional_candidate. */
kono
parents:
diff changeset
2128
kono
parents:
diff changeset
2129 static void
kono
parents:
diff changeset
2130 replace_mult_candidate (slsr_cand_t c, tree basis_name, widest_int bump)
kono
parents:
diff changeset
2131 {
kono
parents:
diff changeset
2132 tree target_type = TREE_TYPE (gimple_assign_lhs (c->cand_stmt));
kono
parents:
diff changeset
2133 enum tree_code cand_code = gimple_assign_rhs_code (c->cand_stmt);
kono
parents:
diff changeset
2134
kono
parents:
diff changeset
2135 /* It is not useful to replace casts, copies, negates, or adds of
kono
parents:
diff changeset
2136 an SSA name and a constant. */
kono
parents:
diff changeset
2137 if (cand_code == SSA_NAME
kono
parents:
diff changeset
2138 || CONVERT_EXPR_CODE_P (cand_code)
kono
parents:
diff changeset
2139 || cand_code == PLUS_EXPR
kono
parents:
diff changeset
2140 || cand_code == POINTER_PLUS_EXPR
kono
parents:
diff changeset
2141 || cand_code == MINUS_EXPR
kono
parents:
diff changeset
2142 || cand_code == NEGATE_EXPR)
kono
parents:
diff changeset
2143 return;
kono
parents:
diff changeset
2144
kono
parents:
diff changeset
2145 enum tree_code code = PLUS_EXPR;
kono
parents:
diff changeset
2146 tree bump_tree;
kono
parents:
diff changeset
2147 gimple *stmt_to_print = NULL;
kono
parents:
diff changeset
2148
kono
parents:
diff changeset
2149 if (wi::neg_p (bump))
kono
parents:
diff changeset
2150 {
kono
parents:
diff changeset
2151 code = MINUS_EXPR;
kono
parents:
diff changeset
2152 bump = -bump;
kono
parents:
diff changeset
2153 }
kono
parents:
diff changeset
2154
kono
parents:
diff changeset
2155 /* It is possible that the resulting bump doesn't fit in target_type.
kono
parents:
diff changeset
2156 Abandon the replacement in this case. This does not affect
kono
parents:
diff changeset
2157 siblings or dependents of C. */
kono
parents:
diff changeset
2158 if (bump != wi::ext (bump, TYPE_PRECISION (target_type),
kono
parents:
diff changeset
2159 TYPE_SIGN (target_type)))
kono
parents:
diff changeset
2160 return;
kono
parents:
diff changeset
2161
kono
parents:
diff changeset
2162 bump_tree = wide_int_to_tree (target_type, bump);
kono
parents:
diff changeset
2163
kono
parents:
diff changeset
2164 /* If the basis name and the candidate's LHS have incompatible types,
kono
parents:
diff changeset
2165 introduce a cast. */
kono
parents:
diff changeset
2166 if (!useless_type_conversion_p (target_type, TREE_TYPE (basis_name)))
kono
parents:
diff changeset
2167 basis_name = introduce_cast_before_cand (c, target_type, basis_name);
kono
parents:
diff changeset
2168
kono
parents:
diff changeset
2169 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2170 {
kono
parents:
diff changeset
2171 fputs ("Replacing: ", dump_file);
kono
parents:
diff changeset
2172 print_gimple_stmt (dump_file, c->cand_stmt, 0);
kono
parents:
diff changeset
2173 }
kono
parents:
diff changeset
2174
kono
parents:
diff changeset
2175 if (bump == 0)
kono
parents:
diff changeset
2176 {
kono
parents:
diff changeset
2177 tree lhs = gimple_assign_lhs (c->cand_stmt);
kono
parents:
diff changeset
2178 gassign *copy_stmt = gimple_build_assign (lhs, basis_name);
kono
parents:
diff changeset
2179 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2180 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
2181 gimple_set_location (copy_stmt, gimple_location (c->cand_stmt));
kono
parents:
diff changeset
2182 gsi_replace (&gsi, copy_stmt, false);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2183 while (cc)
111
kono
parents:
diff changeset
2184 {
kono
parents:
diff changeset
2185 cc->cand_stmt = copy_stmt;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2186 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
2187 }
kono
parents:
diff changeset
2188 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2189 stmt_to_print = copy_stmt;
kono
parents:
diff changeset
2190 }
kono
parents:
diff changeset
2191 else
kono
parents:
diff changeset
2192 {
kono
parents:
diff changeset
2193 tree rhs1, rhs2;
kono
parents:
diff changeset
2194 if (cand_code != NEGATE_EXPR) {
kono
parents:
diff changeset
2195 rhs1 = gimple_assign_rhs1 (c->cand_stmt);
kono
parents:
diff changeset
2196 rhs2 = gimple_assign_rhs2 (c->cand_stmt);
kono
parents:
diff changeset
2197 }
kono
parents:
diff changeset
2198 if (cand_code != NEGATE_EXPR
kono
parents:
diff changeset
2199 && ((operand_equal_p (rhs1, basis_name, 0)
kono
parents:
diff changeset
2200 && operand_equal_p (rhs2, bump_tree, 0))
kono
parents:
diff changeset
2201 || (operand_equal_p (rhs1, bump_tree, 0)
kono
parents:
diff changeset
2202 && operand_equal_p (rhs2, basis_name, 0))))
kono
parents:
diff changeset
2203 {
kono
parents:
diff changeset
2204 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2205 {
kono
parents:
diff changeset
2206 fputs ("(duplicate, not actually replacing)", dump_file);
kono
parents:
diff changeset
2207 stmt_to_print = c->cand_stmt;
kono
parents:
diff changeset
2208 }
kono
parents:
diff changeset
2209 }
kono
parents:
diff changeset
2210 else
kono
parents:
diff changeset
2211 {
kono
parents:
diff changeset
2212 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2213 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
2214 gimple_assign_set_rhs_with_ops (&gsi, code, basis_name, bump_tree);
kono
parents:
diff changeset
2215 update_stmt (gsi_stmt (gsi));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2216 while (cc)
111
kono
parents:
diff changeset
2217 {
kono
parents:
diff changeset
2218 cc->cand_stmt = gsi_stmt (gsi);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2219 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
2220 }
kono
parents:
diff changeset
2221 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2222 stmt_to_print = gsi_stmt (gsi);
kono
parents:
diff changeset
2223 }
kono
parents:
diff changeset
2224 }
kono
parents:
diff changeset
2225
kono
parents:
diff changeset
2226 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2227 {
kono
parents:
diff changeset
2228 fputs ("With: ", dump_file);
kono
parents:
diff changeset
2229 print_gimple_stmt (dump_file, stmt_to_print, 0);
kono
parents:
diff changeset
2230 fputs ("\n", dump_file);
kono
parents:
diff changeset
2231 }
kono
parents:
diff changeset
2232 }
kono
parents:
diff changeset
2233
kono
parents:
diff changeset
2234 /* Replace candidate C with an add or subtract. Note that we only
kono
parents:
diff changeset
2235 operate on CAND_MULTs with known strides, so we will never generate
kono
parents:
diff changeset
2236 a POINTER_PLUS_EXPR. Each candidate X = (B + i) * S is replaced by
kono
parents:
diff changeset
2237 X = Y + ((i - i') * S), as described in the module commentary. The
kono
parents:
diff changeset
2238 folded value ((i - i') * S) is referred to here as the "bump." */
kono
parents:
diff changeset
2239
kono
parents:
diff changeset
2240 static void
kono
parents:
diff changeset
2241 replace_unconditional_candidate (slsr_cand_t c)
kono
parents:
diff changeset
2242 {
kono
parents:
diff changeset
2243 slsr_cand_t basis;
kono
parents:
diff changeset
2244
kono
parents:
diff changeset
2245 if (cand_already_replaced (c))
kono
parents:
diff changeset
2246 return;
kono
parents:
diff changeset
2247
kono
parents:
diff changeset
2248 basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2249 widest_int bump = cand_increment (c) * wi::to_widest (c->stride);
kono
parents:
diff changeset
2250
kono
parents:
diff changeset
2251 replace_mult_candidate (c, gimple_assign_lhs (basis->cand_stmt), bump);
kono
parents:
diff changeset
2252 }
kono
parents:
diff changeset
2253
kono
parents:
diff changeset
2254 /* Return the index in the increment vector of the given INCREMENT,
kono
parents:
diff changeset
2255 or -1 if not found. The latter can occur if more than
kono
parents:
diff changeset
2256 MAX_INCR_VEC_LEN increments have been found. */
kono
parents:
diff changeset
2257
kono
parents:
diff changeset
2258 static inline int
kono
parents:
diff changeset
2259 incr_vec_index (const widest_int &increment)
kono
parents:
diff changeset
2260 {
kono
parents:
diff changeset
2261 unsigned i;
kono
parents:
diff changeset
2262
kono
parents:
diff changeset
2263 for (i = 0; i < incr_vec_len && increment != incr_vec[i].incr; i++)
kono
parents:
diff changeset
2264 ;
kono
parents:
diff changeset
2265
kono
parents:
diff changeset
2266 if (i < incr_vec_len)
kono
parents:
diff changeset
2267 return i;
kono
parents:
diff changeset
2268 else
kono
parents:
diff changeset
2269 return -1;
kono
parents:
diff changeset
2270 }
kono
parents:
diff changeset
2271
kono
parents:
diff changeset
2272 /* Create a new statement along edge E to add BASIS_NAME to the product
kono
parents:
diff changeset
2273 of INCREMENT and the stride of candidate C. Create and return a new
kono
parents:
diff changeset
2274 SSA name from *VAR to be used as the LHS of the new statement.
kono
parents:
diff changeset
2275 KNOWN_STRIDE is true iff C's stride is a constant. */
kono
parents:
diff changeset
2276
kono
parents:
diff changeset
2277 static tree
kono
parents:
diff changeset
2278 create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
kono
parents:
diff changeset
2279 widest_int increment, edge e, location_t loc,
kono
parents:
diff changeset
2280 bool known_stride)
kono
parents:
diff changeset
2281 {
kono
parents:
diff changeset
2282 tree lhs, basis_type;
kono
parents:
diff changeset
2283 gassign *new_stmt, *cast_stmt = NULL;
kono
parents:
diff changeset
2284
kono
parents:
diff changeset
2285 /* If the add candidate along this incoming edge has the same
kono
parents:
diff changeset
2286 index as C's hidden basis, the hidden basis represents this
kono
parents:
diff changeset
2287 edge correctly. */
kono
parents:
diff changeset
2288 if (increment == 0)
kono
parents:
diff changeset
2289 return basis_name;
kono
parents:
diff changeset
2290
kono
parents:
diff changeset
2291 basis_type = TREE_TYPE (basis_name);
kono
parents:
diff changeset
2292 lhs = make_temp_ssa_name (basis_type, NULL, "slsr");
kono
parents:
diff changeset
2293
kono
parents:
diff changeset
2294 /* Occasionally people convert integers to pointers without a
kono
parents:
diff changeset
2295 cast, leading us into trouble if we aren't careful. */
kono
parents:
diff changeset
2296 enum tree_code plus_code
kono
parents:
diff changeset
2297 = POINTER_TYPE_P (basis_type) ? POINTER_PLUS_EXPR : PLUS_EXPR;
kono
parents:
diff changeset
2298
kono
parents:
diff changeset
2299 if (known_stride)
kono
parents:
diff changeset
2300 {
kono
parents:
diff changeset
2301 tree bump_tree;
kono
parents:
diff changeset
2302 enum tree_code code = plus_code;
kono
parents:
diff changeset
2303 widest_int bump = increment * wi::to_widest (c->stride);
kono
parents:
diff changeset
2304 if (wi::neg_p (bump) && !POINTER_TYPE_P (basis_type))
kono
parents:
diff changeset
2305 {
kono
parents:
diff changeset
2306 code = MINUS_EXPR;
kono
parents:
diff changeset
2307 bump = -bump;
kono
parents:
diff changeset
2308 }
kono
parents:
diff changeset
2309
kono
parents:
diff changeset
2310 tree stride_type = POINTER_TYPE_P (basis_type) ? sizetype : basis_type;
kono
parents:
diff changeset
2311 bump_tree = wide_int_to_tree (stride_type, bump);
kono
parents:
diff changeset
2312 new_stmt = gimple_build_assign (lhs, code, basis_name, bump_tree);
kono
parents:
diff changeset
2313 }
kono
parents:
diff changeset
2314 else
kono
parents:
diff changeset
2315 {
kono
parents:
diff changeset
2316 int i;
kono
parents:
diff changeset
2317 bool negate_incr = !POINTER_TYPE_P (basis_type) && wi::neg_p (increment);
kono
parents:
diff changeset
2318 i = incr_vec_index (negate_incr ? -increment : increment);
kono
parents:
diff changeset
2319 gcc_assert (i >= 0);
kono
parents:
diff changeset
2320
kono
parents:
diff changeset
2321 if (incr_vec[i].initializer)
kono
parents:
diff changeset
2322 {
kono
parents:
diff changeset
2323 enum tree_code code = negate_incr ? MINUS_EXPR : plus_code;
kono
parents:
diff changeset
2324 new_stmt = gimple_build_assign (lhs, code, basis_name,
kono
parents:
diff changeset
2325 incr_vec[i].initializer);
kono
parents:
diff changeset
2326 }
kono
parents:
diff changeset
2327 else {
kono
parents:
diff changeset
2328 tree stride;
kono
parents:
diff changeset
2329
kono
parents:
diff changeset
2330 if (!types_compatible_p (TREE_TYPE (c->stride), c->stride_type))
kono
parents:
diff changeset
2331 {
kono
parents:
diff changeset
2332 tree cast_stride = make_temp_ssa_name (c->stride_type, NULL,
kono
parents:
diff changeset
2333 "slsr");
kono
parents:
diff changeset
2334 cast_stmt = gimple_build_assign (cast_stride, NOP_EXPR,
kono
parents:
diff changeset
2335 c->stride);
kono
parents:
diff changeset
2336 stride = cast_stride;
kono
parents:
diff changeset
2337 }
kono
parents:
diff changeset
2338 else
kono
parents:
diff changeset
2339 stride = c->stride;
kono
parents:
diff changeset
2340
kono
parents:
diff changeset
2341 if (increment == 1)
kono
parents:
diff changeset
2342 new_stmt = gimple_build_assign (lhs, plus_code, basis_name, stride);
kono
parents:
diff changeset
2343 else if (increment == -1)
kono
parents:
diff changeset
2344 new_stmt = gimple_build_assign (lhs, MINUS_EXPR, basis_name, stride);
kono
parents:
diff changeset
2345 else
kono
parents:
diff changeset
2346 gcc_unreachable ();
kono
parents:
diff changeset
2347 }
kono
parents:
diff changeset
2348 }
kono
parents:
diff changeset
2349
kono
parents:
diff changeset
2350 if (cast_stmt)
kono
parents:
diff changeset
2351 {
kono
parents:
diff changeset
2352 gimple_set_location (cast_stmt, loc);
kono
parents:
diff changeset
2353 gsi_insert_on_edge (e, cast_stmt);
kono
parents:
diff changeset
2354 }
kono
parents:
diff changeset
2355
kono
parents:
diff changeset
2356 gimple_set_location (new_stmt, loc);
kono
parents:
diff changeset
2357 gsi_insert_on_edge (e, new_stmt);
kono
parents:
diff changeset
2358
kono
parents:
diff changeset
2359 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2360 {
kono
parents:
diff changeset
2361 if (cast_stmt)
kono
parents:
diff changeset
2362 {
kono
parents:
diff changeset
2363 fprintf (dump_file, "Inserting cast on edge %d->%d: ",
kono
parents:
diff changeset
2364 e->src->index, e->dest->index);
kono
parents:
diff changeset
2365 print_gimple_stmt (dump_file, cast_stmt, 0);
kono
parents:
diff changeset
2366 }
kono
parents:
diff changeset
2367 fprintf (dump_file, "Inserting on edge %d->%d: ", e->src->index,
kono
parents:
diff changeset
2368 e->dest->index);
kono
parents:
diff changeset
2369 print_gimple_stmt (dump_file, new_stmt, 0);
kono
parents:
diff changeset
2370 }
kono
parents:
diff changeset
2371
kono
parents:
diff changeset
2372 return lhs;
kono
parents:
diff changeset
2373 }
kono
parents:
diff changeset
2374
kono
parents:
diff changeset
2375 /* Clear the visited field for a tree of PHI candidates. */
kono
parents:
diff changeset
2376
kono
parents:
diff changeset
2377 static void
kono
parents:
diff changeset
2378 clear_visited (gphi *phi)
kono
parents:
diff changeset
2379 {
kono
parents:
diff changeset
2380 unsigned i;
kono
parents:
diff changeset
2381 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
2382
kono
parents:
diff changeset
2383 if (phi_cand->visited)
kono
parents:
diff changeset
2384 {
kono
parents:
diff changeset
2385 phi_cand->visited = 0;
kono
parents:
diff changeset
2386
kono
parents:
diff changeset
2387 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
2388 {
kono
parents:
diff changeset
2389 tree arg = gimple_phi_arg_def (phi, i);
kono
parents:
diff changeset
2390 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
kono
parents:
diff changeset
2391 if (gimple_code (arg_def) == GIMPLE_PHI)
kono
parents:
diff changeset
2392 clear_visited (as_a <gphi *> (arg_def));
kono
parents:
diff changeset
2393 }
kono
parents:
diff changeset
2394 }
kono
parents:
diff changeset
2395 }
kono
parents:
diff changeset
2396
kono
parents:
diff changeset
2397 /* Recursive helper function for create_phi_basis. */
kono
parents:
diff changeset
2398
kono
parents:
diff changeset
2399 static tree
kono
parents:
diff changeset
2400 create_phi_basis_1 (slsr_cand_t c, gimple *from_phi, tree basis_name,
kono
parents:
diff changeset
2401 location_t loc, bool known_stride)
kono
parents:
diff changeset
2402 {
kono
parents:
diff changeset
2403 int i;
kono
parents:
diff changeset
2404 tree name, phi_arg;
kono
parents:
diff changeset
2405 gphi *phi;
kono
parents:
diff changeset
2406 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2407 int nargs = gimple_phi_num_args (from_phi);
kono
parents:
diff changeset
2408 basic_block phi_bb = gimple_bb (from_phi);
kono
parents:
diff changeset
2409 slsr_cand_t phi_cand = *stmt_cand_map->get (from_phi);
kono
parents:
diff changeset
2410 auto_vec<tree> phi_args (nargs);
kono
parents:
diff changeset
2411
kono
parents:
diff changeset
2412 if (phi_cand->visited)
kono
parents:
diff changeset
2413 return phi_cand->cached_basis;
kono
parents:
diff changeset
2414 phi_cand->visited = 1;
kono
parents:
diff changeset
2415
kono
parents:
diff changeset
2416 /* Process each argument of the existing phi that represents
kono
parents:
diff changeset
2417 conditionally-executed add candidates. */
kono
parents:
diff changeset
2418 for (i = 0; i < nargs; i++)
kono
parents:
diff changeset
2419 {
kono
parents:
diff changeset
2420 edge e = (*phi_bb->preds)[i];
kono
parents:
diff changeset
2421 tree arg = gimple_phi_arg_def (from_phi, i);
kono
parents:
diff changeset
2422 tree feeding_def;
kono
parents:
diff changeset
2423
kono
parents:
diff changeset
2424 /* If the phi argument is the base name of the CAND_PHI, then
kono
parents:
diff changeset
2425 this incoming arc should use the hidden basis. */
kono
parents:
diff changeset
2426 if (operand_equal_p (arg, phi_cand->base_expr, 0))
kono
parents:
diff changeset
2427 if (basis->index == 0)
kono
parents:
diff changeset
2428 feeding_def = gimple_assign_lhs (basis->cand_stmt);
kono
parents:
diff changeset
2429 else
kono
parents:
diff changeset
2430 {
kono
parents:
diff changeset
2431 widest_int incr = -basis->index;
kono
parents:
diff changeset
2432 feeding_def = create_add_on_incoming_edge (c, basis_name, incr,
kono
parents:
diff changeset
2433 e, loc, known_stride);
kono
parents:
diff changeset
2434 }
kono
parents:
diff changeset
2435 else
kono
parents:
diff changeset
2436 {
kono
parents:
diff changeset
2437 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
kono
parents:
diff changeset
2438
kono
parents:
diff changeset
2439 /* If there is another phi along this incoming edge, we must
kono
parents:
diff changeset
2440 process it in the same fashion to ensure that all basis
kono
parents:
diff changeset
2441 adjustments are made along its incoming edges. */
kono
parents:
diff changeset
2442 if (gimple_code (arg_def) == GIMPLE_PHI)
kono
parents:
diff changeset
2443 feeding_def = create_phi_basis_1 (c, arg_def, basis_name,
kono
parents:
diff changeset
2444 loc, known_stride);
kono
parents:
diff changeset
2445 else
kono
parents:
diff changeset
2446 {
kono
parents:
diff changeset
2447 slsr_cand_t arg_cand = base_cand_from_table (arg);
kono
parents:
diff changeset
2448 widest_int diff = arg_cand->index - basis->index;
kono
parents:
diff changeset
2449 feeding_def = create_add_on_incoming_edge (c, basis_name, diff,
kono
parents:
diff changeset
2450 e, loc, known_stride);
kono
parents:
diff changeset
2451 }
kono
parents:
diff changeset
2452 }
kono
parents:
diff changeset
2453
kono
parents:
diff changeset
2454 /* Because of recursion, we need to save the arguments in a vector
kono
parents:
diff changeset
2455 so we can create the PHI statement all at once. Otherwise the
kono
parents:
diff changeset
2456 storage for the half-created PHI can be reclaimed. */
kono
parents:
diff changeset
2457 phi_args.safe_push (feeding_def);
kono
parents:
diff changeset
2458 }
kono
parents:
diff changeset
2459
kono
parents:
diff changeset
2460 /* Create the new phi basis. */
kono
parents:
diff changeset
2461 name = make_temp_ssa_name (TREE_TYPE (basis_name), NULL, "slsr");
kono
parents:
diff changeset
2462 phi = create_phi_node (name, phi_bb);
kono
parents:
diff changeset
2463 SSA_NAME_DEF_STMT (name) = phi;
kono
parents:
diff changeset
2464
kono
parents:
diff changeset
2465 FOR_EACH_VEC_ELT (phi_args, i, phi_arg)
kono
parents:
diff changeset
2466 {
kono
parents:
diff changeset
2467 edge e = (*phi_bb->preds)[i];
kono
parents:
diff changeset
2468 add_phi_arg (phi, phi_arg, e, loc);
kono
parents:
diff changeset
2469 }
kono
parents:
diff changeset
2470
kono
parents:
diff changeset
2471 update_stmt (phi);
kono
parents:
diff changeset
2472
kono
parents:
diff changeset
2473 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2474 {
kono
parents:
diff changeset
2475 fputs ("Introducing new phi basis: ", dump_file);
kono
parents:
diff changeset
2476 print_gimple_stmt (dump_file, phi, 0);
kono
parents:
diff changeset
2477 }
kono
parents:
diff changeset
2478
kono
parents:
diff changeset
2479 phi_cand->cached_basis = name;
kono
parents:
diff changeset
2480 return name;
kono
parents:
diff changeset
2481 }
kono
parents:
diff changeset
2482
kono
parents:
diff changeset
2483 /* Given a candidate C with BASIS_NAME being the LHS of C's basis which
kono
parents:
diff changeset
2484 is hidden by the phi node FROM_PHI, create a new phi node in the same
kono
parents:
diff changeset
2485 block as FROM_PHI. The new phi is suitable for use as a basis by C,
kono
parents:
diff changeset
2486 with its phi arguments representing conditional adjustments to the
kono
parents:
diff changeset
2487 hidden basis along conditional incoming paths. Those adjustments are
kono
parents:
diff changeset
2488 made by creating add statements (and sometimes recursively creating
kono
parents:
diff changeset
2489 phis) along those incoming paths. LOC is the location to attach to
kono
parents:
diff changeset
2490 the introduced statements. KNOWN_STRIDE is true iff C's stride is a
kono
parents:
diff changeset
2491 constant. */
kono
parents:
diff changeset
2492
kono
parents:
diff changeset
2493 static tree
kono
parents:
diff changeset
2494 create_phi_basis (slsr_cand_t c, gimple *from_phi, tree basis_name,
kono
parents:
diff changeset
2495 location_t loc, bool known_stride)
kono
parents:
diff changeset
2496 {
kono
parents:
diff changeset
2497 tree retval = create_phi_basis_1 (c, from_phi, basis_name, loc,
kono
parents:
diff changeset
2498 known_stride);
kono
parents:
diff changeset
2499 gcc_assert (retval);
kono
parents:
diff changeset
2500 clear_visited (as_a <gphi *> (from_phi));
kono
parents:
diff changeset
2501 return retval;
kono
parents:
diff changeset
2502 }
kono
parents:
diff changeset
2503
kono
parents:
diff changeset
2504 /* Given a candidate C whose basis is hidden by at least one intervening
kono
parents:
diff changeset
2505 phi, introduce a matching number of new phis to represent its basis
kono
parents:
diff changeset
2506 adjusted by conditional increments along possible incoming paths. Then
kono
parents:
diff changeset
2507 replace C as though it were an unconditional candidate, using the new
kono
parents:
diff changeset
2508 basis. */
kono
parents:
diff changeset
2509
kono
parents:
diff changeset
2510 static void
kono
parents:
diff changeset
2511 replace_conditional_candidate (slsr_cand_t c)
kono
parents:
diff changeset
2512 {
kono
parents:
diff changeset
2513 tree basis_name, name;
kono
parents:
diff changeset
2514 slsr_cand_t basis;
kono
parents:
diff changeset
2515 location_t loc;
kono
parents:
diff changeset
2516
kono
parents:
diff changeset
2517 /* Look up the LHS SSA name from C's basis. This will be the
kono
parents:
diff changeset
2518 RHS1 of the adds we will introduce to create new phi arguments. */
kono
parents:
diff changeset
2519 basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2520 basis_name = gimple_assign_lhs (basis->cand_stmt);
kono
parents:
diff changeset
2521
kono
parents:
diff changeset
2522 /* Create a new phi statement which will represent C's true basis
kono
parents:
diff changeset
2523 after the transformation is complete. */
kono
parents:
diff changeset
2524 loc = gimple_location (c->cand_stmt);
kono
parents:
diff changeset
2525 name = create_phi_basis (c, lookup_cand (c->def_phi)->cand_stmt,
kono
parents:
diff changeset
2526 basis_name, loc, KNOWN_STRIDE);
kono
parents:
diff changeset
2527
kono
parents:
diff changeset
2528 /* Replace C with an add of the new basis phi and a constant. */
kono
parents:
diff changeset
2529 widest_int bump = c->index * wi::to_widest (c->stride);
kono
parents:
diff changeset
2530
kono
parents:
diff changeset
2531 replace_mult_candidate (c, name, bump);
kono
parents:
diff changeset
2532 }
kono
parents:
diff changeset
2533
kono
parents:
diff changeset
2534 /* Recursive helper function for phi_add_costs. SPREAD is a measure of
kono
parents:
diff changeset
2535 how many PHI nodes we have visited at this point in the tree walk. */
kono
parents:
diff changeset
2536
kono
parents:
diff changeset
2537 static int
kono
parents:
diff changeset
2538 phi_add_costs_1 (gimple *phi, slsr_cand_t c, int one_add_cost, int *spread)
kono
parents:
diff changeset
2539 {
kono
parents:
diff changeset
2540 unsigned i;
kono
parents:
diff changeset
2541 int cost = 0;
kono
parents:
diff changeset
2542 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
2543
kono
parents:
diff changeset
2544 if (phi_cand->visited)
kono
parents:
diff changeset
2545 return 0;
kono
parents:
diff changeset
2546
kono
parents:
diff changeset
2547 phi_cand->visited = 1;
kono
parents:
diff changeset
2548 (*spread)++;
kono
parents:
diff changeset
2549
kono
parents:
diff changeset
2550 /* If we work our way back to a phi that isn't dominated by the hidden
kono
parents:
diff changeset
2551 basis, this isn't a candidate for replacement. Indicate this by
kono
parents:
diff changeset
2552 returning an unreasonably high cost. It's not easy to detect
kono
parents:
diff changeset
2553 these situations when determining the basis, so we defer the
kono
parents:
diff changeset
2554 decision until now. */
kono
parents:
diff changeset
2555 basic_block phi_bb = gimple_bb (phi);
kono
parents:
diff changeset
2556 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2557 basic_block basis_bb = gimple_bb (basis->cand_stmt);
kono
parents:
diff changeset
2558
kono
parents:
diff changeset
2559 if (phi_bb == basis_bb || !dominated_by_p (CDI_DOMINATORS, phi_bb, basis_bb))
kono
parents:
diff changeset
2560 return COST_INFINITE;
kono
parents:
diff changeset
2561
kono
parents:
diff changeset
2562 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
2563 {
kono
parents:
diff changeset
2564 tree arg = gimple_phi_arg_def (phi, i);
kono
parents:
diff changeset
2565
kono
parents:
diff changeset
2566 if (arg != phi_cand->base_expr)
kono
parents:
diff changeset
2567 {
kono
parents:
diff changeset
2568 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
kono
parents:
diff changeset
2569
kono
parents:
diff changeset
2570 if (gimple_code (arg_def) == GIMPLE_PHI)
kono
parents:
diff changeset
2571 {
kono
parents:
diff changeset
2572 cost += phi_add_costs_1 (arg_def, c, one_add_cost, spread);
kono
parents:
diff changeset
2573
kono
parents:
diff changeset
2574 if (cost >= COST_INFINITE || *spread > MAX_SPREAD)
kono
parents:
diff changeset
2575 return COST_INFINITE;
kono
parents:
diff changeset
2576 }
kono
parents:
diff changeset
2577 else
kono
parents:
diff changeset
2578 {
kono
parents:
diff changeset
2579 slsr_cand_t arg_cand = base_cand_from_table (arg);
kono
parents:
diff changeset
2580
kono
parents:
diff changeset
2581 if (arg_cand->index != c->index)
kono
parents:
diff changeset
2582 cost += one_add_cost;
kono
parents:
diff changeset
2583 }
kono
parents:
diff changeset
2584 }
kono
parents:
diff changeset
2585 }
kono
parents:
diff changeset
2586
kono
parents:
diff changeset
2587 return cost;
kono
parents:
diff changeset
2588 }
kono
parents:
diff changeset
2589
kono
parents:
diff changeset
2590 /* Compute the expected costs of inserting basis adjustments for
kono
parents:
diff changeset
2591 candidate C with phi-definition PHI. The cost of inserting
kono
parents:
diff changeset
2592 one adjustment is given by ONE_ADD_COST. If PHI has arguments
kono
parents:
diff changeset
2593 which are themselves phi results, recursively calculate costs
kono
parents:
diff changeset
2594 for those phis as well. */
kono
parents:
diff changeset
2595
kono
parents:
diff changeset
2596 static int
kono
parents:
diff changeset
2597 phi_add_costs (gimple *phi, slsr_cand_t c, int one_add_cost)
kono
parents:
diff changeset
2598 {
kono
parents:
diff changeset
2599 int spread = 0;
kono
parents:
diff changeset
2600 int retval = phi_add_costs_1 (phi, c, one_add_cost, &spread);
kono
parents:
diff changeset
2601 clear_visited (as_a <gphi *> (phi));
kono
parents:
diff changeset
2602 return retval;
kono
parents:
diff changeset
2603 }
kono
parents:
diff changeset
2604 /* For candidate C, each sibling of candidate C, and each dependent of
kono
parents:
diff changeset
2605 candidate C, determine whether the candidate is dependent upon a
kono
parents:
diff changeset
2606 phi that hides its basis. If not, replace the candidate unconditionally.
kono
parents:
diff changeset
2607 Otherwise, determine whether the cost of introducing compensation code
kono
parents:
diff changeset
2608 for the candidate is offset by the gains from strength reduction. If
kono
parents:
diff changeset
2609 so, replace the candidate and introduce the compensation code. */
kono
parents:
diff changeset
2610
kono
parents:
diff changeset
2611 static void
kono
parents:
diff changeset
2612 replace_uncond_cands_and_profitable_phis (slsr_cand_t c)
kono
parents:
diff changeset
2613 {
kono
parents:
diff changeset
2614 if (phi_dependent_cand_p (c))
kono
parents:
diff changeset
2615 {
kono
parents:
diff changeset
2616 /* A multiply candidate with a stride of 1 is just an artifice
kono
parents:
diff changeset
2617 of a copy or cast; there is no value in replacing it. */
kono
parents:
diff changeset
2618 if (c->kind == CAND_MULT && wi::to_widest (c->stride) != 1)
kono
parents:
diff changeset
2619 {
kono
parents:
diff changeset
2620 /* A candidate dependent upon a phi will replace a multiply by
kono
parents:
diff changeset
2621 a constant with an add, and will insert at most one add for
kono
parents:
diff changeset
2622 each phi argument. Add these costs with the potential dead-code
kono
parents:
diff changeset
2623 savings to determine profitability. */
kono
parents:
diff changeset
2624 bool speed = optimize_bb_for_speed_p (gimple_bb (c->cand_stmt));
kono
parents:
diff changeset
2625 int mult_savings = stmt_cost (c->cand_stmt, speed);
kono
parents:
diff changeset
2626 gimple *phi = lookup_cand (c->def_phi)->cand_stmt;
kono
parents:
diff changeset
2627 tree phi_result = gimple_phi_result (phi);
kono
parents:
diff changeset
2628 int one_add_cost = add_cost (speed,
kono
parents:
diff changeset
2629 TYPE_MODE (TREE_TYPE (phi_result)));
kono
parents:
diff changeset
2630 int add_costs = one_add_cost + phi_add_costs (phi, c, one_add_cost);
kono
parents:
diff changeset
2631 int cost = add_costs - mult_savings - c->dead_savings;
kono
parents:
diff changeset
2632
kono
parents:
diff changeset
2633 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
2634 {
kono
parents:
diff changeset
2635 fprintf (dump_file, " Conditional candidate %d:\n", c->cand_num);
kono
parents:
diff changeset
2636 fprintf (dump_file, " add_costs = %d\n", add_costs);
kono
parents:
diff changeset
2637 fprintf (dump_file, " mult_savings = %d\n", mult_savings);
kono
parents:
diff changeset
2638 fprintf (dump_file, " dead_savings = %d\n", c->dead_savings);
kono
parents:
diff changeset
2639 fprintf (dump_file, " cost = %d\n", cost);
kono
parents:
diff changeset
2640 if (cost <= COST_NEUTRAL)
kono
parents:
diff changeset
2641 fputs (" Replacing...\n", dump_file);
kono
parents:
diff changeset
2642 else
kono
parents:
diff changeset
2643 fputs (" Not replaced.\n", dump_file);
kono
parents:
diff changeset
2644 }
kono
parents:
diff changeset
2645
kono
parents:
diff changeset
2646 if (cost <= COST_NEUTRAL)
kono
parents:
diff changeset
2647 replace_conditional_candidate (c);
kono
parents:
diff changeset
2648 }
kono
parents:
diff changeset
2649 }
kono
parents:
diff changeset
2650 else
kono
parents:
diff changeset
2651 replace_unconditional_candidate (c);
kono
parents:
diff changeset
2652
kono
parents:
diff changeset
2653 if (c->sibling)
kono
parents:
diff changeset
2654 replace_uncond_cands_and_profitable_phis (lookup_cand (c->sibling));
kono
parents:
diff changeset
2655
kono
parents:
diff changeset
2656 if (c->dependent)
kono
parents:
diff changeset
2657 replace_uncond_cands_and_profitable_phis (lookup_cand (c->dependent));
kono
parents:
diff changeset
2658 }
kono
parents:
diff changeset
2659
kono
parents:
diff changeset
2660 /* Count the number of candidates in the tree rooted at C that have
kono
parents:
diff changeset
2661 not already been replaced under other interpretations. */
kono
parents:
diff changeset
2662
kono
parents:
diff changeset
2663 static int
kono
parents:
diff changeset
2664 count_candidates (slsr_cand_t c)
kono
parents:
diff changeset
2665 {
kono
parents:
diff changeset
2666 unsigned count = cand_already_replaced (c) ? 0 : 1;
kono
parents:
diff changeset
2667
kono
parents:
diff changeset
2668 if (c->sibling)
kono
parents:
diff changeset
2669 count += count_candidates (lookup_cand (c->sibling));
kono
parents:
diff changeset
2670
kono
parents:
diff changeset
2671 if (c->dependent)
kono
parents:
diff changeset
2672 count += count_candidates (lookup_cand (c->dependent));
kono
parents:
diff changeset
2673
kono
parents:
diff changeset
2674 return count;
kono
parents:
diff changeset
2675 }
kono
parents:
diff changeset
2676
kono
parents:
diff changeset
2677 /* Increase the count of INCREMENT by one in the increment vector.
kono
parents:
diff changeset
2678 INCREMENT is associated with candidate C. If INCREMENT is to be
kono
parents:
diff changeset
2679 conditionally executed as part of a conditional candidate replacement,
kono
parents:
diff changeset
2680 IS_PHI_ADJUST is true, otherwise false. If an initializer
kono
parents:
diff changeset
2681 T_0 = stride * I is provided by a candidate that dominates all
kono
parents:
diff changeset
2682 candidates with the same increment, also record T_0 for subsequent use. */
kono
parents:
diff changeset
2683
kono
parents:
diff changeset
2684 static void
kono
parents:
diff changeset
2685 record_increment (slsr_cand_t c, widest_int increment, bool is_phi_adjust)
kono
parents:
diff changeset
2686 {
kono
parents:
diff changeset
2687 bool found = false;
kono
parents:
diff changeset
2688 unsigned i;
kono
parents:
diff changeset
2689
kono
parents:
diff changeset
2690 /* Treat increments that differ only in sign as identical so as to
kono
parents:
diff changeset
2691 share initializers, unless we are generating pointer arithmetic. */
kono
parents:
diff changeset
2692 if (!address_arithmetic_p && wi::neg_p (increment))
kono
parents:
diff changeset
2693 increment = -increment;
kono
parents:
diff changeset
2694
kono
parents:
diff changeset
2695 for (i = 0; i < incr_vec_len; i++)
kono
parents:
diff changeset
2696 {
kono
parents:
diff changeset
2697 if (incr_vec[i].incr == increment)
kono
parents:
diff changeset
2698 {
kono
parents:
diff changeset
2699 incr_vec[i].count++;
kono
parents:
diff changeset
2700 found = true;
kono
parents:
diff changeset
2701
kono
parents:
diff changeset
2702 /* If we previously recorded an initializer that doesn't
kono
parents:
diff changeset
2703 dominate this candidate, it's not going to be useful to
kono
parents:
diff changeset
2704 us after all. */
kono
parents:
diff changeset
2705 if (incr_vec[i].initializer
kono
parents:
diff changeset
2706 && !dominated_by_p (CDI_DOMINATORS,
kono
parents:
diff changeset
2707 gimple_bb (c->cand_stmt),
kono
parents:
diff changeset
2708 incr_vec[i].init_bb))
kono
parents:
diff changeset
2709 {
kono
parents:
diff changeset
2710 incr_vec[i].initializer = NULL_TREE;
kono
parents:
diff changeset
2711 incr_vec[i].init_bb = NULL;
kono
parents:
diff changeset
2712 }
kono
parents:
diff changeset
2713
kono
parents:
diff changeset
2714 break;
kono
parents:
diff changeset
2715 }
kono
parents:
diff changeset
2716 }
kono
parents:
diff changeset
2717
kono
parents:
diff changeset
2718 if (!found && incr_vec_len < MAX_INCR_VEC_LEN - 1)
kono
parents:
diff changeset
2719 {
kono
parents:
diff changeset
2720 /* The first time we see an increment, create the entry for it.
kono
parents:
diff changeset
2721 If this is the root candidate which doesn't have a basis, set
kono
parents:
diff changeset
2722 the count to zero. We're only processing it so it can possibly
kono
parents:
diff changeset
2723 provide an initializer for other candidates. */
kono
parents:
diff changeset
2724 incr_vec[incr_vec_len].incr = increment;
kono
parents:
diff changeset
2725 incr_vec[incr_vec_len].count = c->basis || is_phi_adjust ? 1 : 0;
kono
parents:
diff changeset
2726 incr_vec[incr_vec_len].cost = COST_INFINITE;
kono
parents:
diff changeset
2727
kono
parents:
diff changeset
2728 /* Optimistically record the first occurrence of this increment
kono
parents:
diff changeset
2729 as providing an initializer (if it does); we will revise this
kono
parents:
diff changeset
2730 opinion later if it doesn't dominate all other occurrences.
kono
parents:
diff changeset
2731 Exception: increments of 0, 1 never need initializers;
kono
parents:
diff changeset
2732 and phi adjustments don't ever provide initializers. */
kono
parents:
diff changeset
2733 if (c->kind == CAND_ADD
kono
parents:
diff changeset
2734 && !is_phi_adjust
kono
parents:
diff changeset
2735 && c->index == increment
kono
parents:
diff changeset
2736 && (increment > 1 || increment < 0)
kono
parents:
diff changeset
2737 && (gimple_assign_rhs_code (c->cand_stmt) == PLUS_EXPR
kono
parents:
diff changeset
2738 || gimple_assign_rhs_code (c->cand_stmt) == POINTER_PLUS_EXPR))
kono
parents:
diff changeset
2739 {
kono
parents:
diff changeset
2740 tree t0 = NULL_TREE;
kono
parents:
diff changeset
2741 tree rhs1 = gimple_assign_rhs1 (c->cand_stmt);
kono
parents:
diff changeset
2742 tree rhs2 = gimple_assign_rhs2 (c->cand_stmt);
kono
parents:
diff changeset
2743 if (operand_equal_p (rhs1, c->base_expr, 0))
kono
parents:
diff changeset
2744 t0 = rhs2;
kono
parents:
diff changeset
2745 else if (operand_equal_p (rhs2, c->base_expr, 0))
kono
parents:
diff changeset
2746 t0 = rhs1;
kono
parents:
diff changeset
2747 if (t0
kono
parents:
diff changeset
2748 && SSA_NAME_DEF_STMT (t0)
kono
parents:
diff changeset
2749 && gimple_bb (SSA_NAME_DEF_STMT (t0)))
kono
parents:
diff changeset
2750 {
kono
parents:
diff changeset
2751 incr_vec[incr_vec_len].initializer = t0;
kono
parents:
diff changeset
2752 incr_vec[incr_vec_len++].init_bb
kono
parents:
diff changeset
2753 = gimple_bb (SSA_NAME_DEF_STMT (t0));
kono
parents:
diff changeset
2754 }
kono
parents:
diff changeset
2755 else
kono
parents:
diff changeset
2756 {
kono
parents:
diff changeset
2757 incr_vec[incr_vec_len].initializer = NULL_TREE;
kono
parents:
diff changeset
2758 incr_vec[incr_vec_len++].init_bb = NULL;
kono
parents:
diff changeset
2759 }
kono
parents:
diff changeset
2760 }
kono
parents:
diff changeset
2761 else
kono
parents:
diff changeset
2762 {
kono
parents:
diff changeset
2763 incr_vec[incr_vec_len].initializer = NULL_TREE;
kono
parents:
diff changeset
2764 incr_vec[incr_vec_len++].init_bb = NULL;
kono
parents:
diff changeset
2765 }
kono
parents:
diff changeset
2766 }
kono
parents:
diff changeset
2767 }
kono
parents:
diff changeset
2768
kono
parents:
diff changeset
2769 /* Recursive helper function for record_phi_increments. */
kono
parents:
diff changeset
2770
kono
parents:
diff changeset
2771 static void
kono
parents:
diff changeset
2772 record_phi_increments_1 (slsr_cand_t basis, gimple *phi)
kono
parents:
diff changeset
2773 {
kono
parents:
diff changeset
2774 unsigned i;
kono
parents:
diff changeset
2775 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
2776
kono
parents:
diff changeset
2777 if (phi_cand->visited)
kono
parents:
diff changeset
2778 return;
kono
parents:
diff changeset
2779 phi_cand->visited = 1;
kono
parents:
diff changeset
2780
kono
parents:
diff changeset
2781 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
2782 {
kono
parents:
diff changeset
2783 tree arg = gimple_phi_arg_def (phi, i);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2784 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2785
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2786 if (gimple_code (arg_def) == GIMPLE_PHI)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2787 record_phi_increments_1 (basis, arg_def);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2788 else
111
kono
parents:
diff changeset
2789 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2790 widest_int diff;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2791
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2792 if (operand_equal_p (arg, phi_cand->base_expr, 0))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2793 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2794 diff = -basis->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2795 record_increment (phi_cand, diff, PHI_ADJUST);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2796 }
111
kono
parents:
diff changeset
2797 else
kono
parents:
diff changeset
2798 {
kono
parents:
diff changeset
2799 slsr_cand_t arg_cand = base_cand_from_table (arg);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2800 diff = arg_cand->index - basis->index;
111
kono
parents:
diff changeset
2801 record_increment (arg_cand, diff, PHI_ADJUST);
kono
parents:
diff changeset
2802 }
kono
parents:
diff changeset
2803 }
kono
parents:
diff changeset
2804 }
kono
parents:
diff changeset
2805 }
kono
parents:
diff changeset
2806
kono
parents:
diff changeset
2807 /* Given phi statement PHI that hides a candidate from its BASIS, find
kono
parents:
diff changeset
2808 the increments along each incoming arc (recursively handling additional
kono
parents:
diff changeset
2809 phis that may be present) and record them. These increments are the
kono
parents:
diff changeset
2810 difference in index between the index-adjusting statements and the
kono
parents:
diff changeset
2811 index of the basis. */
kono
parents:
diff changeset
2812
kono
parents:
diff changeset
2813 static void
kono
parents:
diff changeset
2814 record_phi_increments (slsr_cand_t basis, gimple *phi)
kono
parents:
diff changeset
2815 {
kono
parents:
diff changeset
2816 record_phi_increments_1 (basis, phi);
kono
parents:
diff changeset
2817 clear_visited (as_a <gphi *> (phi));
kono
parents:
diff changeset
2818 }
kono
parents:
diff changeset
2819
kono
parents:
diff changeset
2820 /* Determine how many times each unique increment occurs in the set
kono
parents:
diff changeset
2821 of candidates rooted at C's parent, recording the data in the
kono
parents:
diff changeset
2822 increment vector. For each unique increment I, if an initializer
kono
parents:
diff changeset
2823 T_0 = stride * I is provided by a candidate that dominates all
kono
parents:
diff changeset
2824 candidates with the same increment, also record T_0 for subsequent
kono
parents:
diff changeset
2825 use. */
kono
parents:
diff changeset
2826
kono
parents:
diff changeset
2827 static void
kono
parents:
diff changeset
2828 record_increments (slsr_cand_t c)
kono
parents:
diff changeset
2829 {
kono
parents:
diff changeset
2830 if (!cand_already_replaced (c))
kono
parents:
diff changeset
2831 {
kono
parents:
diff changeset
2832 if (!phi_dependent_cand_p (c))
kono
parents:
diff changeset
2833 record_increment (c, cand_increment (c), NOT_PHI_ADJUST);
kono
parents:
diff changeset
2834 else
kono
parents:
diff changeset
2835 {
kono
parents:
diff changeset
2836 /* A candidate with a basis hidden by a phi will have one
kono
parents:
diff changeset
2837 increment for its relationship to the index represented by
kono
parents:
diff changeset
2838 the phi, and potentially additional increments along each
kono
parents:
diff changeset
2839 incoming edge. For the root of the dependency tree (which
kono
parents:
diff changeset
2840 has no basis), process just the initial index in case it has
kono
parents:
diff changeset
2841 an initializer that can be used by subsequent candidates. */
kono
parents:
diff changeset
2842 record_increment (c, c->index, NOT_PHI_ADJUST);
kono
parents:
diff changeset
2843
kono
parents:
diff changeset
2844 if (c->basis)
kono
parents:
diff changeset
2845 record_phi_increments (lookup_cand (c->basis),
kono
parents:
diff changeset
2846 lookup_cand (c->def_phi)->cand_stmt);
kono
parents:
diff changeset
2847 }
kono
parents:
diff changeset
2848 }
kono
parents:
diff changeset
2849
kono
parents:
diff changeset
2850 if (c->sibling)
kono
parents:
diff changeset
2851 record_increments (lookup_cand (c->sibling));
kono
parents:
diff changeset
2852
kono
parents:
diff changeset
2853 if (c->dependent)
kono
parents:
diff changeset
2854 record_increments (lookup_cand (c->dependent));
kono
parents:
diff changeset
2855 }
kono
parents:
diff changeset
2856
kono
parents:
diff changeset
2857 /* Recursive helper function for phi_incr_cost. */
kono
parents:
diff changeset
2858
kono
parents:
diff changeset
2859 static int
kono
parents:
diff changeset
2860 phi_incr_cost_1 (slsr_cand_t c, const widest_int &incr, gimple *phi,
kono
parents:
diff changeset
2861 int *savings)
kono
parents:
diff changeset
2862 {
kono
parents:
diff changeset
2863 unsigned i;
kono
parents:
diff changeset
2864 int cost = 0;
kono
parents:
diff changeset
2865 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
2866 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
2867
kono
parents:
diff changeset
2868 if (phi_cand->visited)
kono
parents:
diff changeset
2869 return 0;
kono
parents:
diff changeset
2870 phi_cand->visited = 1;
kono
parents:
diff changeset
2871
kono
parents:
diff changeset
2872 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
2873 {
kono
parents:
diff changeset
2874 tree arg = gimple_phi_arg_def (phi, i);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2875 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2876
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2877 if (gimple_code (arg_def) == GIMPLE_PHI)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2878 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2879 int feeding_savings = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2880 tree feeding_var = gimple_phi_result (arg_def);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2881 cost += phi_incr_cost_1 (c, incr, arg_def, &feeding_savings);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2882 if (uses_consumed_by_stmt (feeding_var, phi))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2883 *savings += feeding_savings;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2884 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2885 else
111
kono
parents:
diff changeset
2886 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2887 widest_int diff;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2888 slsr_cand_t arg_cand;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2889
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2890 /* When the PHI argument is just a pass-through to the base
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2891 expression of the hidden basis, the difference is zero minus
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2892 the index of the basis. There is no potential savings by
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2893 eliminating a statement in this case. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2894 if (operand_equal_p (arg, phi_cand->base_expr, 0))
111
kono
parents:
diff changeset
2895 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2896 arg_cand = (slsr_cand_t)NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2897 diff = -basis->index;
111
kono
parents:
diff changeset
2898 }
kono
parents:
diff changeset
2899 else
kono
parents:
diff changeset
2900 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2901 arg_cand = base_cand_from_table (arg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2902 diff = arg_cand->index - basis->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2903 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2904
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2905 if (incr == diff)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2906 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2907 tree basis_lhs = gimple_assign_lhs (basis->cand_stmt);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2908 cost += add_cost (true, TYPE_MODE (TREE_TYPE (basis_lhs)));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2909 if (arg_cand)
111
kono
parents:
diff changeset
2910 {
kono
parents:
diff changeset
2911 tree lhs = gimple_assign_lhs (arg_cand->cand_stmt);
kono
parents:
diff changeset
2912 if (uses_consumed_by_stmt (lhs, phi))
kono
parents:
diff changeset
2913 *savings += stmt_cost (arg_cand->cand_stmt, true);
kono
parents:
diff changeset
2914 }
kono
parents:
diff changeset
2915 }
kono
parents:
diff changeset
2916 }
kono
parents:
diff changeset
2917 }
kono
parents:
diff changeset
2918
kono
parents:
diff changeset
2919 return cost;
kono
parents:
diff changeset
2920 }
kono
parents:
diff changeset
2921
kono
parents:
diff changeset
2922 /* Add up and return the costs of introducing add statements that
kono
parents:
diff changeset
2923 require the increment INCR on behalf of candidate C and phi
kono
parents:
diff changeset
2924 statement PHI. Accumulate into *SAVINGS the potential savings
kono
parents:
diff changeset
2925 from removing existing statements that feed PHI and have no other
kono
parents:
diff changeset
2926 uses. */
kono
parents:
diff changeset
2927
kono
parents:
diff changeset
2928 static int
kono
parents:
diff changeset
2929 phi_incr_cost (slsr_cand_t c, const widest_int &incr, gimple *phi,
kono
parents:
diff changeset
2930 int *savings)
kono
parents:
diff changeset
2931 {
kono
parents:
diff changeset
2932 int retval = phi_incr_cost_1 (c, incr, phi, savings);
kono
parents:
diff changeset
2933 clear_visited (as_a <gphi *> (phi));
kono
parents:
diff changeset
2934 return retval;
kono
parents:
diff changeset
2935 }
kono
parents:
diff changeset
2936
kono
parents:
diff changeset
2937 /* Return the first candidate in the tree rooted at C that has not
kono
parents:
diff changeset
2938 already been replaced, favoring siblings over dependents. */
kono
parents:
diff changeset
2939
kono
parents:
diff changeset
2940 static slsr_cand_t
kono
parents:
diff changeset
2941 unreplaced_cand_in_tree (slsr_cand_t c)
kono
parents:
diff changeset
2942 {
kono
parents:
diff changeset
2943 if (!cand_already_replaced (c))
kono
parents:
diff changeset
2944 return c;
kono
parents:
diff changeset
2945
kono
parents:
diff changeset
2946 if (c->sibling)
kono
parents:
diff changeset
2947 {
kono
parents:
diff changeset
2948 slsr_cand_t sib = unreplaced_cand_in_tree (lookup_cand (c->sibling));
kono
parents:
diff changeset
2949 if (sib)
kono
parents:
diff changeset
2950 return sib;
kono
parents:
diff changeset
2951 }
kono
parents:
diff changeset
2952
kono
parents:
diff changeset
2953 if (c->dependent)
kono
parents:
diff changeset
2954 {
kono
parents:
diff changeset
2955 slsr_cand_t dep = unreplaced_cand_in_tree (lookup_cand (c->dependent));
kono
parents:
diff changeset
2956 if (dep)
kono
parents:
diff changeset
2957 return dep;
kono
parents:
diff changeset
2958 }
kono
parents:
diff changeset
2959
kono
parents:
diff changeset
2960 return NULL;
kono
parents:
diff changeset
2961 }
kono
parents:
diff changeset
2962
kono
parents:
diff changeset
2963 /* Return TRUE if the candidates in the tree rooted at C should be
kono
parents:
diff changeset
2964 optimized for speed, else FALSE. We estimate this based on the block
kono
parents:
diff changeset
2965 containing the most dominant candidate in the tree that has not yet
kono
parents:
diff changeset
2966 been replaced. */
kono
parents:
diff changeset
2967
kono
parents:
diff changeset
2968 static bool
kono
parents:
diff changeset
2969 optimize_cands_for_speed_p (slsr_cand_t c)
kono
parents:
diff changeset
2970 {
kono
parents:
diff changeset
2971 slsr_cand_t c2 = unreplaced_cand_in_tree (c);
kono
parents:
diff changeset
2972 gcc_assert (c2);
kono
parents:
diff changeset
2973 return optimize_bb_for_speed_p (gimple_bb (c2->cand_stmt));
kono
parents:
diff changeset
2974 }
kono
parents:
diff changeset
2975
kono
parents:
diff changeset
2976 /* Add COST_IN to the lowest cost of any dependent path starting at
kono
parents:
diff changeset
2977 candidate C or any of its siblings, counting only candidates along
kono
parents:
diff changeset
2978 such paths with increment INCR. Assume that replacing a candidate
kono
parents:
diff changeset
2979 reduces cost by REPL_SAVINGS. Also account for savings from any
kono
parents:
diff changeset
2980 statements that would go dead. If COUNT_PHIS is true, include
kono
parents:
diff changeset
2981 costs of introducing feeding statements for conditional candidates. */
kono
parents:
diff changeset
2982
kono
parents:
diff changeset
2983 static int
kono
parents:
diff changeset
2984 lowest_cost_path (int cost_in, int repl_savings, slsr_cand_t c,
kono
parents:
diff changeset
2985 const widest_int &incr, bool count_phis)
kono
parents:
diff changeset
2986 {
kono
parents:
diff changeset
2987 int local_cost, sib_cost, savings = 0;
kono
parents:
diff changeset
2988 widest_int cand_incr = cand_abs_increment (c);
kono
parents:
diff changeset
2989
kono
parents:
diff changeset
2990 if (cand_already_replaced (c))
kono
parents:
diff changeset
2991 local_cost = cost_in;
kono
parents:
diff changeset
2992 else if (incr == cand_incr)
kono
parents:
diff changeset
2993 local_cost = cost_in - repl_savings - c->dead_savings;
kono
parents:
diff changeset
2994 else
kono
parents:
diff changeset
2995 local_cost = cost_in - c->dead_savings;
kono
parents:
diff changeset
2996
kono
parents:
diff changeset
2997 if (count_phis
kono
parents:
diff changeset
2998 && phi_dependent_cand_p (c)
kono
parents:
diff changeset
2999 && !cand_already_replaced (c))
kono
parents:
diff changeset
3000 {
kono
parents:
diff changeset
3001 gimple *phi = lookup_cand (c->def_phi)->cand_stmt;
kono
parents:
diff changeset
3002 local_cost += phi_incr_cost (c, incr, phi, &savings);
kono
parents:
diff changeset
3003
kono
parents:
diff changeset
3004 if (uses_consumed_by_stmt (gimple_phi_result (phi), c->cand_stmt))
kono
parents:
diff changeset
3005 local_cost -= savings;
kono
parents:
diff changeset
3006 }
kono
parents:
diff changeset
3007
kono
parents:
diff changeset
3008 if (c->dependent)
kono
parents:
diff changeset
3009 local_cost = lowest_cost_path (local_cost, repl_savings,
kono
parents:
diff changeset
3010 lookup_cand (c->dependent), incr,
kono
parents:
diff changeset
3011 count_phis);
kono
parents:
diff changeset
3012
kono
parents:
diff changeset
3013 if (c->sibling)
kono
parents:
diff changeset
3014 {
kono
parents:
diff changeset
3015 sib_cost = lowest_cost_path (cost_in, repl_savings,
kono
parents:
diff changeset
3016 lookup_cand (c->sibling), incr,
kono
parents:
diff changeset
3017 count_phis);
kono
parents:
diff changeset
3018 local_cost = MIN (local_cost, sib_cost);
kono
parents:
diff changeset
3019 }
kono
parents:
diff changeset
3020
kono
parents:
diff changeset
3021 return local_cost;
kono
parents:
diff changeset
3022 }
kono
parents:
diff changeset
3023
kono
parents:
diff changeset
3024 /* Compute the total savings that would accrue from all replacements
kono
parents:
diff changeset
3025 in the candidate tree rooted at C, counting only candidates with
kono
parents:
diff changeset
3026 increment INCR. Assume that replacing a candidate reduces cost
kono
parents:
diff changeset
3027 by REPL_SAVINGS. Also account for savings from statements that
kono
parents:
diff changeset
3028 would go dead. */
kono
parents:
diff changeset
3029
kono
parents:
diff changeset
3030 static int
kono
parents:
diff changeset
3031 total_savings (int repl_savings, slsr_cand_t c, const widest_int &incr,
kono
parents:
diff changeset
3032 bool count_phis)
kono
parents:
diff changeset
3033 {
kono
parents:
diff changeset
3034 int savings = 0;
kono
parents:
diff changeset
3035 widest_int cand_incr = cand_abs_increment (c);
kono
parents:
diff changeset
3036
kono
parents:
diff changeset
3037 if (incr == cand_incr && !cand_already_replaced (c))
kono
parents:
diff changeset
3038 savings += repl_savings + c->dead_savings;
kono
parents:
diff changeset
3039
kono
parents:
diff changeset
3040 if (count_phis
kono
parents:
diff changeset
3041 && phi_dependent_cand_p (c)
kono
parents:
diff changeset
3042 && !cand_already_replaced (c))
kono
parents:
diff changeset
3043 {
kono
parents:
diff changeset
3044 int phi_savings = 0;
kono
parents:
diff changeset
3045 gimple *phi = lookup_cand (c->def_phi)->cand_stmt;
kono
parents:
diff changeset
3046 savings -= phi_incr_cost (c, incr, phi, &phi_savings);
kono
parents:
diff changeset
3047
kono
parents:
diff changeset
3048 if (uses_consumed_by_stmt (gimple_phi_result (phi), c->cand_stmt))
kono
parents:
diff changeset
3049 savings += phi_savings;
kono
parents:
diff changeset
3050 }
kono
parents:
diff changeset
3051
kono
parents:
diff changeset
3052 if (c->dependent)
kono
parents:
diff changeset
3053 savings += total_savings (repl_savings, lookup_cand (c->dependent), incr,
kono
parents:
diff changeset
3054 count_phis);
kono
parents:
diff changeset
3055
kono
parents:
diff changeset
3056 if (c->sibling)
kono
parents:
diff changeset
3057 savings += total_savings (repl_savings, lookup_cand (c->sibling), incr,
kono
parents:
diff changeset
3058 count_phis);
kono
parents:
diff changeset
3059
kono
parents:
diff changeset
3060 return savings;
kono
parents:
diff changeset
3061 }
kono
parents:
diff changeset
3062
kono
parents:
diff changeset
3063 /* Use target-specific costs to determine and record which increments
kono
parents:
diff changeset
3064 in the current candidate tree are profitable to replace, assuming
kono
parents:
diff changeset
3065 MODE and SPEED. FIRST_DEP is the first dependent of the root of
kono
parents:
diff changeset
3066 the candidate tree.
kono
parents:
diff changeset
3067
kono
parents:
diff changeset
3068 One slight limitation here is that we don't account for the possible
kono
parents:
diff changeset
3069 introduction of casts in some cases. See replace_one_candidate for
kono
parents:
diff changeset
3070 the cases where these are introduced. This should probably be cleaned
kono
parents:
diff changeset
3071 up sometime. */
kono
parents:
diff changeset
3072
kono
parents:
diff changeset
3073 static void
kono
parents:
diff changeset
3074 analyze_increments (slsr_cand_t first_dep, machine_mode mode, bool speed)
kono
parents:
diff changeset
3075 {
kono
parents:
diff changeset
3076 unsigned i;
kono
parents:
diff changeset
3077
kono
parents:
diff changeset
3078 for (i = 0; i < incr_vec_len; i++)
kono
parents:
diff changeset
3079 {
kono
parents:
diff changeset
3080 HOST_WIDE_INT incr = incr_vec[i].incr.to_shwi ();
kono
parents:
diff changeset
3081
kono
parents:
diff changeset
3082 /* If somehow this increment is bigger than a HWI, we won't
kono
parents:
diff changeset
3083 be optimizing candidates that use it. And if the increment
kono
parents:
diff changeset
3084 has a count of zero, nothing will be done with it. */
kono
parents:
diff changeset
3085 if (!wi::fits_shwi_p (incr_vec[i].incr) || !incr_vec[i].count)
kono
parents:
diff changeset
3086 incr_vec[i].cost = COST_INFINITE;
kono
parents:
diff changeset
3087
kono
parents:
diff changeset
3088 /* Increments of 0, 1, and -1 are always profitable to replace,
kono
parents:
diff changeset
3089 because they always replace a multiply or add with an add or
kono
parents:
diff changeset
3090 copy, and may cause one or more existing instructions to go
kono
parents:
diff changeset
3091 dead. Exception: -1 can't be assumed to be profitable for
kono
parents:
diff changeset
3092 pointer addition. */
kono
parents:
diff changeset
3093 else if (incr == 0
kono
parents:
diff changeset
3094 || incr == 1
kono
parents:
diff changeset
3095 || (incr == -1
kono
parents:
diff changeset
3096 && !POINTER_TYPE_P (first_dep->cand_type)))
kono
parents:
diff changeset
3097 incr_vec[i].cost = COST_NEUTRAL;
kono
parents:
diff changeset
3098
kono
parents:
diff changeset
3099 /* If we need to add an initializer, give up if a cast from the
kono
parents:
diff changeset
3100 candidate's type to its stride's type can lose precision.
kono
parents:
diff changeset
3101 Note that this already takes into account that the stride may
kono
parents:
diff changeset
3102 have been cast to a wider type, in which case this test won't
kono
parents:
diff changeset
3103 fire. Example:
kono
parents:
diff changeset
3104
kono
parents:
diff changeset
3105 short int _1;
kono
parents:
diff changeset
3106 _2 = (int) _1;
kono
parents:
diff changeset
3107 _3 = _2 * 10;
kono
parents:
diff changeset
3108 _4 = x + _3; ADD: x + (10 * (int)_1) : int
kono
parents:
diff changeset
3109 _5 = _2 * 15;
kono
parents:
diff changeset
3110 _6 = x + _5; ADD: x + (15 * (int)_1) : int
kono
parents:
diff changeset
3111
kono
parents:
diff changeset
3112 Although the stride was a short int initially, the stride
kono
parents:
diff changeset
3113 used in the analysis has been widened to an int, and such
kono
parents:
diff changeset
3114 widening will be done in the initializer as well. */
kono
parents:
diff changeset
3115 else if (!incr_vec[i].initializer
kono
parents:
diff changeset
3116 && TREE_CODE (first_dep->stride) != INTEGER_CST
kono
parents:
diff changeset
3117 && !legal_cast_p_1 (first_dep->stride_type,
kono
parents:
diff changeset
3118 TREE_TYPE (gimple_assign_lhs
kono
parents:
diff changeset
3119 (first_dep->cand_stmt))))
kono
parents:
diff changeset
3120 incr_vec[i].cost = COST_INFINITE;
kono
parents:
diff changeset
3121
kono
parents:
diff changeset
3122 /* If we need to add an initializer, make sure we don't introduce
kono
parents:
diff changeset
3123 a multiply by a pointer type, which can happen in certain cast
kono
parents:
diff changeset
3124 scenarios. */
kono
parents:
diff changeset
3125 else if (!incr_vec[i].initializer
kono
parents:
diff changeset
3126 && TREE_CODE (first_dep->stride) != INTEGER_CST
kono
parents:
diff changeset
3127 && POINTER_TYPE_P (first_dep->stride_type))
kono
parents:
diff changeset
3128 incr_vec[i].cost = COST_INFINITE;
kono
parents:
diff changeset
3129
kono
parents:
diff changeset
3130 /* For any other increment, if this is a multiply candidate, we
kono
parents:
diff changeset
3131 must introduce a temporary T and initialize it with
kono
parents:
diff changeset
3132 T_0 = stride * increment. When optimizing for speed, walk the
kono
parents:
diff changeset
3133 candidate tree to calculate the best cost reduction along any
kono
parents:
diff changeset
3134 path; if it offsets the fixed cost of inserting the initializer,
kono
parents:
diff changeset
3135 replacing the increment is profitable. When optimizing for
kono
parents:
diff changeset
3136 size, instead calculate the total cost reduction from replacing
kono
parents:
diff changeset
3137 all candidates with this increment. */
kono
parents:
diff changeset
3138 else if (first_dep->kind == CAND_MULT)
kono
parents:
diff changeset
3139 {
kono
parents:
diff changeset
3140 int cost = mult_by_coeff_cost (incr, mode, speed);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3141 int repl_savings;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3142
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3143 if (tree_fits_shwi_p (first_dep->stride))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3144 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3145 HOST_WIDE_INT hwi_stride = tree_to_shwi (first_dep->stride);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3146 repl_savings = mult_by_coeff_cost (hwi_stride, mode, speed);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3147 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3148 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3149 repl_savings = mul_cost (speed, mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3150 repl_savings -= add_cost (speed, mode);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3151
111
kono
parents:
diff changeset
3152 if (speed)
kono
parents:
diff changeset
3153 cost = lowest_cost_path (cost, repl_savings, first_dep,
kono
parents:
diff changeset
3154 incr_vec[i].incr, COUNT_PHIS);
kono
parents:
diff changeset
3155 else
kono
parents:
diff changeset
3156 cost -= total_savings (repl_savings, first_dep, incr_vec[i].incr,
kono
parents:
diff changeset
3157 COUNT_PHIS);
kono
parents:
diff changeset
3158
kono
parents:
diff changeset
3159 incr_vec[i].cost = cost;
kono
parents:
diff changeset
3160 }
kono
parents:
diff changeset
3161
kono
parents:
diff changeset
3162 /* If this is an add candidate, the initializer may already
kono
parents:
diff changeset
3163 exist, so only calculate the cost of the initializer if it
kono
parents:
diff changeset
3164 doesn't. We are replacing one add with another here, so the
kono
parents:
diff changeset
3165 known replacement savings is zero. We will account for removal
kono
parents:
diff changeset
3166 of dead instructions in lowest_cost_path or total_savings. */
kono
parents:
diff changeset
3167 else
kono
parents:
diff changeset
3168 {
kono
parents:
diff changeset
3169 int cost = 0;
kono
parents:
diff changeset
3170 if (!incr_vec[i].initializer)
kono
parents:
diff changeset
3171 cost = mult_by_coeff_cost (incr, mode, speed);
kono
parents:
diff changeset
3172
kono
parents:
diff changeset
3173 if (speed)
kono
parents:
diff changeset
3174 cost = lowest_cost_path (cost, 0, first_dep, incr_vec[i].incr,
kono
parents:
diff changeset
3175 DONT_COUNT_PHIS);
kono
parents:
diff changeset
3176 else
kono
parents:
diff changeset
3177 cost -= total_savings (0, first_dep, incr_vec[i].incr,
kono
parents:
diff changeset
3178 DONT_COUNT_PHIS);
kono
parents:
diff changeset
3179
kono
parents:
diff changeset
3180 incr_vec[i].cost = cost;
kono
parents:
diff changeset
3181 }
kono
parents:
diff changeset
3182 }
kono
parents:
diff changeset
3183 }
kono
parents:
diff changeset
3184
kono
parents:
diff changeset
3185 /* Return the nearest common dominator of BB1 and BB2. If the blocks
kono
parents:
diff changeset
3186 are identical, return the earlier of C1 and C2 in *WHERE. Otherwise,
kono
parents:
diff changeset
3187 if the NCD matches BB1, return C1 in *WHERE; if the NCD matches BB2,
kono
parents:
diff changeset
3188 return C2 in *WHERE; and if the NCD matches neither, return NULL in
kono
parents:
diff changeset
3189 *WHERE. Note: It is possible for one of C1 and C2 to be NULL. */
kono
parents:
diff changeset
3190
kono
parents:
diff changeset
3191 static basic_block
kono
parents:
diff changeset
3192 ncd_for_two_cands (basic_block bb1, basic_block bb2,
kono
parents:
diff changeset
3193 slsr_cand_t c1, slsr_cand_t c2, slsr_cand_t *where)
kono
parents:
diff changeset
3194 {
kono
parents:
diff changeset
3195 basic_block ncd;
kono
parents:
diff changeset
3196
kono
parents:
diff changeset
3197 if (!bb1)
kono
parents:
diff changeset
3198 {
kono
parents:
diff changeset
3199 *where = c2;
kono
parents:
diff changeset
3200 return bb2;
kono
parents:
diff changeset
3201 }
kono
parents:
diff changeset
3202
kono
parents:
diff changeset
3203 if (!bb2)
kono
parents:
diff changeset
3204 {
kono
parents:
diff changeset
3205 *where = c1;
kono
parents:
diff changeset
3206 return bb1;
kono
parents:
diff changeset
3207 }
kono
parents:
diff changeset
3208
kono
parents:
diff changeset
3209 ncd = nearest_common_dominator (CDI_DOMINATORS, bb1, bb2);
kono
parents:
diff changeset
3210
kono
parents:
diff changeset
3211 /* If both candidates are in the same block, the earlier
kono
parents:
diff changeset
3212 candidate wins. */
kono
parents:
diff changeset
3213 if (bb1 == ncd && bb2 == ncd)
kono
parents:
diff changeset
3214 {
kono
parents:
diff changeset
3215 if (!c1 || (c2 && c2->cand_num < c1->cand_num))
kono
parents:
diff changeset
3216 *where = c2;
kono
parents:
diff changeset
3217 else
kono
parents:
diff changeset
3218 *where = c1;
kono
parents:
diff changeset
3219 }
kono
parents:
diff changeset
3220
kono
parents:
diff changeset
3221 /* Otherwise, if one of them produced a candidate in the
kono
parents:
diff changeset
3222 dominator, that one wins. */
kono
parents:
diff changeset
3223 else if (bb1 == ncd)
kono
parents:
diff changeset
3224 *where = c1;
kono
parents:
diff changeset
3225
kono
parents:
diff changeset
3226 else if (bb2 == ncd)
kono
parents:
diff changeset
3227 *where = c2;
kono
parents:
diff changeset
3228
kono
parents:
diff changeset
3229 /* If neither matches the dominator, neither wins. */
kono
parents:
diff changeset
3230 else
kono
parents:
diff changeset
3231 *where = NULL;
kono
parents:
diff changeset
3232
kono
parents:
diff changeset
3233 return ncd;
kono
parents:
diff changeset
3234 }
kono
parents:
diff changeset
3235
kono
parents:
diff changeset
3236 /* Consider all candidates that feed PHI. Find the nearest common
kono
parents:
diff changeset
3237 dominator of those candidates requiring the given increment INCR.
kono
parents:
diff changeset
3238 Further find and return the nearest common dominator of this result
kono
parents:
diff changeset
3239 with block NCD. If the returned block contains one or more of the
kono
parents:
diff changeset
3240 candidates, return the earliest candidate in the block in *WHERE. */
kono
parents:
diff changeset
3241
kono
parents:
diff changeset
3242 static basic_block
kono
parents:
diff changeset
3243 ncd_with_phi (slsr_cand_t c, const widest_int &incr, gphi *phi,
kono
parents:
diff changeset
3244 basic_block ncd, slsr_cand_t *where)
kono
parents:
diff changeset
3245 {
kono
parents:
diff changeset
3246 unsigned i;
kono
parents:
diff changeset
3247 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
3248 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
3249
kono
parents:
diff changeset
3250 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
3251 {
kono
parents:
diff changeset
3252 tree arg = gimple_phi_arg_def (phi, i);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3253 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3254
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3255 if (gimple_code (arg_def) == GIMPLE_PHI)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3256 ncd = ncd_with_phi (c, incr, as_a <gphi *> (arg_def), ncd, where);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3257 else
111
kono
parents:
diff changeset
3258 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3259 widest_int diff;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3260
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3261 if (operand_equal_p (arg, phi_cand->base_expr, 0))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3262 diff = -basis->index;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3263 else
111
kono
parents:
diff changeset
3264 {
kono
parents:
diff changeset
3265 slsr_cand_t arg_cand = base_cand_from_table (arg);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3266 diff = arg_cand->index - basis->index;
111
kono
parents:
diff changeset
3267 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3268
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3269 basic_block pred = gimple_phi_arg_edge (phi, i)->src;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3270
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3271 if ((incr == diff) || (!address_arithmetic_p && incr == -diff))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3272 ncd = ncd_for_two_cands (ncd, pred, *where, NULL, where);
111
kono
parents:
diff changeset
3273 }
kono
parents:
diff changeset
3274 }
kono
parents:
diff changeset
3275
kono
parents:
diff changeset
3276 return ncd;
kono
parents:
diff changeset
3277 }
kono
parents:
diff changeset
3278
kono
parents:
diff changeset
3279 /* Consider the candidate C together with any candidates that feed
kono
parents:
diff changeset
3280 C's phi dependence (if any). Find and return the nearest common
kono
parents:
diff changeset
3281 dominator of those candidates requiring the given increment INCR.
kono
parents:
diff changeset
3282 If the returned block contains one or more of the candidates,
kono
parents:
diff changeset
3283 return the earliest candidate in the block in *WHERE. */
kono
parents:
diff changeset
3284
kono
parents:
diff changeset
3285 static basic_block
kono
parents:
diff changeset
3286 ncd_of_cand_and_phis (slsr_cand_t c, const widest_int &incr, slsr_cand_t *where)
kono
parents:
diff changeset
3287 {
kono
parents:
diff changeset
3288 basic_block ncd = NULL;
kono
parents:
diff changeset
3289
kono
parents:
diff changeset
3290 if (cand_abs_increment (c) == incr)
kono
parents:
diff changeset
3291 {
kono
parents:
diff changeset
3292 ncd = gimple_bb (c->cand_stmt);
kono
parents:
diff changeset
3293 *where = c;
kono
parents:
diff changeset
3294 }
kono
parents:
diff changeset
3295
kono
parents:
diff changeset
3296 if (phi_dependent_cand_p (c))
kono
parents:
diff changeset
3297 ncd = ncd_with_phi (c, incr,
kono
parents:
diff changeset
3298 as_a <gphi *> (lookup_cand (c->def_phi)->cand_stmt),
kono
parents:
diff changeset
3299 ncd, where);
kono
parents:
diff changeset
3300
kono
parents:
diff changeset
3301 return ncd;
kono
parents:
diff changeset
3302 }
kono
parents:
diff changeset
3303
kono
parents:
diff changeset
3304 /* Consider all candidates in the tree rooted at C for which INCR
kono
parents:
diff changeset
3305 represents the required increment of C relative to its basis.
kono
parents:
diff changeset
3306 Find and return the basic block that most nearly dominates all
kono
parents:
diff changeset
3307 such candidates. If the returned block contains one or more of
kono
parents:
diff changeset
3308 the candidates, return the earliest candidate in the block in
kono
parents:
diff changeset
3309 *WHERE. */
kono
parents:
diff changeset
3310
kono
parents:
diff changeset
3311 static basic_block
kono
parents:
diff changeset
3312 nearest_common_dominator_for_cands (slsr_cand_t c, const widest_int &incr,
kono
parents:
diff changeset
3313 slsr_cand_t *where)
kono
parents:
diff changeset
3314 {
kono
parents:
diff changeset
3315 basic_block sib_ncd = NULL, dep_ncd = NULL, this_ncd = NULL, ncd;
kono
parents:
diff changeset
3316 slsr_cand_t sib_where = NULL, dep_where = NULL, this_where = NULL, new_where;
kono
parents:
diff changeset
3317
kono
parents:
diff changeset
3318 /* First find the NCD of all siblings and dependents. */
kono
parents:
diff changeset
3319 if (c->sibling)
kono
parents:
diff changeset
3320 sib_ncd = nearest_common_dominator_for_cands (lookup_cand (c->sibling),
kono
parents:
diff changeset
3321 incr, &sib_where);
kono
parents:
diff changeset
3322 if (c->dependent)
kono
parents:
diff changeset
3323 dep_ncd = nearest_common_dominator_for_cands (lookup_cand (c->dependent),
kono
parents:
diff changeset
3324 incr, &dep_where);
kono
parents:
diff changeset
3325 if (!sib_ncd && !dep_ncd)
kono
parents:
diff changeset
3326 {
kono
parents:
diff changeset
3327 new_where = NULL;
kono
parents:
diff changeset
3328 ncd = NULL;
kono
parents:
diff changeset
3329 }
kono
parents:
diff changeset
3330 else if (sib_ncd && !dep_ncd)
kono
parents:
diff changeset
3331 {
kono
parents:
diff changeset
3332 new_where = sib_where;
kono
parents:
diff changeset
3333 ncd = sib_ncd;
kono
parents:
diff changeset
3334 }
kono
parents:
diff changeset
3335 else if (dep_ncd && !sib_ncd)
kono
parents:
diff changeset
3336 {
kono
parents:
diff changeset
3337 new_where = dep_where;
kono
parents:
diff changeset
3338 ncd = dep_ncd;
kono
parents:
diff changeset
3339 }
kono
parents:
diff changeset
3340 else
kono
parents:
diff changeset
3341 ncd = ncd_for_two_cands (sib_ncd, dep_ncd, sib_where,
kono
parents:
diff changeset
3342 dep_where, &new_where);
kono
parents:
diff changeset
3343
kono
parents:
diff changeset
3344 /* If the candidate's increment doesn't match the one we're interested
kono
parents:
diff changeset
3345 in (and nor do any increments for feeding defs of a phi-dependence),
kono
parents:
diff changeset
3346 then the result depends only on siblings and dependents. */
kono
parents:
diff changeset
3347 this_ncd = ncd_of_cand_and_phis (c, incr, &this_where);
kono
parents:
diff changeset
3348
kono
parents:
diff changeset
3349 if (!this_ncd || cand_already_replaced (c))
kono
parents:
diff changeset
3350 {
kono
parents:
diff changeset
3351 *where = new_where;
kono
parents:
diff changeset
3352 return ncd;
kono
parents:
diff changeset
3353 }
kono
parents:
diff changeset
3354
kono
parents:
diff changeset
3355 /* Otherwise, compare this candidate with the result from all siblings
kono
parents:
diff changeset
3356 and dependents. */
kono
parents:
diff changeset
3357 ncd = ncd_for_two_cands (ncd, this_ncd, new_where, this_where, where);
kono
parents:
diff changeset
3358
kono
parents:
diff changeset
3359 return ncd;
kono
parents:
diff changeset
3360 }
kono
parents:
diff changeset
3361
kono
parents:
diff changeset
3362 /* Return TRUE if the increment indexed by INDEX is profitable to replace. */
kono
parents:
diff changeset
3363
kono
parents:
diff changeset
3364 static inline bool
kono
parents:
diff changeset
3365 profitable_increment_p (unsigned index)
kono
parents:
diff changeset
3366 {
kono
parents:
diff changeset
3367 return (incr_vec[index].cost <= COST_NEUTRAL);
kono
parents:
diff changeset
3368 }
kono
parents:
diff changeset
3369
kono
parents:
diff changeset
3370 /* For each profitable increment in the increment vector not equal to
kono
parents:
diff changeset
3371 0 or 1 (or -1, for non-pointer arithmetic), find the nearest common
kono
parents:
diff changeset
3372 dominator of all statements in the candidate chain rooted at C
kono
parents:
diff changeset
3373 that require that increment, and insert an initializer
kono
parents:
diff changeset
3374 T_0 = stride * increment at that location. Record T_0 with the
kono
parents:
diff changeset
3375 increment record. */
kono
parents:
diff changeset
3376
kono
parents:
diff changeset
3377 static void
kono
parents:
diff changeset
3378 insert_initializers (slsr_cand_t c)
kono
parents:
diff changeset
3379 {
kono
parents:
diff changeset
3380 unsigned i;
kono
parents:
diff changeset
3381
kono
parents:
diff changeset
3382 for (i = 0; i < incr_vec_len; i++)
kono
parents:
diff changeset
3383 {
kono
parents:
diff changeset
3384 basic_block bb;
kono
parents:
diff changeset
3385 slsr_cand_t where = NULL;
kono
parents:
diff changeset
3386 gassign *init_stmt;
kono
parents:
diff changeset
3387 gassign *cast_stmt = NULL;
kono
parents:
diff changeset
3388 tree new_name, incr_tree, init_stride;
kono
parents:
diff changeset
3389 widest_int incr = incr_vec[i].incr;
kono
parents:
diff changeset
3390
kono
parents:
diff changeset
3391 if (!profitable_increment_p (i)
kono
parents:
diff changeset
3392 || incr == 1
kono
parents:
diff changeset
3393 || (incr == -1
kono
parents:
diff changeset
3394 && (!POINTER_TYPE_P (lookup_cand (c->basis)->cand_type)))
kono
parents:
diff changeset
3395 || incr == 0)
kono
parents:
diff changeset
3396 continue;
kono
parents:
diff changeset
3397
kono
parents:
diff changeset
3398 /* We may have already identified an existing initializer that
kono
parents:
diff changeset
3399 will suffice. */
kono
parents:
diff changeset
3400 if (incr_vec[i].initializer)
kono
parents:
diff changeset
3401 {
kono
parents:
diff changeset
3402 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3403 {
kono
parents:
diff changeset
3404 fputs ("Using existing initializer: ", dump_file);
kono
parents:
diff changeset
3405 print_gimple_stmt (dump_file,
kono
parents:
diff changeset
3406 SSA_NAME_DEF_STMT (incr_vec[i].initializer),
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3407 0, TDF_NONE);
111
kono
parents:
diff changeset
3408 }
kono
parents:
diff changeset
3409 continue;
kono
parents:
diff changeset
3410 }
kono
parents:
diff changeset
3411
kono
parents:
diff changeset
3412 /* Find the block that most closely dominates all candidates
kono
parents:
diff changeset
3413 with this increment. If there is at least one candidate in
kono
parents:
diff changeset
3414 that block, the earliest one will be returned in WHERE. */
kono
parents:
diff changeset
3415 bb = nearest_common_dominator_for_cands (c, incr, &where);
kono
parents:
diff changeset
3416
kono
parents:
diff changeset
3417 /* If the NCD is not dominated by the block containing the
kono
parents:
diff changeset
3418 definition of the stride, we can't legally insert a
kono
parents:
diff changeset
3419 single initializer. Mark the increment as unprofitable
kono
parents:
diff changeset
3420 so we don't make any replacements. FIXME: Multiple
kono
parents:
diff changeset
3421 initializers could be placed with more analysis. */
kono
parents:
diff changeset
3422 gimple *stride_def = SSA_NAME_DEF_STMT (c->stride);
kono
parents:
diff changeset
3423 basic_block stride_bb = gimple_bb (stride_def);
kono
parents:
diff changeset
3424
kono
parents:
diff changeset
3425 if (stride_bb && !dominated_by_p (CDI_DOMINATORS, bb, stride_bb))
kono
parents:
diff changeset
3426 {
kono
parents:
diff changeset
3427 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3428 fprintf (dump_file,
kono
parents:
diff changeset
3429 "Initializer #%d cannot be legally placed\n", i);
kono
parents:
diff changeset
3430 incr_vec[i].cost = COST_INFINITE;
kono
parents:
diff changeset
3431 continue;
kono
parents:
diff changeset
3432 }
kono
parents:
diff changeset
3433
kono
parents:
diff changeset
3434 /* If the nominal stride has a different type than the recorded
kono
parents:
diff changeset
3435 stride type, build a cast from the nominal stride to that type. */
kono
parents:
diff changeset
3436 if (!types_compatible_p (TREE_TYPE (c->stride), c->stride_type))
kono
parents:
diff changeset
3437 {
kono
parents:
diff changeset
3438 init_stride = make_temp_ssa_name (c->stride_type, NULL, "slsr");
kono
parents:
diff changeset
3439 cast_stmt = gimple_build_assign (init_stride, NOP_EXPR, c->stride);
kono
parents:
diff changeset
3440 }
kono
parents:
diff changeset
3441 else
kono
parents:
diff changeset
3442 init_stride = c->stride;
kono
parents:
diff changeset
3443
kono
parents:
diff changeset
3444 /* Create a new SSA name to hold the initializer's value. */
kono
parents:
diff changeset
3445 new_name = make_temp_ssa_name (c->stride_type, NULL, "slsr");
kono
parents:
diff changeset
3446 incr_vec[i].initializer = new_name;
kono
parents:
diff changeset
3447
kono
parents:
diff changeset
3448 /* Create the initializer and insert it in the latest possible
kono
parents:
diff changeset
3449 dominating position. */
kono
parents:
diff changeset
3450 incr_tree = wide_int_to_tree (c->stride_type, incr);
kono
parents:
diff changeset
3451 init_stmt = gimple_build_assign (new_name, MULT_EXPR,
kono
parents:
diff changeset
3452 init_stride, incr_tree);
kono
parents:
diff changeset
3453 if (where)
kono
parents:
diff changeset
3454 {
kono
parents:
diff changeset
3455 gimple_stmt_iterator gsi = gsi_for_stmt (where->cand_stmt);
kono
parents:
diff changeset
3456 location_t loc = gimple_location (where->cand_stmt);
kono
parents:
diff changeset
3457
kono
parents:
diff changeset
3458 if (cast_stmt)
kono
parents:
diff changeset
3459 {
kono
parents:
diff changeset
3460 gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3461 gimple_set_location (cast_stmt, loc);
kono
parents:
diff changeset
3462 }
kono
parents:
diff changeset
3463
kono
parents:
diff changeset
3464 gsi_insert_before (&gsi, init_stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3465 gimple_set_location (init_stmt, loc);
kono
parents:
diff changeset
3466 }
kono
parents:
diff changeset
3467 else
kono
parents:
diff changeset
3468 {
kono
parents:
diff changeset
3469 gimple_stmt_iterator gsi = gsi_last_bb (bb);
kono
parents:
diff changeset
3470 gimple *basis_stmt = lookup_cand (c->basis)->cand_stmt;
kono
parents:
diff changeset
3471 location_t loc = gimple_location (basis_stmt);
kono
parents:
diff changeset
3472
kono
parents:
diff changeset
3473 if (!gsi_end_p (gsi) && stmt_ends_bb_p (gsi_stmt (gsi)))
kono
parents:
diff changeset
3474 {
kono
parents:
diff changeset
3475 if (cast_stmt)
kono
parents:
diff changeset
3476 {
kono
parents:
diff changeset
3477 gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3478 gimple_set_location (cast_stmt, loc);
kono
parents:
diff changeset
3479 }
kono
parents:
diff changeset
3480 gsi_insert_before (&gsi, init_stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3481 }
kono
parents:
diff changeset
3482 else
kono
parents:
diff changeset
3483 {
kono
parents:
diff changeset
3484 if (cast_stmt)
kono
parents:
diff changeset
3485 {
kono
parents:
diff changeset
3486 gsi_insert_after (&gsi, cast_stmt, GSI_NEW_STMT);
kono
parents:
diff changeset
3487 gimple_set_location (cast_stmt, loc);
kono
parents:
diff changeset
3488 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3489 gsi_insert_after (&gsi, init_stmt, GSI_NEW_STMT);
111
kono
parents:
diff changeset
3490 }
kono
parents:
diff changeset
3491
kono
parents:
diff changeset
3492 gimple_set_location (init_stmt, gimple_location (basis_stmt));
kono
parents:
diff changeset
3493 }
kono
parents:
diff changeset
3494
kono
parents:
diff changeset
3495 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3496 {
kono
parents:
diff changeset
3497 if (cast_stmt)
kono
parents:
diff changeset
3498 {
kono
parents:
diff changeset
3499 fputs ("Inserting stride cast: ", dump_file);
kono
parents:
diff changeset
3500 print_gimple_stmt (dump_file, cast_stmt, 0);
kono
parents:
diff changeset
3501 }
kono
parents:
diff changeset
3502 fputs ("Inserting initializer: ", dump_file);
kono
parents:
diff changeset
3503 print_gimple_stmt (dump_file, init_stmt, 0);
kono
parents:
diff changeset
3504 }
kono
parents:
diff changeset
3505 }
kono
parents:
diff changeset
3506 }
kono
parents:
diff changeset
3507
kono
parents:
diff changeset
3508 /* Recursive helper function for all_phi_incrs_profitable. */
kono
parents:
diff changeset
3509
kono
parents:
diff changeset
3510 static bool
kono
parents:
diff changeset
3511 all_phi_incrs_profitable_1 (slsr_cand_t c, gphi *phi, int *spread)
kono
parents:
diff changeset
3512 {
kono
parents:
diff changeset
3513 unsigned i;
kono
parents:
diff changeset
3514 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
3515 slsr_cand_t phi_cand = *stmt_cand_map->get (phi);
kono
parents:
diff changeset
3516
kono
parents:
diff changeset
3517 if (phi_cand->visited)
kono
parents:
diff changeset
3518 return true;
kono
parents:
diff changeset
3519
kono
parents:
diff changeset
3520 phi_cand->visited = 1;
kono
parents:
diff changeset
3521 (*spread)++;
kono
parents:
diff changeset
3522
kono
parents:
diff changeset
3523 /* If the basis doesn't dominate the PHI (including when the PHI is
kono
parents:
diff changeset
3524 in the same block as the basis), we won't be able to create a PHI
kono
parents:
diff changeset
3525 using the basis here. */
kono
parents:
diff changeset
3526 basic_block basis_bb = gimple_bb (basis->cand_stmt);
kono
parents:
diff changeset
3527 basic_block phi_bb = gimple_bb (phi);
kono
parents:
diff changeset
3528
kono
parents:
diff changeset
3529 if (phi_bb == basis_bb
kono
parents:
diff changeset
3530 || !dominated_by_p (CDI_DOMINATORS, phi_bb, basis_bb))
kono
parents:
diff changeset
3531 return false;
kono
parents:
diff changeset
3532
kono
parents:
diff changeset
3533 for (i = 0; i < gimple_phi_num_args (phi); i++)
kono
parents:
diff changeset
3534 {
kono
parents:
diff changeset
3535 /* If the PHI arg resides in a block not dominated by the basis,
kono
parents:
diff changeset
3536 we won't be able to create a PHI using the basis here. */
kono
parents:
diff changeset
3537 basic_block pred_bb = gimple_phi_arg_edge (phi, i)->src;
kono
parents:
diff changeset
3538
kono
parents:
diff changeset
3539 if (!dominated_by_p (CDI_DOMINATORS, pred_bb, basis_bb))
kono
parents:
diff changeset
3540 return false;
kono
parents:
diff changeset
3541
kono
parents:
diff changeset
3542 tree arg = gimple_phi_arg_def (phi, i);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3543 gimple *arg_def = SSA_NAME_DEF_STMT (arg);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3544
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3545 if (gimple_code (arg_def) == GIMPLE_PHI)
111
kono
parents:
diff changeset
3546 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3547 if (!all_phi_incrs_profitable_1 (c, as_a <gphi *> (arg_def), spread)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3548 || *spread > MAX_SPREAD)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3549 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3550 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3551 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3552 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3553 int j;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3554 widest_int increment;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3555
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3556 if (operand_equal_p (arg, phi_cand->base_expr, 0))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3557 increment = -basis->index;
111
kono
parents:
diff changeset
3558 else
kono
parents:
diff changeset
3559 {
kono
parents:
diff changeset
3560 slsr_cand_t arg_cand = base_cand_from_table (arg);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3561 increment = arg_cand->index - basis->index;
111
kono
parents:
diff changeset
3562 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3563
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3564 if (!address_arithmetic_p && wi::neg_p (increment))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3565 increment = -increment;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3566
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3567 j = incr_vec_index (increment);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3568
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3569 if (dump_file && (dump_flags & TDF_DETAILS))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3570 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3571 fprintf (dump_file, " Conditional candidate %d, phi: ",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3572 c->cand_num);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3573 print_gimple_stmt (dump_file, phi, 0);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3574 fputs (" increment: ", dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3575 print_decs (increment, dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3576 if (j < 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3577 fprintf (dump_file,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3578 "\n Not replaced; incr_vec overflow.\n");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3579 else {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3580 fprintf (dump_file, "\n cost: %d\n", incr_vec[j].cost);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3581 if (profitable_increment_p (j))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3582 fputs (" Replacing...\n", dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3583 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3584 fputs (" Not replaced.\n", dump_file);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3585 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3586 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3587
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3588 if (j < 0 || !profitable_increment_p (j))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3589 return false;
111
kono
parents:
diff changeset
3590 }
kono
parents:
diff changeset
3591 }
kono
parents:
diff changeset
3592
kono
parents:
diff changeset
3593 return true;
kono
parents:
diff changeset
3594 }
kono
parents:
diff changeset
3595
kono
parents:
diff changeset
3596 /* Return TRUE iff all required increments for candidates feeding PHI
kono
parents:
diff changeset
3597 are profitable (and legal!) to replace on behalf of candidate C. */
kono
parents:
diff changeset
3598
kono
parents:
diff changeset
3599 static bool
kono
parents:
diff changeset
3600 all_phi_incrs_profitable (slsr_cand_t c, gphi *phi)
kono
parents:
diff changeset
3601 {
kono
parents:
diff changeset
3602 int spread = 0;
kono
parents:
diff changeset
3603 bool retval = all_phi_incrs_profitable_1 (c, phi, &spread);
kono
parents:
diff changeset
3604 clear_visited (phi);
kono
parents:
diff changeset
3605 return retval;
kono
parents:
diff changeset
3606 }
kono
parents:
diff changeset
3607
kono
parents:
diff changeset
3608 /* Create a NOP_EXPR that copies FROM_EXPR into a new SSA name of
kono
parents:
diff changeset
3609 type TO_TYPE, and insert it in front of the statement represented
kono
parents:
diff changeset
3610 by candidate C. Use *NEW_VAR to create the new SSA name. Return
kono
parents:
diff changeset
3611 the new SSA name. */
kono
parents:
diff changeset
3612
kono
parents:
diff changeset
3613 static tree
kono
parents:
diff changeset
3614 introduce_cast_before_cand (slsr_cand_t c, tree to_type, tree from_expr)
kono
parents:
diff changeset
3615 {
kono
parents:
diff changeset
3616 tree cast_lhs;
kono
parents:
diff changeset
3617 gassign *cast_stmt;
kono
parents:
diff changeset
3618 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
kono
parents:
diff changeset
3619
kono
parents:
diff changeset
3620 cast_lhs = make_temp_ssa_name (to_type, NULL, "slsr");
kono
parents:
diff changeset
3621 cast_stmt = gimple_build_assign (cast_lhs, NOP_EXPR, from_expr);
kono
parents:
diff changeset
3622 gimple_set_location (cast_stmt, gimple_location (c->cand_stmt));
kono
parents:
diff changeset
3623 gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
kono
parents:
diff changeset
3624
kono
parents:
diff changeset
3625 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3626 {
kono
parents:
diff changeset
3627 fputs (" Inserting: ", dump_file);
kono
parents:
diff changeset
3628 print_gimple_stmt (dump_file, cast_stmt, 0);
kono
parents:
diff changeset
3629 }
kono
parents:
diff changeset
3630
kono
parents:
diff changeset
3631 return cast_lhs;
kono
parents:
diff changeset
3632 }
kono
parents:
diff changeset
3633
kono
parents:
diff changeset
3634 /* Replace the RHS of the statement represented by candidate C with
kono
parents:
diff changeset
3635 NEW_CODE, NEW_RHS1, and NEW_RHS2, provided that to do so doesn't
kono
parents:
diff changeset
3636 leave C unchanged or just interchange its operands. The original
kono
parents:
diff changeset
3637 operation and operands are in OLD_CODE, OLD_RHS1, and OLD_RHS2.
kono
parents:
diff changeset
3638 If the replacement was made and we are doing a details dump,
kono
parents:
diff changeset
3639 return the revised statement, else NULL. */
kono
parents:
diff changeset
3640
kono
parents:
diff changeset
3641 static gimple *
kono
parents:
diff changeset
3642 replace_rhs_if_not_dup (enum tree_code new_code, tree new_rhs1, tree new_rhs2,
kono
parents:
diff changeset
3643 enum tree_code old_code, tree old_rhs1, tree old_rhs2,
kono
parents:
diff changeset
3644 slsr_cand_t c)
kono
parents:
diff changeset
3645 {
kono
parents:
diff changeset
3646 if (new_code != old_code
kono
parents:
diff changeset
3647 || ((!operand_equal_p (new_rhs1, old_rhs1, 0)
kono
parents:
diff changeset
3648 || !operand_equal_p (new_rhs2, old_rhs2, 0))
kono
parents:
diff changeset
3649 && (!operand_equal_p (new_rhs1, old_rhs2, 0)
kono
parents:
diff changeset
3650 || !operand_equal_p (new_rhs2, old_rhs1, 0))))
kono
parents:
diff changeset
3651 {
kono
parents:
diff changeset
3652 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3653 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
3654 gimple_assign_set_rhs_with_ops (&gsi, new_code, new_rhs1, new_rhs2);
kono
parents:
diff changeset
3655 update_stmt (gsi_stmt (gsi));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3656 while (cc)
111
kono
parents:
diff changeset
3657 {
kono
parents:
diff changeset
3658 cc->cand_stmt = gsi_stmt (gsi);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3659 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
3660 }
kono
parents:
diff changeset
3661
kono
parents:
diff changeset
3662 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3663 return gsi_stmt (gsi);
kono
parents:
diff changeset
3664 }
kono
parents:
diff changeset
3665
kono
parents:
diff changeset
3666 else if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3667 fputs (" (duplicate, not actually replacing)\n", dump_file);
kono
parents:
diff changeset
3668
kono
parents:
diff changeset
3669 return NULL;
kono
parents:
diff changeset
3670 }
kono
parents:
diff changeset
3671
kono
parents:
diff changeset
3672 /* Strength-reduce the statement represented by candidate C by replacing
kono
parents:
diff changeset
3673 it with an equivalent addition or subtraction. I is the index into
kono
parents:
diff changeset
3674 the increment vector identifying C's increment. NEW_VAR is used to
kono
parents:
diff changeset
3675 create a new SSA name if a cast needs to be introduced. BASIS_NAME
kono
parents:
diff changeset
3676 is the rhs1 to use in creating the add/subtract. */
kono
parents:
diff changeset
3677
kono
parents:
diff changeset
3678 static void
kono
parents:
diff changeset
3679 replace_one_candidate (slsr_cand_t c, unsigned i, tree basis_name)
kono
parents:
diff changeset
3680 {
kono
parents:
diff changeset
3681 gimple *stmt_to_print = NULL;
kono
parents:
diff changeset
3682 tree orig_rhs1, orig_rhs2;
kono
parents:
diff changeset
3683 tree rhs2;
kono
parents:
diff changeset
3684 enum tree_code orig_code, repl_code;
kono
parents:
diff changeset
3685 widest_int cand_incr;
kono
parents:
diff changeset
3686
kono
parents:
diff changeset
3687 orig_code = gimple_assign_rhs_code (c->cand_stmt);
kono
parents:
diff changeset
3688 orig_rhs1 = gimple_assign_rhs1 (c->cand_stmt);
kono
parents:
diff changeset
3689 orig_rhs2 = gimple_assign_rhs2 (c->cand_stmt);
kono
parents:
diff changeset
3690 cand_incr = cand_increment (c);
kono
parents:
diff changeset
3691
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3692 /* If orig_rhs2 is NULL, we have already replaced this in situ with
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3693 a copy statement under another interpretation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3694 if (!orig_rhs2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3695 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3696
111
kono
parents:
diff changeset
3697 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3698 {
kono
parents:
diff changeset
3699 fputs ("Replacing: ", dump_file);
kono
parents:
diff changeset
3700 print_gimple_stmt (dump_file, c->cand_stmt, 0);
kono
parents:
diff changeset
3701 stmt_to_print = c->cand_stmt;
kono
parents:
diff changeset
3702 }
kono
parents:
diff changeset
3703
kono
parents:
diff changeset
3704 if (address_arithmetic_p)
kono
parents:
diff changeset
3705 repl_code = POINTER_PLUS_EXPR;
kono
parents:
diff changeset
3706 else
kono
parents:
diff changeset
3707 repl_code = PLUS_EXPR;
kono
parents:
diff changeset
3708
kono
parents:
diff changeset
3709 /* If the increment has an initializer T_0, replace the candidate
kono
parents:
diff changeset
3710 statement with an add of the basis name and the initializer. */
kono
parents:
diff changeset
3711 if (incr_vec[i].initializer)
kono
parents:
diff changeset
3712 {
kono
parents:
diff changeset
3713 tree init_type = TREE_TYPE (incr_vec[i].initializer);
kono
parents:
diff changeset
3714 tree orig_type = TREE_TYPE (orig_rhs2);
kono
parents:
diff changeset
3715
kono
parents:
diff changeset
3716 if (types_compatible_p (orig_type, init_type))
kono
parents:
diff changeset
3717 rhs2 = incr_vec[i].initializer;
kono
parents:
diff changeset
3718 else
kono
parents:
diff changeset
3719 rhs2 = introduce_cast_before_cand (c, orig_type,
kono
parents:
diff changeset
3720 incr_vec[i].initializer);
kono
parents:
diff changeset
3721
kono
parents:
diff changeset
3722 if (incr_vec[i].incr != cand_incr)
kono
parents:
diff changeset
3723 {
kono
parents:
diff changeset
3724 gcc_assert (repl_code == PLUS_EXPR);
kono
parents:
diff changeset
3725 repl_code = MINUS_EXPR;
kono
parents:
diff changeset
3726 }
kono
parents:
diff changeset
3727
kono
parents:
diff changeset
3728 stmt_to_print = replace_rhs_if_not_dup (repl_code, basis_name, rhs2,
kono
parents:
diff changeset
3729 orig_code, orig_rhs1, orig_rhs2,
kono
parents:
diff changeset
3730 c);
kono
parents:
diff changeset
3731 }
kono
parents:
diff changeset
3732
kono
parents:
diff changeset
3733 /* Otherwise, the increment is one of -1, 0, and 1. Replace
kono
parents:
diff changeset
3734 with a subtract of the stride from the basis name, a copy
kono
parents:
diff changeset
3735 from the basis name, or an add of the stride to the basis
kono
parents:
diff changeset
3736 name, respectively. It may be necessary to introduce a
kono
parents:
diff changeset
3737 cast (or reuse an existing cast). */
kono
parents:
diff changeset
3738 else if (cand_incr == 1)
kono
parents:
diff changeset
3739 {
kono
parents:
diff changeset
3740 tree stride_type = TREE_TYPE (c->stride);
kono
parents:
diff changeset
3741 tree orig_type = TREE_TYPE (orig_rhs2);
kono
parents:
diff changeset
3742
kono
parents:
diff changeset
3743 if (types_compatible_p (orig_type, stride_type))
kono
parents:
diff changeset
3744 rhs2 = c->stride;
kono
parents:
diff changeset
3745 else
kono
parents:
diff changeset
3746 rhs2 = introduce_cast_before_cand (c, orig_type, c->stride);
kono
parents:
diff changeset
3747
kono
parents:
diff changeset
3748 stmt_to_print = replace_rhs_if_not_dup (repl_code, basis_name, rhs2,
kono
parents:
diff changeset
3749 orig_code, orig_rhs1, orig_rhs2,
kono
parents:
diff changeset
3750 c);
kono
parents:
diff changeset
3751 }
kono
parents:
diff changeset
3752
kono
parents:
diff changeset
3753 else if (cand_incr == -1)
kono
parents:
diff changeset
3754 {
kono
parents:
diff changeset
3755 tree stride_type = TREE_TYPE (c->stride);
kono
parents:
diff changeset
3756 tree orig_type = TREE_TYPE (orig_rhs2);
kono
parents:
diff changeset
3757 gcc_assert (repl_code != POINTER_PLUS_EXPR);
kono
parents:
diff changeset
3758
kono
parents:
diff changeset
3759 if (types_compatible_p (orig_type, stride_type))
kono
parents:
diff changeset
3760 rhs2 = c->stride;
kono
parents:
diff changeset
3761 else
kono
parents:
diff changeset
3762 rhs2 = introduce_cast_before_cand (c, orig_type, c->stride);
kono
parents:
diff changeset
3763
kono
parents:
diff changeset
3764 if (orig_code != MINUS_EXPR
kono
parents:
diff changeset
3765 || !operand_equal_p (basis_name, orig_rhs1, 0)
kono
parents:
diff changeset
3766 || !operand_equal_p (rhs2, orig_rhs2, 0))
kono
parents:
diff changeset
3767 {
kono
parents:
diff changeset
3768 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3769 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
3770 gimple_assign_set_rhs_with_ops (&gsi, MINUS_EXPR, basis_name, rhs2);
kono
parents:
diff changeset
3771 update_stmt (gsi_stmt (gsi));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3772 while (cc)
111
kono
parents:
diff changeset
3773 {
kono
parents:
diff changeset
3774 cc->cand_stmt = gsi_stmt (gsi);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3775 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
3776 }
kono
parents:
diff changeset
3777
kono
parents:
diff changeset
3778 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3779 stmt_to_print = gsi_stmt (gsi);
kono
parents:
diff changeset
3780 }
kono
parents:
diff changeset
3781 else if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3782 fputs (" (duplicate, not actually replacing)\n", dump_file);
kono
parents:
diff changeset
3783 }
kono
parents:
diff changeset
3784
kono
parents:
diff changeset
3785 else if (cand_incr == 0)
kono
parents:
diff changeset
3786 {
kono
parents:
diff changeset
3787 tree lhs = gimple_assign_lhs (c->cand_stmt);
kono
parents:
diff changeset
3788 tree lhs_type = TREE_TYPE (lhs);
kono
parents:
diff changeset
3789 tree basis_type = TREE_TYPE (basis_name);
kono
parents:
diff changeset
3790
kono
parents:
diff changeset
3791 if (types_compatible_p (lhs_type, basis_type))
kono
parents:
diff changeset
3792 {
kono
parents:
diff changeset
3793 gassign *copy_stmt = gimple_build_assign (lhs, basis_name);
kono
parents:
diff changeset
3794 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3795 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
3796 gimple_set_location (copy_stmt, gimple_location (c->cand_stmt));
kono
parents:
diff changeset
3797 gsi_replace (&gsi, copy_stmt, false);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3798 while (cc)
111
kono
parents:
diff changeset
3799 {
kono
parents:
diff changeset
3800 cc->cand_stmt = copy_stmt;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3801 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
3802 }
kono
parents:
diff changeset
3803
kono
parents:
diff changeset
3804 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3805 stmt_to_print = copy_stmt;
kono
parents:
diff changeset
3806 }
kono
parents:
diff changeset
3807 else
kono
parents:
diff changeset
3808 {
kono
parents:
diff changeset
3809 gimple_stmt_iterator gsi = gsi_for_stmt (c->cand_stmt);
kono
parents:
diff changeset
3810 gassign *cast_stmt = gimple_build_assign (lhs, NOP_EXPR, basis_name);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3811 slsr_cand_t cc = lookup_cand (c->first_interp);
111
kono
parents:
diff changeset
3812 gimple_set_location (cast_stmt, gimple_location (c->cand_stmt));
kono
parents:
diff changeset
3813 gsi_replace (&gsi, cast_stmt, false);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3814 while (cc)
111
kono
parents:
diff changeset
3815 {
kono
parents:
diff changeset
3816 cc->cand_stmt = cast_stmt;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3817 cc = lookup_cand (cc->next_interp);
111
kono
parents:
diff changeset
3818 }
kono
parents:
diff changeset
3819
kono
parents:
diff changeset
3820 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3821 stmt_to_print = cast_stmt;
kono
parents:
diff changeset
3822 }
kono
parents:
diff changeset
3823 }
kono
parents:
diff changeset
3824 else
kono
parents:
diff changeset
3825 gcc_unreachable ();
kono
parents:
diff changeset
3826
kono
parents:
diff changeset
3827 if (dump_file && (dump_flags & TDF_DETAILS) && stmt_to_print)
kono
parents:
diff changeset
3828 {
kono
parents:
diff changeset
3829 fputs ("With: ", dump_file);
kono
parents:
diff changeset
3830 print_gimple_stmt (dump_file, stmt_to_print, 0);
kono
parents:
diff changeset
3831 fputs ("\n", dump_file);
kono
parents:
diff changeset
3832 }
kono
parents:
diff changeset
3833 }
kono
parents:
diff changeset
3834
kono
parents:
diff changeset
3835 /* For each candidate in the tree rooted at C, replace it with
kono
parents:
diff changeset
3836 an increment if such has been shown to be profitable. */
kono
parents:
diff changeset
3837
kono
parents:
diff changeset
3838 static void
kono
parents:
diff changeset
3839 replace_profitable_candidates (slsr_cand_t c)
kono
parents:
diff changeset
3840 {
kono
parents:
diff changeset
3841 if (!cand_already_replaced (c))
kono
parents:
diff changeset
3842 {
kono
parents:
diff changeset
3843 widest_int increment = cand_abs_increment (c);
kono
parents:
diff changeset
3844 enum tree_code orig_code = gimple_assign_rhs_code (c->cand_stmt);
kono
parents:
diff changeset
3845 int i;
kono
parents:
diff changeset
3846
kono
parents:
diff changeset
3847 i = incr_vec_index (increment);
kono
parents:
diff changeset
3848
kono
parents:
diff changeset
3849 /* Only process profitable increments. Nothing useful can be done
kono
parents:
diff changeset
3850 to a cast or copy. */
kono
parents:
diff changeset
3851 if (i >= 0
kono
parents:
diff changeset
3852 && profitable_increment_p (i)
kono
parents:
diff changeset
3853 && orig_code != SSA_NAME
kono
parents:
diff changeset
3854 && !CONVERT_EXPR_CODE_P (orig_code))
kono
parents:
diff changeset
3855 {
kono
parents:
diff changeset
3856 if (phi_dependent_cand_p (c))
kono
parents:
diff changeset
3857 {
kono
parents:
diff changeset
3858 gphi *phi = as_a <gphi *> (lookup_cand (c->def_phi)->cand_stmt);
kono
parents:
diff changeset
3859
kono
parents:
diff changeset
3860 if (all_phi_incrs_profitable (c, phi))
kono
parents:
diff changeset
3861 {
kono
parents:
diff changeset
3862 /* Look up the LHS SSA name from C's basis. This will be
kono
parents:
diff changeset
3863 the RHS1 of the adds we will introduce to create new
kono
parents:
diff changeset
3864 phi arguments. */
kono
parents:
diff changeset
3865 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
3866 tree basis_name = gimple_assign_lhs (basis->cand_stmt);
kono
parents:
diff changeset
3867
kono
parents:
diff changeset
3868 /* Create a new phi statement that will represent C's true
kono
parents:
diff changeset
3869 basis after the transformation is complete. */
kono
parents:
diff changeset
3870 location_t loc = gimple_location (c->cand_stmt);
kono
parents:
diff changeset
3871 tree name = create_phi_basis (c, phi, basis_name,
kono
parents:
diff changeset
3872 loc, UNKNOWN_STRIDE);
kono
parents:
diff changeset
3873
kono
parents:
diff changeset
3874 /* Replace C with an add of the new basis phi and the
kono
parents:
diff changeset
3875 increment. */
kono
parents:
diff changeset
3876 replace_one_candidate (c, i, name);
kono
parents:
diff changeset
3877 }
kono
parents:
diff changeset
3878 }
kono
parents:
diff changeset
3879 else
kono
parents:
diff changeset
3880 {
kono
parents:
diff changeset
3881 slsr_cand_t basis = lookup_cand (c->basis);
kono
parents:
diff changeset
3882 tree basis_name = gimple_assign_lhs (basis->cand_stmt);
kono
parents:
diff changeset
3883 replace_one_candidate (c, i, basis_name);
kono
parents:
diff changeset
3884 }
kono
parents:
diff changeset
3885 }
kono
parents:
diff changeset
3886 }
kono
parents:
diff changeset
3887
kono
parents:
diff changeset
3888 if (c->sibling)
kono
parents:
diff changeset
3889 replace_profitable_candidates (lookup_cand (c->sibling));
kono
parents:
diff changeset
3890
kono
parents:
diff changeset
3891 if (c->dependent)
kono
parents:
diff changeset
3892 replace_profitable_candidates (lookup_cand (c->dependent));
kono
parents:
diff changeset
3893 }
kono
parents:
diff changeset
3894
kono
parents:
diff changeset
3895 /* Analyze costs of related candidates in the candidate vector,
kono
parents:
diff changeset
3896 and make beneficial replacements. */
kono
parents:
diff changeset
3897
kono
parents:
diff changeset
3898 static void
kono
parents:
diff changeset
3899 analyze_candidates_and_replace (void)
kono
parents:
diff changeset
3900 {
kono
parents:
diff changeset
3901 unsigned i;
kono
parents:
diff changeset
3902 slsr_cand_t c;
kono
parents:
diff changeset
3903
kono
parents:
diff changeset
3904 /* Each candidate that has a null basis and a non-null
kono
parents:
diff changeset
3905 dependent is the root of a tree of related statements.
kono
parents:
diff changeset
3906 Analyze each tree to determine a subset of those
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3907 statements that can be replaced with maximum benefit.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3908
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3909 Note the first NULL element is skipped. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3910 FOR_EACH_VEC_ELT_FROM (cand_vec, i, c, 1)
111
kono
parents:
diff changeset
3911 {
kono
parents:
diff changeset
3912 slsr_cand_t first_dep;
kono
parents:
diff changeset
3913
kono
parents:
diff changeset
3914 if (c->basis != 0 || c->dependent == 0)
kono
parents:
diff changeset
3915 continue;
kono
parents:
diff changeset
3916
kono
parents:
diff changeset
3917 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
3918 fprintf (dump_file, "\nProcessing dependency tree rooted at %d.\n",
kono
parents:
diff changeset
3919 c->cand_num);
kono
parents:
diff changeset
3920
kono
parents:
diff changeset
3921 first_dep = lookup_cand (c->dependent);
kono
parents:
diff changeset
3922
kono
parents:
diff changeset
3923 /* If this is a chain of CAND_REFs, unconditionally replace
kono
parents:
diff changeset
3924 each of them with a strength-reduced data reference. */
kono
parents:
diff changeset
3925 if (c->kind == CAND_REF)
kono
parents:
diff changeset
3926 replace_refs (c);
kono
parents:
diff changeset
3927
kono
parents:
diff changeset
3928 /* If the common stride of all related candidates is a known
kono
parents:
diff changeset
3929 constant, each candidate without a phi-dependence can be
kono
parents:
diff changeset
3930 profitably replaced. Each replaces a multiply by a single
kono
parents:
diff changeset
3931 add, with the possibility that a feeding add also goes dead.
kono
parents:
diff changeset
3932 A candidate with a phi-dependence is replaced only if the
kono
parents:
diff changeset
3933 compensation code it requires is offset by the strength
kono
parents:
diff changeset
3934 reduction savings. */
kono
parents:
diff changeset
3935 else if (TREE_CODE (c->stride) == INTEGER_CST)
kono
parents:
diff changeset
3936 replace_uncond_cands_and_profitable_phis (first_dep);
kono
parents:
diff changeset
3937
kono
parents:
diff changeset
3938 /* When the stride is an SSA name, it may still be profitable
kono
parents:
diff changeset
3939 to replace some or all of the dependent candidates, depending
kono
parents:
diff changeset
3940 on whether the introduced increments can be reused, or are
kono
parents:
diff changeset
3941 less expensive to calculate than the replaced statements. */
kono
parents:
diff changeset
3942 else
kono
parents:
diff changeset
3943 {
kono
parents:
diff changeset
3944 machine_mode mode;
kono
parents:
diff changeset
3945 bool speed;
kono
parents:
diff changeset
3946
kono
parents:
diff changeset
3947 /* Determine whether we'll be generating pointer arithmetic
kono
parents:
diff changeset
3948 when replacing candidates. */
kono
parents:
diff changeset
3949 address_arithmetic_p = (c->kind == CAND_ADD
kono
parents:
diff changeset
3950 && POINTER_TYPE_P (c->cand_type));
kono
parents:
diff changeset
3951
kono
parents:
diff changeset
3952 /* If all candidates have already been replaced under other
kono
parents:
diff changeset
3953 interpretations, nothing remains to be done. */
kono
parents:
diff changeset
3954 if (!count_candidates (c))
kono
parents:
diff changeset
3955 continue;
kono
parents:
diff changeset
3956
kono
parents:
diff changeset
3957 /* Construct an array of increments for this candidate chain. */
kono
parents:
diff changeset
3958 incr_vec = XNEWVEC (incr_info, MAX_INCR_VEC_LEN);
kono
parents:
diff changeset
3959 incr_vec_len = 0;
kono
parents:
diff changeset
3960 record_increments (c);
kono
parents:
diff changeset
3961
kono
parents:
diff changeset
3962 /* Determine which increments are profitable to replace. */
kono
parents:
diff changeset
3963 mode = TYPE_MODE (TREE_TYPE (gimple_assign_lhs (c->cand_stmt)));
kono
parents:
diff changeset
3964 speed = optimize_cands_for_speed_p (c);
kono
parents:
diff changeset
3965 analyze_increments (first_dep, mode, speed);
kono
parents:
diff changeset
3966
kono
parents:
diff changeset
3967 /* Insert initializers of the form T_0 = stride * increment
kono
parents:
diff changeset
3968 for use in profitable replacements. */
kono
parents:
diff changeset
3969 insert_initializers (first_dep);
kono
parents:
diff changeset
3970 dump_incr_vec ();
kono
parents:
diff changeset
3971
kono
parents:
diff changeset
3972 /* Perform the replacements. */
kono
parents:
diff changeset
3973 replace_profitable_candidates (first_dep);
kono
parents:
diff changeset
3974 free (incr_vec);
kono
parents:
diff changeset
3975 }
kono
parents:
diff changeset
3976 }
kono
parents:
diff changeset
3977
kono
parents:
diff changeset
3978 /* For conditional candidates, we may have uncommitted insertions
kono
parents:
diff changeset
3979 on edges to clean up. */
kono
parents:
diff changeset
3980 gsi_commit_edge_inserts ();
kono
parents:
diff changeset
3981 }
kono
parents:
diff changeset
3982
kono
parents:
diff changeset
3983 namespace {
kono
parents:
diff changeset
3984
kono
parents:
diff changeset
3985 const pass_data pass_data_strength_reduction =
kono
parents:
diff changeset
3986 {
kono
parents:
diff changeset
3987 GIMPLE_PASS, /* type */
kono
parents:
diff changeset
3988 "slsr", /* name */
kono
parents:
diff changeset
3989 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
3990 TV_GIMPLE_SLSR, /* tv_id */
kono
parents:
diff changeset
3991 ( PROP_cfg | PROP_ssa ), /* properties_required */
kono
parents:
diff changeset
3992 0, /* properties_provided */
kono
parents:
diff changeset
3993 0, /* properties_destroyed */
kono
parents:
diff changeset
3994 0, /* todo_flags_start */
kono
parents:
diff changeset
3995 0, /* todo_flags_finish */
kono
parents:
diff changeset
3996 };
kono
parents:
diff changeset
3997
kono
parents:
diff changeset
3998 class pass_strength_reduction : public gimple_opt_pass
kono
parents:
diff changeset
3999 {
kono
parents:
diff changeset
4000 public:
kono
parents:
diff changeset
4001 pass_strength_reduction (gcc::context *ctxt)
kono
parents:
diff changeset
4002 : gimple_opt_pass (pass_data_strength_reduction, ctxt)
kono
parents:
diff changeset
4003 {}
kono
parents:
diff changeset
4004
kono
parents:
diff changeset
4005 /* opt_pass methods: */
kono
parents:
diff changeset
4006 virtual bool gate (function *) { return flag_tree_slsr; }
kono
parents:
diff changeset
4007 virtual unsigned int execute (function *);
kono
parents:
diff changeset
4008
kono
parents:
diff changeset
4009 }; // class pass_strength_reduction
kono
parents:
diff changeset
4010
kono
parents:
diff changeset
4011 unsigned
kono
parents:
diff changeset
4012 pass_strength_reduction::execute (function *fun)
kono
parents:
diff changeset
4013 {
kono
parents:
diff changeset
4014 /* Create the obstack where candidates will reside. */
kono
parents:
diff changeset
4015 gcc_obstack_init (&cand_obstack);
kono
parents:
diff changeset
4016
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4017 /* Allocate the candidate vector and initialize the first NULL element. */
111
kono
parents:
diff changeset
4018 cand_vec.create (128);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4019 cand_vec.safe_push (NULL);
111
kono
parents:
diff changeset
4020
kono
parents:
diff changeset
4021 /* Allocate the mapping from statements to candidate indices. */
kono
parents:
diff changeset
4022 stmt_cand_map = new hash_map<gimple *, slsr_cand_t>;
kono
parents:
diff changeset
4023
kono
parents:
diff changeset
4024 /* Create the obstack where candidate chains will reside. */
kono
parents:
diff changeset
4025 gcc_obstack_init (&chain_obstack);
kono
parents:
diff changeset
4026
kono
parents:
diff changeset
4027 /* Allocate the mapping from base expressions to candidate chains. */
kono
parents:
diff changeset
4028 base_cand_map = new hash_table<cand_chain_hasher> (500);
kono
parents:
diff changeset
4029
kono
parents:
diff changeset
4030 /* Allocate the mapping from bases to alternative bases. */
kono
parents:
diff changeset
4031 alt_base_map = new hash_map<tree, tree>;
kono
parents:
diff changeset
4032
kono
parents:
diff changeset
4033 /* Initialize the loop optimizer. We need to detect flow across
kono
parents:
diff changeset
4034 back edges, and this gives us dominator information as well. */
kono
parents:
diff changeset
4035 loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
kono
parents:
diff changeset
4036
kono
parents:
diff changeset
4037 /* Walk the CFG in predominator order looking for strength reduction
kono
parents:
diff changeset
4038 candidates. */
kono
parents:
diff changeset
4039 find_candidates_dom_walker (CDI_DOMINATORS)
kono
parents:
diff changeset
4040 .walk (fun->cfg->x_entry_block_ptr);
kono
parents:
diff changeset
4041
kono
parents:
diff changeset
4042 if (dump_file && (dump_flags & TDF_DETAILS))
kono
parents:
diff changeset
4043 {
kono
parents:
diff changeset
4044 dump_cand_vec ();
kono
parents:
diff changeset
4045 dump_cand_chains ();
kono
parents:
diff changeset
4046 }
kono
parents:
diff changeset
4047
kono
parents:
diff changeset
4048 delete alt_base_map;
kono
parents:
diff changeset
4049 free_affine_expand_cache (&name_expansions);
kono
parents:
diff changeset
4050
kono
parents:
diff changeset
4051 /* Analyze costs and make appropriate replacements. */
kono
parents:
diff changeset
4052 analyze_candidates_and_replace ();
kono
parents:
diff changeset
4053
kono
parents:
diff changeset
4054 loop_optimizer_finalize ();
kono
parents:
diff changeset
4055 delete base_cand_map;
kono
parents:
diff changeset
4056 base_cand_map = NULL;
kono
parents:
diff changeset
4057 obstack_free (&chain_obstack, NULL);
kono
parents:
diff changeset
4058 delete stmt_cand_map;
kono
parents:
diff changeset
4059 cand_vec.release ();
kono
parents:
diff changeset
4060 obstack_free (&cand_obstack, NULL);
kono
parents:
diff changeset
4061
kono
parents:
diff changeset
4062 return 0;
kono
parents:
diff changeset
4063 }
kono
parents:
diff changeset
4064
kono
parents:
diff changeset
4065 } // anon namespace
kono
parents:
diff changeset
4066
kono
parents:
diff changeset
4067 gimple_opt_pass *
kono
parents:
diff changeset
4068 make_pass_strength_reduction (gcc::context *ctxt)
kono
parents:
diff changeset
4069 {
kono
parents:
diff changeset
4070 return new pass_strength_reduction (ctxt);
kono
parents:
diff changeset
4071 }