]>
Commit | Line | Data |
---|---|---|
00509c04 | 1 | /* Routines for performing Temporary Expression Replacement (TER) in SSA trees. |
818ab71a | 2 | Copyright (C) 2003-2016 Free Software Foundation, Inc. |
00509c04 AM |
3 | Contributed by Andrew MacLeod <amacleod@redhat.com> |
4 | ||
5 | This file is part of GCC. | |
6 | ||
7 | GCC is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9dcd6f09 | 9 | the Free Software Foundation; either version 3, or (at your option) |
00509c04 AM |
10 | any later version. |
11 | ||
12 | GCC is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
9dcd6f09 NC |
18 | along with GCC; see the file COPYING3. If not see |
19 | <http://www.gnu.org/licenses/>. */ | |
00509c04 AM |
20 | |
21 | ||
22 | #include "config.h" | |
23 | #include "system.h" | |
24 | #include "coretypes.h" | |
c7131fb2 | 25 | #include "backend.h" |
00509c04 | 26 | #include "tree.h" |
c7131fb2 | 27 | #include "gimple.h" |
c7131fb2 | 28 | #include "ssa.h" |
957060b5 | 29 | #include "gimple-pretty-print.h" |
5be5c238 | 30 | #include "gimple-iterator.h" |
7ee2468b | 31 | #include "dumpfile.h" |
8e9055ae AM |
32 | #include "tree-ssa-live.h" |
33 | #include "tree-ssa-ter.h" | |
78bca40d | 34 | #include "tree-outof-ssa.h" |
9f1363cd | 35 | #include "gimple-walk.h" |
00509c04 AM |
36 | |
37 | ||
38 | /* Temporary Expression Replacement (TER) | |
39 | ||
40 | Replace SSA version variables during out-of-ssa with their defining | |
b8698a0f | 41 | expression if there is only one use of the variable. |
00509c04 AM |
42 | |
43 | This pass is required in order for the RTL expansion pass to see larger | |
44 | chunks of code. This allows it to make better choices on RTL pattern | |
45 | selection. When expand is rewritten and merged with out-of-ssa, and | |
b8698a0f | 46 | understands SSA, this should be eliminated. |
00509c04 AM |
47 | |
48 | A pass is made through the function, one block at a time. No cross block | |
49 | information is tracked. | |
50 | ||
51 | Variables which only have one use, and whose defining stmt is considered | |
78bca40d | 52 | a replaceable expression (see ssa_is_replaceable_p) are tracked to see whether |
b8698a0f L |
53 | they can be replaced at their use location. |
54 | ||
00509c04 AM |
55 | n_12 = C * 10 |
56 | a_2 = b_5 + 6 | |
57 | v_9 = a_2 * n_12 | |
58 | ||
59 | if there are the only use of n_12 and a_2, TER will substitute in their | |
60 | expressions in v_9, and end up with: | |
61 | ||
62 | v_9 = (b_5 + 6) * (C * 10) | |
63 | ||
64 | which will then have the ssa_name assigned to regular variables, and the | |
fa10beec | 65 | resulting code which will be passed to the expander looks something like: |
00509c04 AM |
66 | |
67 | v = (b + 6) * (C * 10) | |
68 | ||
b8698a0f L |
69 | |
70 | This requires ensuring that none of the variables used by the expression | |
71 | change between the def point and where it is used. Furthermore, if any | |
72 | of the ssa_names used in this expression are themselves replaceable, we | |
73 | have to ensure none of that expressions' arguments change either. | |
74 | Although SSA_NAMES themselves don't change, this pass is performed after | |
75 | coalescing has coalesced different SSA_NAMES together, so there could be a | |
00509c04 | 76 | definition of an SSA_NAME which is coalesced with a use that causes a |
fa10beec | 77 | problem, i.e., |
b8698a0f | 78 | |
00509c04 AM |
79 | PHI b_5 = <b_8(2), b_14(1)> |
80 | <...> | |
81 | a_2 = b_5 + 6 | |
82 | b_8 = c_4 + 4 | |
83 | v_9 = a_2 * n_12 | |
84 | <...> | |
85 | ||
2e226e66 | 86 | If b_5, b_8 and b_14 are all coalesced together... |
00509c04 AM |
87 | The expression b_5 + 6 CANNOT replace the use in the statement defining v_9 |
88 | because b_8 is in fact killing the value of b_5 since they share a partition | |
2e226e66 | 89 | and will be assigned the same memory or register location. |
b8698a0f | 90 | |
00509c04 | 91 | TER implements this but stepping through the instructions in a block and |
2e226e66 | 92 | tracking potential expressions for replacement, and the partitions they are |
00509c04 | 93 | dependent on. Expressions are represented by the SSA_NAME_VERSION of the |
726a989a | 94 | DEF on the LHS of a GIMPLE_ASSIGN and the expression is the RHS. |
00509c04 AM |
95 | |
96 | When a stmt is determined to be a possible replacement expression, the | |
97 | following steps are taken: | |
98 | ||
b8698a0f L |
99 | EXPR_DECL_UID bitmap is allocated and set to the base variable UID of the |
100 | def and any uses in the expression. non-NULL means the expression is being | |
00509c04 | 101 | tracked. The UID's themselves are used to prevent TER substitution into |
fa10beec RW |
102 | accumulating sequences, i.e., |
103 | ||
00509c04 AM |
104 | x = x + y |
105 | x = x + z | |
106 | x = x + w | |
107 | etc. | |
108 | this can result in very large expressions which don't accomplish anything | |
b8698a0f | 109 | see PR tree-optimization/17549. |
00509c04 | 110 | |
b8698a0f | 111 | PARTITION_DEPENDENCIES is another bitmap array, and it has a bit set for any |
00509c04 AM |
112 | partition which is used in the expression. This is primarily used to remove |
113 | an expression from the partition kill lists when a decision is made whether | |
114 | to replace it or not. This is indexed by ssa version number as well, and | |
115 | indicates a partition number. virtual operands are not tracked individually, | |
2e226e66 KH |
116 | but they are summarized by an artificial partition called VIRTUAL_PARTITION. |
117 | This means a MAY or MUST def will kill *ALL* expressions that are dependent | |
00509c04 | 118 | on a virtual operand. |
b8698a0f | 119 | Note that the EXPR_DECL_UID and this bitmap represent very similar |
00509c04 AM |
120 | information, but the info in one is not easy to obtain from the other. |
121 | ||
122 | KILL_LIST is yet another bitmap array, this time it is indexed by partition | |
026c3cfd | 123 | number, and represents a list of active expressions which will no |
00509c04 AM |
124 | longer be valid if a definition into this partition takes place. |
125 | ||
126 | PARTITION_IN_USE is simply a bitmap which is used to track which partitions | |
b8698a0f | 127 | currently have something in their kill list. This is used at the end of |
00509c04 AM |
128 | a block to clear out the KILL_LIST bitmaps at the end of each block. |
129 | ||
b8698a0f | 130 | NEW_REPLACEABLE_DEPENDENCIES is used as a temporary place to store |
fa10beec | 131 | dependencies which will be reused by the current definition. All the uses |
00509c04 AM |
132 | on an expression are processed before anything else is done. If a use is |
133 | determined to be a replaceable expression AND the current stmt is also going | |
134 | to be replaceable, all the dependencies of this replaceable use will be | |
135 | picked up by the current stmt's expression. Rather than recreate them, they | |
136 | are simply copied here and then copied into the new expression when it is | |
137 | processed. | |
138 | ||
139 | a_2 = b_5 + 6 | |
140 | v_8 = a_2 + c_4 | |
141 | ||
b8698a0f | 142 | a_2's expression 'b_5 + 6' is determined to be replaceable at the use |
00509c04 | 143 | location. It is dependent on the partition 'b_5' is in. This is cached into |
fa10beec RW |
144 | the NEW_REPLACEABLE_DEPENDENCIES bitmap, and when v_8 is examined for |
145 | replaceability, it is a candidate, and it is dependent on the partition | |
00509c04 AM |
146 | b_5 is in *NOT* a_2, as well as c_4's partition. |
147 | ||
148 | if v_8 is also replaceable: | |
149 | ||
150 | x_9 = v_8 * 5 | |
151 | ||
152 | x_9 is dependent on partitions b_5, and c_4 | |
b8698a0f L |
153 | |
154 | if a statement is found which has either of those partitions written to | |
00509c04 AM |
155 | before x_9 is used, then x_9 itself is NOT replaceable. */ |
156 | ||
157 | ||
158 | /* Temporary Expression Replacement (TER) table information. */ | |
159 | ||
09a23476 | 160 | struct temp_expr_table |
00509c04 AM |
161 | { |
162 | var_map map; | |
163 | bitmap *partition_dependencies; /* Partitions expr is dependent on. */ | |
e97809c6 | 164 | bitmap replaceable_expressions; /* Replacement expression table. */ |
00509c04 AM |
165 | bitmap *expr_decl_uids; /* Base uids of exprs. */ |
166 | bitmap *kill_list; /* Expr's killed by a partition. */ | |
2e226e66 KH |
167 | int virtual_partition; /* Pseudo partition for virtual ops. */ |
168 | bitmap partition_in_use; /* Partitions with kill entries. */ | |
00509c04 AM |
169 | bitmap new_replaceable_dependencies; /* Holding place for pending dep's. */ |
170 | int *num_in_part; /* # of ssa_names in a partition. */ | |
2ea5ee06 | 171 | int *call_cnt; /* Call count at definition. */ |
09a23476 | 172 | }; |
00509c04 | 173 | |
38635499 | 174 | /* Used to indicate a dependency on VDEFs. */ |
00509c04 AM |
175 | #define VIRTUAL_PARTITION(table) (table->virtual_partition) |
176 | ||
3f9b14ff SB |
177 | /* A place for the many, many bitmaps we create. */ |
178 | static bitmap_obstack ter_bitmap_obstack; | |
179 | ||
09a23476 | 180 | extern void debug_ter (FILE *, temp_expr_table *); |
00509c04 AM |
181 | |
182 | ||
183 | /* Create a new TER table for MAP. */ | |
184 | ||
09a23476 | 185 | static temp_expr_table * |
00509c04 AM |
186 | new_temp_expr_table (var_map map) |
187 | { | |
09a23476 | 188 | temp_expr_table *t = XNEW (struct temp_expr_table); |
00509c04 AM |
189 | t->map = map; |
190 | ||
191 | t->partition_dependencies = XCNEWVEC (bitmap, num_ssa_names + 1); | |
192 | t->expr_decl_uids = XCNEWVEC (bitmap, num_ssa_names + 1); | |
193 | t->kill_list = XCNEWVEC (bitmap, num_var_partitions (map) + 1); | |
194 | ||
3f9b14ff | 195 | t->partition_in_use = BITMAP_ALLOC (&ter_bitmap_obstack); |
00509c04 AM |
196 | |
197 | t->virtual_partition = num_var_partitions (map); | |
3f9b14ff | 198 | t->new_replaceable_dependencies = BITMAP_ALLOC (&ter_bitmap_obstack); |
00509c04 AM |
199 | |
200 | t->replaceable_expressions = NULL; | |
201 | t->num_in_part = XCNEWVEC (int, num_var_partitions (map)); | |
46aa019a KV |
202 | |
203 | unsigned x; | |
204 | tree name; | |
205 | ||
206 | FOR_EACH_SSA_NAME (x, name, cfun) | |
00509c04 AM |
207 | { |
208 | int p; | |
00509c04 AM |
209 | p = var_to_partition (map, name); |
210 | if (p != NO_PARTITION) | |
211 | t->num_in_part[p]++; | |
212 | } | |
2ea5ee06 | 213 | t->call_cnt = XCNEWVEC (int, num_ssa_names + 1); |
00509c04 AM |
214 | |
215 | return t; | |
216 | } | |
217 | ||
218 | ||
b8698a0f | 219 | /* Free TER table T. If there are valid replacements, return the expression |
00509c04 AM |
220 | vector. */ |
221 | ||
e97809c6 | 222 | static bitmap |
09a23476 | 223 | free_temp_expr_table (temp_expr_table *t) |
00509c04 | 224 | { |
e97809c6 | 225 | bitmap ret = NULL; |
00509c04 | 226 | |
b2b29377 | 227 | if (flag_checking) |
60ffe2fe | 228 | { |
b2b29377 MM |
229 | for (unsigned x = 0; x <= num_var_partitions (t->map); x++) |
230 | gcc_assert (!t->kill_list[x]); | |
231 | for (unsigned x = 0; x < num_ssa_names; x++) | |
232 | { | |
233 | gcc_assert (t->expr_decl_uids[x] == NULL); | |
234 | gcc_assert (t->partition_dependencies[x] == NULL); | |
235 | } | |
60ffe2fe | 236 | } |
00509c04 AM |
237 | |
238 | BITMAP_FREE (t->partition_in_use); | |
42b22da8 | 239 | BITMAP_FREE (t->new_replaceable_dependencies); |
00509c04 | 240 | |
00509c04 | 241 | free (t->expr_decl_uids); |
00509c04 AM |
242 | free (t->kill_list); |
243 | free (t->partition_dependencies); | |
42b22da8 | 244 | free (t->num_in_part); |
2ea5ee06 | 245 | free (t->call_cnt); |
00509c04 AM |
246 | |
247 | if (t->replaceable_expressions) | |
248 | ret = t->replaceable_expressions; | |
249 | ||
250 | free (t); | |
251 | return ret; | |
252 | } | |
253 | ||
254 | ||
255 | /* Return TRUE if VERSION is to be replaced by an expression in TAB. */ | |
256 | ||
257 | static inline bool | |
09a23476 | 258 | version_to_be_replaced_p (temp_expr_table *tab, int version) |
00509c04 AM |
259 | { |
260 | if (!tab->replaceable_expressions) | |
261 | return false; | |
e97809c6 | 262 | return bitmap_bit_p (tab->replaceable_expressions, version); |
00509c04 AM |
263 | } |
264 | ||
265 | ||
b8698a0f | 266 | /* Add partition P to the list if partitions VERSION is dependent on. TAB is |
00509c04 AM |
267 | the expression table */ |
268 | ||
269 | static inline void | |
09a23476 | 270 | make_dependent_on_partition (temp_expr_table *tab, int version, int p) |
00509c04 AM |
271 | { |
272 | if (!tab->partition_dependencies[version]) | |
3f9b14ff | 273 | tab->partition_dependencies[version] = BITMAP_ALLOC (&ter_bitmap_obstack); |
00509c04 AM |
274 | |
275 | bitmap_set_bit (tab->partition_dependencies[version], p); | |
276 | } | |
277 | ||
278 | ||
279 | /* Add VER to the kill list for P. TAB is the expression table */ | |
280 | ||
281 | static inline void | |
09a23476 | 282 | add_to_partition_kill_list (temp_expr_table *tab, int p, int ver) |
00509c04 AM |
283 | { |
284 | if (!tab->kill_list[p]) | |
285 | { | |
3f9b14ff | 286 | tab->kill_list[p] = BITMAP_ALLOC (&ter_bitmap_obstack); |
00509c04 AM |
287 | bitmap_set_bit (tab->partition_in_use, p); |
288 | } | |
289 | bitmap_set_bit (tab->kill_list[p], ver); | |
290 | } | |
291 | ||
292 | ||
b8698a0f | 293 | /* Remove VER from the partition kill list for P. TAB is the expression |
00509c04 AM |
294 | table. */ |
295 | ||
b8698a0f | 296 | static inline void |
09a23476 | 297 | remove_from_partition_kill_list (temp_expr_table *tab, int p, int version) |
00509c04 | 298 | { |
77a74ed7 | 299 | gcc_checking_assert (tab->kill_list[p]); |
00509c04 AM |
300 | bitmap_clear_bit (tab->kill_list[p], version); |
301 | if (bitmap_empty_p (tab->kill_list[p])) | |
302 | { | |
303 | bitmap_clear_bit (tab->partition_in_use, p); | |
304 | BITMAP_FREE (tab->kill_list[p]); | |
305 | } | |
306 | } | |
307 | ||
308 | ||
b8698a0f L |
309 | /* Add a dependency between the def of ssa VERSION and VAR. If VAR is |
310 | replaceable by an expression, add a dependence each of the elements of the | |
00509c04 AM |
311 | expression. These are contained in the new_replaceable list. TAB is the |
312 | expression table. */ | |
313 | ||
314 | static void | |
09a23476 | 315 | add_dependence (temp_expr_table *tab, int version, tree var) |
00509c04 AM |
316 | { |
317 | int i; | |
318 | bitmap_iterator bi; | |
319 | unsigned x; | |
320 | ||
321 | i = SSA_NAME_VERSION (var); | |
322 | if (version_to_be_replaced_p (tab, i)) | |
323 | { | |
324 | if (!bitmap_empty_p (tab->new_replaceable_dependencies)) | |
325 | { | |
b8698a0f | 326 | /* Version will now be killed by a write to any partition the |
00509c04 AM |
327 | substituted expression would have been killed by. */ |
328 | EXECUTE_IF_SET_IN_BITMAP (tab->new_replaceable_dependencies, 0, x, bi) | |
329 | add_to_partition_kill_list (tab, x, version); | |
330 | ||
b8698a0f | 331 | /* Rather than set partition_dependencies and in_use lists bit by |
00509c04 AM |
332 | bit, simply OR in the new_replaceable_dependencies bits. */ |
333 | if (!tab->partition_dependencies[version]) | |
3f9b14ff SB |
334 | tab->partition_dependencies[version] = |
335 | BITMAP_ALLOC (&ter_bitmap_obstack); | |
b8698a0f | 336 | bitmap_ior_into (tab->partition_dependencies[version], |
00509c04 | 337 | tab->new_replaceable_dependencies); |
b8698a0f | 338 | bitmap_ior_into (tab->partition_in_use, |
00509c04 AM |
339 | tab->new_replaceable_dependencies); |
340 | /* It is only necessary to add these once. */ | |
341 | bitmap_clear (tab->new_replaceable_dependencies); | |
342 | } | |
343 | } | |
344 | else | |
345 | { | |
346 | i = var_to_partition (tab->map, var); | |
77a74ed7 NF |
347 | gcc_checking_assert (i != NO_PARTITION); |
348 | gcc_checking_assert (tab->num_in_part[i] != 0); | |
00509c04 AM |
349 | /* Only dependencies on ssa_names which are coalesced with something need |
350 | to be tracked. Partitions with containing only a single SSA_NAME | |
351 | *cannot* have their value changed. */ | |
352 | if (tab->num_in_part[i] > 1) | |
353 | { | |
354 | add_to_partition_kill_list (tab, i, version); | |
355 | make_dependent_on_partition (tab, version, i); | |
356 | } | |
357 | } | |
358 | } | |
359 | ||
360 | ||
b8698a0f L |
361 | /* This function will remove the expression for VERSION from replacement |
362 | consideration in table TAB. If FREE_EXPR is true, then remove the | |
00509c04 AM |
363 | expression from consideration as well by freeing the decl uid bitmap. */ |
364 | ||
365 | static void | |
09a23476 | 366 | finished_with_expr (temp_expr_table *tab, int version, bool free_expr) |
00509c04 AM |
367 | { |
368 | unsigned i; | |
369 | bitmap_iterator bi; | |
370 | ||
371 | /* Remove this expression from its dependent lists. The partition dependence | |
073a8998 | 372 | list is retained and transferred later to whomever uses this version. */ |
00509c04 AM |
373 | if (tab->partition_dependencies[version]) |
374 | { | |
375 | EXECUTE_IF_SET_IN_BITMAP (tab->partition_dependencies[version], 0, i, bi) | |
376 | remove_from_partition_kill_list (tab, i, version); | |
377 | BITMAP_FREE (tab->partition_dependencies[version]); | |
378 | } | |
379 | if (free_expr) | |
380 | BITMAP_FREE (tab->expr_decl_uids[version]); | |
381 | } | |
382 | ||
383 | ||
78bca40d AM |
384 | /* Return TRUE if expression STMT is suitable for replacement. |
385 | In addition to ssa_is_replaceable_p, require the same bb, and for -O0 | |
386 | same locus and same BLOCK), Considers memory loads as replaceable if aliasing | |
387 | is available. */ | |
388 | ||
389 | static inline bool | |
355fe088 | 390 | ter_is_replaceable_p (gimple *stmt) |
78bca40d AM |
391 | { |
392 | ||
393 | if (ssa_is_replaceable_p (stmt)) | |
394 | { | |
395 | use_operand_p use_p; | |
396 | tree def; | |
355fe088 | 397 | gimple *use_stmt; |
78bca40d AM |
398 | location_t locus1, locus2; |
399 | tree block1, block2; | |
400 | ||
401 | /* Only consider definitions which have a single use. ssa_is_replaceable_p | |
402 | already performed this check, but the use stmt pointer is required for | |
403 | further checks. */ | |
404 | def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF); | |
405 | if (!single_imm_use (def, &use_p, &use_stmt)) | |
406 | return false; | |
407 | ||
408 | /* If the use isn't in this block, it wont be replaced either. */ | |
409 | if (gimple_bb (use_stmt) != gimple_bb (stmt)) | |
410 | return false; | |
411 | ||
412 | locus1 = gimple_location (stmt); | |
413 | block1 = LOCATION_BLOCK (locus1); | |
414 | locus1 = LOCATION_LOCUS (locus1); | |
415 | ||
538dd0b7 DM |
416 | if (gphi *phi = dyn_cast <gphi *> (use_stmt)) |
417 | locus2 = gimple_phi_arg_location (phi, | |
78bca40d AM |
418 | PHI_ARG_INDEX_FROM_USE (use_p)); |
419 | else | |
420 | locus2 = gimple_location (use_stmt); | |
421 | block2 = LOCATION_BLOCK (locus2); | |
422 | locus2 = LOCATION_LOCUS (locus2); | |
423 | ||
424 | if ((!optimize || optimize_debug) | |
425 | && ((locus1 != UNKNOWN_LOCATION && locus1 != locus2) | |
426 | || (block1 != NULL_TREE && block1 != block2))) | |
427 | return false; | |
428 | ||
78bca40d AM |
429 | return true; |
430 | } | |
431 | return false; | |
432 | } | |
433 | ||
434 | ||
fea10e36 | 435 | /* Create an expression entry for a replaceable expression. */ |
00509c04 | 436 | |
b8698a0f | 437 | static void |
355fe088 | 438 | process_replaceable (temp_expr_table *tab, gimple *stmt, int call_cnt) |
00509c04 AM |
439 | { |
440 | tree var, def, basevar; | |
441 | int version; | |
442 | ssa_op_iter iter; | |
443 | bitmap def_vars, use_vars; | |
444 | ||
78bca40d | 445 | gcc_checking_assert (ter_is_replaceable_p (stmt)); |
00509c04 AM |
446 | |
447 | def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF); | |
448 | version = SSA_NAME_VERSION (def); | |
3f9b14ff | 449 | def_vars = BITMAP_ALLOC (&ter_bitmap_obstack); |
00509c04 | 450 | |
70b5e7dc RG |
451 | basevar = SSA_NAME_VAR (def); |
452 | if (basevar) | |
453 | bitmap_set_bit (def_vars, DECL_UID (basevar)); | |
00509c04 AM |
454 | |
455 | /* Add this expression to the dependency list for each use partition. */ | |
456 | FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE) | |
457 | { | |
458 | int var_version = SSA_NAME_VERSION (var); | |
459 | ||
460 | use_vars = tab->expr_decl_uids[var_version]; | |
461 | add_dependence (tab, version, var); | |
462 | if (use_vars) | |
463 | { | |
464 | bitmap_ior_into (def_vars, use_vars); | |
465 | BITMAP_FREE (tab->expr_decl_uids[var_version]); | |
466 | } | |
70b5e7dc | 467 | else if (SSA_NAME_VAR (var)) |
00509c04 AM |
468 | bitmap_set_bit (def_vars, DECL_UID (SSA_NAME_VAR (var))); |
469 | } | |
470 | tab->expr_decl_uids[version] = def_vars; | |
471 | ||
472 | /* If there are VUSES, add a dependence on virtual defs. */ | |
5006671f | 473 | if (gimple_vuse (stmt)) |
00509c04 AM |
474 | { |
475 | make_dependent_on_partition (tab, version, VIRTUAL_PARTITION (tab)); | |
476 | add_to_partition_kill_list (tab, VIRTUAL_PARTITION (tab), version); | |
477 | } | |
2ea5ee06 PH |
478 | |
479 | tab->call_cnt[version] = call_cnt; | |
00509c04 AM |
480 | } |
481 | ||
482 | ||
483 | /* This function removes any expression in TAB which is dependent on PARTITION | |
484 | from consideration, making it not replaceable. */ | |
485 | ||
486 | static inline void | |
09a23476 | 487 | kill_expr (temp_expr_table *tab, int partition) |
00509c04 AM |
488 | { |
489 | unsigned version; | |
490 | ||
b8698a0f | 491 | /* Mark every active expr dependent on this var as not replaceable. |
00509c04 AM |
492 | finished_with_expr can modify the bitmap, so we can't execute over it. */ |
493 | while (tab->kill_list[partition]) | |
494 | { | |
495 | version = bitmap_first_set_bit (tab->kill_list[partition]); | |
496 | finished_with_expr (tab, version, true); | |
497 | } | |
498 | ||
77a74ed7 | 499 | gcc_checking_assert (!tab->kill_list[partition]); |
00509c04 AM |
500 | } |
501 | ||
502 | ||
b8698a0f | 503 | /* This function kills all expressions in TAB which are dependent on virtual |
00509c04 AM |
504 | partitions. */ |
505 | ||
506 | static inline void | |
09a23476 | 507 | kill_virtual_exprs (temp_expr_table *tab) |
00509c04 AM |
508 | { |
509 | kill_expr (tab, VIRTUAL_PARTITION (tab)); | |
510 | } | |
511 | ||
512 | ||
513 | /* Mark the expression associated with VAR as replaceable, and enter | |
fa10beec | 514 | the defining stmt into the partition_dependencies table TAB. If |
00509c04 AM |
515 | MORE_REPLACING is true, accumulate the pending partition dependencies. */ |
516 | ||
517 | static void | |
09a23476 | 518 | mark_replaceable (temp_expr_table *tab, tree var, bool more_replacing) |
00509c04 AM |
519 | { |
520 | int version = SSA_NAME_VERSION (var); | |
521 | ||
522 | /* Move the dependence list to the pending listpending. */ | |
523 | if (more_replacing && tab->partition_dependencies[version]) | |
b8698a0f | 524 | bitmap_ior_into (tab->new_replaceable_dependencies, |
00509c04 AM |
525 | tab->partition_dependencies[version]); |
526 | ||
527 | finished_with_expr (tab, version, !more_replacing); | |
528 | ||
3f9b14ff SB |
529 | /* Set the replaceable expression. |
530 | The bitmap for this "escapes" from this file so it's allocated | |
531 | on the default obstack. */ | |
00509c04 | 532 | if (!tab->replaceable_expressions) |
e97809c6 MM |
533 | tab->replaceable_expressions = BITMAP_ALLOC (NULL); |
534 | bitmap_set_bit (tab->replaceable_expressions, version); | |
00509c04 AM |
535 | } |
536 | ||
537 | ||
9f1363cd JJ |
538 | /* Helper function for find_ssaname_in_stores. Called via walk_tree to |
539 | find a SSA_NAME DATA somewhere in *TP. */ | |
540 | ||
541 | static tree | |
542 | find_ssaname (tree *tp, int *walk_subtrees, void *data) | |
543 | { | |
544 | tree var = (tree) data; | |
545 | if (*tp == var) | |
546 | return var; | |
547 | else if (IS_TYPE_OR_DECL_P (*tp)) | |
548 | *walk_subtrees = 0; | |
549 | return NULL_TREE; | |
550 | } | |
551 | ||
552 | /* Helper function for find_replaceable_in_bb. Return true if SSA_NAME DATA | |
553 | is used somewhere in T, which is a store in the statement. Called via | |
554 | walk_stmt_load_store_addr_ops. */ | |
555 | ||
556 | static bool | |
355fe088 | 557 | find_ssaname_in_store (gimple *, tree, tree t, void *data) |
9f1363cd JJ |
558 | { |
559 | return walk_tree (&t, find_ssaname, data, NULL) != NULL_TREE; | |
560 | } | |
561 | ||
00509c04 AM |
562 | /* This function processes basic block BB, and looks for variables which can |
563 | be replaced by their expressions. Results are stored in the table TAB. */ | |
564 | ||
565 | static void | |
09a23476 | 566 | find_replaceable_in_bb (temp_expr_table *tab, basic_block bb) |
00509c04 | 567 | { |
726a989a | 568 | gimple_stmt_iterator bsi; |
355fe088 | 569 | gimple *stmt; |
2ea5ee06 | 570 | tree def, use, fndecl; |
00509c04 AM |
571 | int partition; |
572 | var_map map = tab->map; | |
573 | ssa_op_iter iter; | |
574 | bool stmt_replaceable; | |
2ea5ee06 | 575 | int cur_call_cnt = 0; |
00509c04 | 576 | |
726a989a | 577 | for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) |
00509c04 | 578 | { |
726a989a | 579 | stmt = gsi_stmt (bsi); |
00509c04 | 580 | |
b5b8b0ac AO |
581 | if (is_gimple_debug (stmt)) |
582 | continue; | |
583 | ||
78bca40d | 584 | stmt_replaceable = ter_is_replaceable_p (stmt); |
726a989a | 585 | |
00509c04 AM |
586 | /* Determine if this stmt finishes an existing expression. */ |
587 | FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) | |
588 | { | |
589 | unsigned ver = SSA_NAME_VERSION (use); | |
590 | ||
591 | /* If this use is a potential replacement variable, process it. */ | |
592 | if (tab->expr_decl_uids[ver]) | |
593 | { | |
594 | bool same_root_var = false; | |
595 | ssa_op_iter iter2; | |
596 | bitmap vars = tab->expr_decl_uids[ver]; | |
597 | ||
598 | /* See if the root variables are the same. If they are, we | |
599 | do not want to do the replacement to avoid problems with | |
600 | code size, see PR tree-optimization/17549. */ | |
601 | if (!bitmap_empty_p (vars)) | |
602 | FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter2, SSA_OP_DEF) | |
603 | { | |
70b5e7dc RG |
604 | if (SSA_NAME_VAR (def) |
605 | && bitmap_bit_p (vars, DECL_UID (SSA_NAME_VAR (def)))) | |
00509c04 AM |
606 | { |
607 | same_root_var = true; | |
608 | break; | |
609 | } | |
610 | } | |
611 | ||
70f34814 RG |
612 | /* If the stmt does a memory store and the replacement |
613 | is a load aliasing it avoid creating overlapping | |
614 | assignments which we cannot expand correctly. */ | |
7d07de0b | 615 | if (gimple_vdef (stmt)) |
70f34814 | 616 | { |
355fe088 | 617 | gimple *def_stmt = SSA_NAME_DEF_STMT (use); |
70f34814 RG |
618 | while (is_gimple_assign (def_stmt) |
619 | && gimple_assign_rhs_code (def_stmt) == SSA_NAME) | |
620 | def_stmt | |
621 | = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (def_stmt)); | |
622 | if (gimple_vuse (def_stmt) | |
623 | && gimple_assign_single_p (def_stmt) | |
7d07de0b RB |
624 | && stmt_may_clobber_ref_p (stmt, |
625 | gimple_assign_rhs1 (def_stmt))) | |
9f1363cd JJ |
626 | { |
627 | /* For calls, it is not a problem if USE is among | |
628 | call's arguments or say OBJ_TYPE_REF argument, | |
629 | all those necessarily need to be evaluated before | |
630 | the call that may clobber the memory. But if | |
631 | LHS of the call refers to USE, expansion might | |
632 | evaluate it after the call, prevent TER in that | |
633 | case. | |
634 | For inline asm, allow TER of loads into input | |
635 | arguments, but disallow TER for USEs that occur | |
636 | somewhere in outputs. */ | |
637 | if (is_gimple_call (stmt) | |
638 | || gimple_code (stmt) == GIMPLE_ASM) | |
639 | { | |
640 | if (walk_stmt_load_store_ops (stmt, use, NULL, | |
641 | find_ssaname_in_store)) | |
642 | same_root_var = true; | |
643 | } | |
644 | else | |
645 | same_root_var = true; | |
646 | } | |
70f34814 RG |
647 | } |
648 | ||
2ea5ee06 | 649 | /* Mark expression as replaceable unless stmt is volatile, or the |
b8698a0f | 650 | def variable has the same root variable as something in the |
2ea5ee06 PH |
651 | substitution list, or the def and use span a call such that |
652 | we'll expand lifetimes across a call. */ | |
604f9a90 PH |
653 | if (gimple_has_volatile_ops (stmt) || same_root_var |
654 | || (tab->call_cnt[ver] != cur_call_cnt | |
655 | && SINGLE_SSA_USE_OPERAND (SSA_NAME_DEF_STMT (use), SSA_OP_USE) | |
656 | == NULL_USE_OPERAND_P)) | |
00509c04 AM |
657 | finished_with_expr (tab, ver, true); |
658 | else | |
659 | mark_replaceable (tab, use, stmt_replaceable); | |
660 | } | |
661 | } | |
b8698a0f | 662 | |
00509c04 AM |
663 | /* Next, see if this stmt kills off an active expression. */ |
664 | FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_DEF) | |
665 | { | |
666 | partition = var_to_partition (map, def); | |
667 | if (partition != NO_PARTITION && tab->kill_list[partition]) | |
668 | kill_expr (tab, partition); | |
669 | } | |
670 | ||
2ea5ee06 PH |
671 | /* Increment counter if this is a non BUILT_IN call. We allow |
672 | replacement over BUILT_IN calls since many will expand to inline | |
673 | insns instead of a true call. */ | |
674 | if (is_gimple_call (stmt) | |
675 | && !((fndecl = gimple_call_fndecl (stmt)) | |
676 | && DECL_BUILT_IN (fndecl))) | |
677 | cur_call_cnt++; | |
678 | ||
00509c04 AM |
679 | /* Now see if we are creating a new expression or not. */ |
680 | if (stmt_replaceable) | |
2ea5ee06 | 681 | process_replaceable (tab, stmt, cur_call_cnt); |
00509c04 AM |
682 | |
683 | /* Free any unused dependency lists. */ | |
684 | bitmap_clear (tab->new_replaceable_dependencies); | |
685 | ||
686 | /* A V_{MAY,MUST}_DEF kills any expression using a virtual operand, | |
687 | including the current stmt. */ | |
5006671f | 688 | if (gimple_vdef (stmt)) |
00509c04 AM |
689 | kill_virtual_exprs (tab); |
690 | } | |
691 | } | |
692 | ||
693 | ||
694 | /* This function is the driver routine for replacement of temporary expressions | |
b8698a0f L |
695 | in the SSA->normal phase, operating on MAP. If there are replaceable |
696 | expressions, a table is returned which maps SSA versions to the | |
697 | expressions they should be replaced with. A NULL_TREE indicates no | |
698 | replacement should take place. If there are no replacements at all, | |
00509c04 AM |
699 | NULL is returned by the function, otherwise an expression vector indexed |
700 | by SSA_NAME version numbers. */ | |
701 | ||
3f9b14ff | 702 | bitmap |
00509c04 AM |
703 | find_replaceable_exprs (var_map map) |
704 | { | |
705 | basic_block bb; | |
09a23476 | 706 | temp_expr_table *table; |
e97809c6 | 707 | bitmap ret; |
00509c04 | 708 | |
3f9b14ff | 709 | bitmap_obstack_initialize (&ter_bitmap_obstack); |
00509c04 | 710 | table = new_temp_expr_table (map); |
11cd3bed | 711 | FOR_EACH_BB_FN (bb, cfun) |
00509c04 AM |
712 | { |
713 | find_replaceable_in_bb (table, bb); | |
77a74ed7 | 714 | gcc_checking_assert (bitmap_empty_p (table->partition_in_use)); |
00509c04 | 715 | } |
00509c04 | 716 | ret = free_temp_expr_table (table); |
3f9b14ff | 717 | bitmap_obstack_release (&ter_bitmap_obstack); |
00509c04 | 718 | return ret; |
b8698a0f | 719 | } |
00509c04 AM |
720 | |
721 | /* Dump TER expression table EXPR to file F. */ | |
722 | ||
726a989a | 723 | void |
e97809c6 | 724 | dump_replaceable_exprs (FILE *f, bitmap expr) |
00509c04 | 725 | { |
726a989a RB |
726 | tree var; |
727 | unsigned x; | |
00509c04 AM |
728 | |
729 | fprintf (f, "\nReplacing Expressions\n"); | |
726a989a | 730 | for (x = 0; x < num_ssa_names; x++) |
e97809c6 | 731 | if (bitmap_bit_p (expr, x)) |
00509c04 | 732 | { |
726a989a | 733 | var = ssa_name (x); |
00509c04 AM |
734 | print_generic_expr (f, var, TDF_SLIM); |
735 | fprintf (f, " replace with --> "); | |
e97809c6 | 736 | print_gimple_stmt (f, SSA_NAME_DEF_STMT (var), 0, TDF_SLIM); |
00509c04 AM |
737 | fprintf (f, "\n"); |
738 | } | |
739 | fprintf (f, "\n"); | |
740 | } | |
741 | ||
742 | ||
00509c04 AM |
743 | /* Dump the status of the various tables in the expression table. This is used |
744 | exclusively to debug TER. F is the place to send debug info and T is the | |
745 | table being debugged. */ | |
746 | ||
24e47c76 | 747 | DEBUG_FUNCTION void |
09a23476 | 748 | debug_ter (FILE *f, temp_expr_table *t) |
00509c04 AM |
749 | { |
750 | unsigned x, y; | |
751 | bitmap_iterator bi; | |
752 | ||
b8698a0f | 753 | fprintf (f, "\nDumping current state of TER\n virtual partition = %d\n", |
00509c04 AM |
754 | VIRTUAL_PARTITION (t)); |
755 | if (t->replaceable_expressions) | |
756 | dump_replaceable_exprs (f, t->replaceable_expressions); | |
757 | fprintf (f, "Currently tracking the following expressions:\n"); | |
758 | ||
759 | for (x = 1; x < num_ssa_names; x++) | |
760 | if (t->expr_decl_uids[x]) | |
761 | { | |
2ea5ee06 | 762 | print_generic_expr (f, ssa_name (x), TDF_SLIM); |
00509c04 | 763 | fprintf (f, " dep-parts : "); |
b8698a0f | 764 | if (t->partition_dependencies[x] |
00509c04 AM |
765 | && !bitmap_empty_p (t->partition_dependencies[x])) |
766 | { | |
767 | EXECUTE_IF_SET_IN_BITMAP (t->partition_dependencies[x], 0, y, bi) | |
768 | fprintf (f, "P%d ",y); | |
769 | } | |
2ea5ee06 | 770 | fprintf (f, " basedecls: "); |
00509c04 AM |
771 | EXECUTE_IF_SET_IN_BITMAP (t->expr_decl_uids[x], 0, y, bi) |
772 | fprintf (f, "%d ",y); | |
2ea5ee06 PH |
773 | fprintf (f, " call_cnt : %d",t->call_cnt[x]); |
774 | fprintf (f, "\n"); | |
00509c04 AM |
775 | } |
776 | ||
b8698a0f | 777 | bitmap_print (f, t->partition_in_use, "Partitions in use ", |
00509c04 AM |
778 | "\npartition KILL lists:\n"); |
779 | ||
780 | for (x = 0; x <= num_var_partitions (t->map); x++) | |
781 | if (t->kill_list[x]) | |
782 | { | |
783 | fprintf (f, "Partition %d : ", x); | |
784 | EXECUTE_IF_SET_IN_BITMAP (t->kill_list[x], 0, y, bi) | |
785 | fprintf (f, "_%d ",y); | |
786 | } | |
787 | ||
788 | fprintf (f, "\n----------\n"); | |
789 | } |