]>
Commit | Line | Data |
---|---|---|
0bca51f0 | 1 | /* Copy propagation and SSA_NAME replacement support routines. |
ad616de1 | 2 | Copyright (C) 2004, 2005 Free Software Foundation, Inc. |
6de9cd9a DN |
3 | |
4 | This file is part of GCC. | |
5 | ||
6 | GCC is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
8 | the Free Software Foundation; either version 2, or (at your option) | |
9 | any later version. | |
10 | ||
11 | GCC is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with GCC; see the file COPYING. If not, write to | |
366ccddb KC |
18 | the Free Software Foundation, 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. */ | |
6de9cd9a DN |
20 | |
21 | #include "config.h" | |
22 | #include "system.h" | |
23 | #include "coretypes.h" | |
24 | #include "tm.h" | |
25 | #include "tree.h" | |
26 | #include "flags.h" | |
27 | #include "rtl.h" | |
28 | #include "tm_p.h" | |
29 | #include "ggc.h" | |
30 | #include "basic-block.h" | |
31 | #include "output.h" | |
6de9cd9a DN |
32 | #include "expr.h" |
33 | #include "function.h" | |
34 | #include "diagnostic.h" | |
35 | #include "timevar.h" | |
36 | #include "tree-dump.h" | |
37 | #include "tree-flow.h" | |
38 | #include "tree-pass.h" | |
0bca51f0 | 39 | #include "tree-ssa-propagate.h" |
6de9cd9a DN |
40 | #include "langhooks.h" |
41 | ||
0bca51f0 DN |
42 | /* This file implements the copy propagation pass and provides a |
43 | handful of interfaces for performing const/copy propagation and | |
44 | simple expression replacement which keep variable annotations | |
45 | up-to-date. | |
6de9cd9a DN |
46 | |
47 | We require that for any copy operation where the RHS and LHS have | |
3a7c155d | 48 | a non-null memory tag the memory tag be the same. It is OK |
6de9cd9a DN |
49 | for one or both of the memory tags to be NULL. |
50 | ||
51 | We also require tracking if a variable is dereferenced in a load or | |
52 | store operation. | |
53 | ||
54 | We enforce these requirements by having all copy propagation and | |
55 | replacements of one SSA_NAME with a different SSA_NAME to use the | |
56 | APIs defined in this file. */ | |
57 | ||
63b88252 RH |
58 | /* Return true if we may propagate ORIG into DEST, false otherwise. */ |
59 | ||
60 | bool | |
61 | may_propagate_copy (tree dest, tree orig) | |
62 | { | |
63 | tree type_d = TREE_TYPE (dest); | |
64 | tree type_o = TREE_TYPE (orig); | |
65 | ||
66 | /* Do not copy between types for which we *do* need a conversion. */ | |
67 | if (!tree_ssa_useless_type_conversion_1 (type_d, type_o)) | |
68 | return false; | |
69 | ||
70 | /* FIXME. GIMPLE is allowing pointer assignments and comparisons of | |
71 | pointers that have different alias sets. This means that these | |
72 | pointers will have different memory tags associated to them. | |
19114537 | 73 | |
63b88252 RH |
74 | If we allow copy propagation in these cases, statements de-referencing |
75 | the new pointer will now have a reference to a different memory tag | |
76 | with potentially incorrect SSA information. | |
77 | ||
78 | This was showing up in libjava/java/util/zip/ZipFile.java with code | |
79 | like: | |
80 | ||
81 | struct java.io.BufferedInputStream *T.660; | |
82 | struct java.io.BufferedInputStream *T.647; | |
83 | struct java.io.InputStream *is; | |
84 | struct java.io.InputStream *is.662; | |
85 | [ ... ] | |
86 | T.660 = T.647; | |
87 | is = T.660; <-- This ought to be type-casted | |
88 | is.662 = is; | |
89 | ||
90 | Also, f/name.c exposed a similar problem with a COND_EXPR predicate | |
91 | that was causing DOM to generate and equivalence with two pointers of | |
92 | alias-incompatible types: | |
93 | ||
94 | struct _ffename_space *n; | |
95 | struct _ffename *ns; | |
96 | [ ... ] | |
97 | if (n == ns) | |
98 | goto lab; | |
99 | ... | |
100 | lab: | |
101 | return n; | |
102 | ||
103 | I think that GIMPLE should emit the appropriate type-casts. For the | |
104 | time being, blocking copy-propagation in these cases is the safe thing | |
105 | to do. */ | |
0bca51f0 DN |
106 | if (TREE_CODE (dest) == SSA_NAME |
107 | && TREE_CODE (orig) == SSA_NAME | |
108 | && POINTER_TYPE_P (type_d) | |
109 | && POINTER_TYPE_P (type_o)) | |
63b88252 RH |
110 | { |
111 | tree mt_dest = var_ann (SSA_NAME_VAR (dest))->type_mem_tag; | |
112 | tree mt_orig = var_ann (SSA_NAME_VAR (orig))->type_mem_tag; | |
113 | if (mt_dest && mt_orig && mt_dest != mt_orig) | |
114 | return false; | |
bbc630f5 DN |
115 | else if (!lang_hooks.types_compatible_p (type_d, type_o)) |
116 | return false; | |
b1940f0c AP |
117 | else if (get_alias_set (TREE_TYPE (type_d)) != |
118 | get_alias_set (TREE_TYPE (type_o))) | |
9ae2a5d1 | 119 | return false; |
63b88252 RH |
120 | } |
121 | ||
122 | /* If the destination is a SSA_NAME for a virtual operand, then we have | |
123 | some special cases to handle. */ | |
124 | if (TREE_CODE (dest) == SSA_NAME && !is_gimple_reg (dest)) | |
125 | { | |
126 | /* If both operands are SSA_NAMEs referring to virtual operands, then | |
127 | we can always propagate. */ | |
0bca51f0 DN |
128 | if (TREE_CODE (orig) == SSA_NAME |
129 | && !is_gimple_reg (orig)) | |
130 | return true; | |
63b88252 RH |
131 | |
132 | /* We have a "copy" from something like a constant into a virtual | |
133 | operand. Reject these. */ | |
134 | return false; | |
135 | } | |
136 | ||
137 | /* If ORIG flows in from an abnormal edge, it cannot be propagated. */ | |
138 | if (TREE_CODE (orig) == SSA_NAME | |
139 | && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (orig)) | |
140 | return false; | |
141 | ||
e670d9e4 RH |
142 | /* If DEST is an SSA_NAME that flows from an abnormal edge, then it |
143 | cannot be replaced. */ | |
63b88252 | 144 | if (TREE_CODE (dest) == SSA_NAME |
e670d9e4 | 145 | && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (dest)) |
63b88252 RH |
146 | return false; |
147 | ||
148 | /* Anything else is OK. */ | |
149 | return true; | |
150 | } | |
151 | ||
aa24864c RH |
152 | /* Similarly, but we know that we're propagating into an ASM_EXPR. */ |
153 | ||
154 | bool | |
155 | may_propagate_copy_into_asm (tree dest) | |
156 | { | |
157 | /* Hard register operands of asms are special. Do not bypass. */ | |
158 | return !(TREE_CODE (dest) == SSA_NAME | |
e670d9e4 | 159 | && TREE_CODE (SSA_NAME_VAR (dest)) == VAR_DECL |
aa24864c RH |
160 | && DECL_HARD_REGISTER (SSA_NAME_VAR (dest))); |
161 | } | |
162 | ||
6de9cd9a | 163 | |
bbc630f5 DN |
164 | /* Given two SSA_NAMEs pointers ORIG and NEW such that we are copy |
165 | propagating NEW into ORIG, consolidate aliasing information so that | |
166 | they both share the same memory tags. */ | |
19114537 | 167 | |
6de9cd9a | 168 | static void |
bbc630f5 | 169 | merge_alias_info (tree orig, tree new) |
6de9cd9a | 170 | { |
bbc630f5 DN |
171 | tree new_sym = SSA_NAME_VAR (new); |
172 | tree orig_sym = SSA_NAME_VAR (orig); | |
173 | var_ann_t new_ann = var_ann (new_sym); | |
174 | var_ann_t orig_ann = var_ann (orig_sym); | |
175 | ||
1e128c5f GB |
176 | gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig))); |
177 | gcc_assert (POINTER_TYPE_P (TREE_TYPE (new))); | |
e03a46f5 | 178 | |
6de9cd9a | 179 | #if defined ENABLE_CHECKING |
1e128c5f GB |
180 | gcc_assert (lang_hooks.types_compatible_p (TREE_TYPE (orig), |
181 | TREE_TYPE (new))); | |
6de9cd9a | 182 | |
bbc630f5 DN |
183 | /* If the pointed-to alias sets are different, these two pointers |
184 | would never have the same memory tag. In this case, NEW should | |
185 | not have been propagated into ORIG. */ | |
1e128c5f GB |
186 | gcc_assert (get_alias_set (TREE_TYPE (TREE_TYPE (new_sym))) |
187 | == get_alias_set (TREE_TYPE (TREE_TYPE (orig_sym)))); | |
bbc630f5 | 188 | #endif |
6de9cd9a | 189 | |
de66168d DN |
190 | /* Synchronize the type tags. If both pointers had a tag and they |
191 | are different, then something has gone wrong. */ | |
bbc630f5 DN |
192 | if (new_ann->type_mem_tag == NULL_TREE) |
193 | new_ann->type_mem_tag = orig_ann->type_mem_tag; | |
194 | else if (orig_ann->type_mem_tag == NULL_TREE) | |
195 | orig_ann->type_mem_tag = new_ann->type_mem_tag; | |
1e128c5f GB |
196 | else |
197 | gcc_assert (new_ann->type_mem_tag == orig_ann->type_mem_tag); | |
de66168d | 198 | |
0bca51f0 DN |
199 | /* Synchronize the name tags. If NEW did not have a name tag, get |
200 | it from ORIG. This happens when NEW is a compiler generated | |
201 | temporary which still hasn't had its points-to information filled | |
202 | in. */ | |
203 | if (SSA_NAME_PTR_INFO (orig)) | |
e03a46f5 | 204 | { |
0bca51f0 DN |
205 | struct ptr_info_def *orig_ptr_info = SSA_NAME_PTR_INFO (orig); |
206 | struct ptr_info_def *new_ptr_info = SSA_NAME_PTR_INFO (new); | |
207 | ||
208 | if (new_ptr_info == NULL) | |
209 | duplicate_ssa_name_ptr_info (new, orig_ptr_info); | |
210 | else if (orig_ptr_info->name_mem_tag | |
211 | && new_ptr_info->name_mem_tag | |
212 | && orig_ptr_info->pt_vars | |
213 | && new_ptr_info->pt_vars) | |
214 | { | |
215 | /* Note that pointer NEW may actually have a different set | |
216 | of pointed-to variables. However, since NEW is being | |
217 | copy-propagated into ORIG, it must always be true that | |
218 | the pointed-to set for pointer NEW is the same, or a | |
219 | subset, of the pointed-to set for pointer ORIG. If this | |
220 | isn't the case, we shouldn't have been able to do the | |
221 | propagation of NEW into ORIG. */ | |
222 | gcc_assert (bitmap_intersect_p (new_ptr_info->pt_vars, | |
223 | orig_ptr_info->pt_vars)); | |
224 | } | |
986583fd | 225 | } |
de66168d | 226 | } |
d00ad49b | 227 | |
6de9cd9a DN |
228 | |
229 | /* Common code for propagate_value and replace_exp. | |
230 | ||
19114537 | 231 | Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the |
d00ad49b | 232 | replacement is done to propagate a value or not. */ |
6de9cd9a DN |
233 | |
234 | static void | |
bbc630f5 DN |
235 | replace_exp_1 (use_operand_p op_p, tree val, |
236 | bool for_propagation ATTRIBUTE_UNUSED) | |
6de9cd9a | 237 | { |
bbc630f5 DN |
238 | tree op = USE_FROM_PTR (op_p); |
239 | ||
240 | #if defined ENABLE_CHECKING | |
1e128c5f GB |
241 | gcc_assert (!(for_propagation |
242 | && TREE_CODE (op) == SSA_NAME | |
243 | && TREE_CODE (val) == SSA_NAME | |
244 | && !may_propagate_copy (op, val))); | |
bbc630f5 DN |
245 | #endif |
246 | ||
6de9cd9a DN |
247 | if (TREE_CODE (val) == SSA_NAME) |
248 | { | |
bbc630f5 DN |
249 | if (TREE_CODE (op) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (op))) |
250 | merge_alias_info (op, val); | |
d00ad49b | 251 | SET_USE (op_p, val); |
6de9cd9a DN |
252 | } |
253 | else | |
19114537 | 254 | SET_USE (op_p, unsave_expr_now (val)); |
6de9cd9a DN |
255 | } |
256 | ||
ff2ad0f7 | 257 | |
6de9cd9a DN |
258 | /* Propagate the value VAL (assumed to be a constant or another SSA_NAME) |
259 | into the operand pointed by OP_P. | |
260 | ||
261 | Use this version for const/copy propagation as it will perform additional | |
262 | checks to ensure validity of the const/copy propagation. */ | |
263 | ||
264 | void | |
d00ad49b | 265 | propagate_value (use_operand_p op_p, tree val) |
6de9cd9a DN |
266 | { |
267 | replace_exp_1 (op_p, val, true); | |
268 | } | |
269 | ||
ff2ad0f7 | 270 | |
d00ad49b AM |
271 | /* Propagate the value VAL (assumed to be a constant or another SSA_NAME) |
272 | into the tree pointed by OP_P. | |
273 | ||
19114537 EC |
274 | Use this version for const/copy propagation when SSA operands are not |
275 | available. It will perform the additional checks to ensure validity of | |
d00ad49b AM |
276 | the const/copy propagation, but will not update any operand information. |
277 | Be sure to mark the stmt as modified. */ | |
278 | ||
279 | void | |
280 | propagate_tree_value (tree *op_p, tree val) | |
281 | { | |
bbc630f5 | 282 | #if defined ENABLE_CHECKING |
1e128c5f GB |
283 | gcc_assert (!(TREE_CODE (val) == SSA_NAME |
284 | && TREE_CODE (*op_p) == SSA_NAME | |
285 | && !may_propagate_copy (*op_p, val))); | |
bbc630f5 DN |
286 | #endif |
287 | ||
d00ad49b AM |
288 | if (TREE_CODE (val) == SSA_NAME) |
289 | { | |
bbc630f5 DN |
290 | if (TREE_CODE (*op_p) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*op_p))) |
291 | merge_alias_info (*op_p, val); | |
d00ad49b AM |
292 | *op_p = val; |
293 | } | |
294 | else | |
19114537 | 295 | *op_p = unsave_expr_now (val); |
d00ad49b AM |
296 | } |
297 | ||
ff2ad0f7 | 298 | |
6de9cd9a DN |
299 | /* Replace *OP_P with value VAL (assumed to be a constant or another SSA_NAME). |
300 | ||
301 | Use this version when not const/copy propagating values. For example, | |
302 | PRE uses this version when building expressions as they would appear | |
303 | in specific blocks taking into account actions of PHI nodes. */ | |
304 | ||
305 | void | |
d00ad49b | 306 | replace_exp (use_operand_p op_p, tree val) |
6de9cd9a DN |
307 | { |
308 | replace_exp_1 (op_p, val, false); | |
309 | } | |
0bca51f0 DN |
310 | |
311 | ||
312 | /*--------------------------------------------------------------------------- | |
313 | Copy propagation | |
314 | ---------------------------------------------------------------------------*/ | |
315 | /* During propagation, we keep chains of variables that are copies of | |
316 | one another. If variable X_i is a copy of X_j and X_j is a copy of | |
317 | X_k, COPY_OF will contain: | |
318 | ||
319 | COPY_OF[i].VALUE = X_j | |
320 | COPY_OF[j].VALUE = X_k | |
321 | COPY_OF[k].VALUE = X_k | |
322 | ||
323 | After propagation, the copy-of value for each variable X_i is | |
324 | converted into the final value by walking the copy-of chains and | |
325 | updating COPY_OF[i].VALUE to be the last element of the chain. */ | |
326 | static prop_value_t *copy_of; | |
327 | ||
328 | /* Used in set_copy_of_val to determine if the last link of a copy-of | |
329 | chain has changed. */ | |
330 | static tree *cached_last_copy_of; | |
331 | ||
332 | /* True if we are doing copy propagation on loads and stores. */ | |
333 | static bool do_store_copy_prop; | |
334 | ||
335 | ||
336 | /* Return true if this statement may generate a useful copy. */ | |
337 | ||
338 | static bool | |
339 | stmt_may_generate_copy (tree stmt) | |
340 | { | |
341 | tree lhs, rhs; | |
342 | stmt_ann_t ann; | |
343 | ||
344 | if (TREE_CODE (stmt) == PHI_NODE) | |
345 | return !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (stmt)); | |
346 | ||
347 | if (TREE_CODE (stmt) != MODIFY_EXPR) | |
348 | return false; | |
349 | ||
350 | lhs = TREE_OPERAND (stmt, 0); | |
351 | rhs = TREE_OPERAND (stmt, 1); | |
352 | ann = stmt_ann (stmt); | |
353 | ||
354 | /* If the statement has volatile operands, it won't generate a | |
355 | useful copy. */ | |
356 | if (ann->has_volatile_ops) | |
357 | return false; | |
358 | ||
359 | /* If we are not doing store copy-prop, statements with loads and/or | |
360 | stores will never generate a useful copy. */ | |
361 | if (!do_store_copy_prop | |
f47c96aa | 362 | && !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)) |
0bca51f0 DN |
363 | return false; |
364 | ||
365 | /* Otherwise, the only statements that generate useful copies are | |
366 | assignments whose RHS is just an SSA name that doesn't flow | |
367 | through abnormal edges. */ | |
368 | return TREE_CODE (rhs) == SSA_NAME && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (rhs); | |
369 | } | |
370 | ||
371 | ||
372 | /* Return the copy-of value for VAR. */ | |
373 | ||
374 | static inline prop_value_t * | |
375 | get_copy_of_val (tree var) | |
376 | { | |
377 | prop_value_t *val = ©_of[SSA_NAME_VERSION (var)]; | |
378 | ||
379 | if (val->value == NULL_TREE | |
380 | && !stmt_may_generate_copy (SSA_NAME_DEF_STMT (var))) | |
381 | { | |
382 | /* If the variable will never generate a useful copy relation, | |
383 | make it its own copy. */ | |
384 | val->value = var; | |
385 | val->mem_ref = NULL_TREE; | |
386 | } | |
387 | ||
388 | return val; | |
389 | } | |
390 | ||
391 | ||
392 | /* Return last link in the copy-of chain for VAR. */ | |
393 | ||
394 | static tree | |
395 | get_last_copy_of (tree var) | |
396 | { | |
397 | tree last; | |
398 | int i; | |
399 | ||
400 | /* Traverse COPY_OF starting at VAR until we get to the last | |
401 | link in the chain. Since it is possible to have cycles in PHI | |
402 | nodes, the copy-of chain may also contain cycles. | |
403 | ||
404 | To avoid infinite loops and to avoid traversing lengthy copy-of | |
405 | chains, we artificially limit the maximum number of chains we are | |
406 | willing to traverse. | |
407 | ||
408 | The value 5 was taken from a compiler and runtime library | |
409 | bootstrap and a mixture of C and C++ code from various sources. | |
410 | More than 82% of all copy-of chains were shorter than 5 links. */ | |
411 | #define LIMIT 5 | |
412 | ||
413 | last = var; | |
414 | for (i = 0; i < LIMIT; i++) | |
415 | { | |
416 | tree copy = copy_of[SSA_NAME_VERSION (last)].value; | |
417 | if (copy == NULL_TREE || copy == last) | |
418 | break; | |
419 | last = copy; | |
420 | } | |
421 | ||
422 | /* If we have reached the limit, then we are either in a copy-of | |
423 | cycle or the copy-of chain is too long. In this case, just | |
424 | return VAR so that it is not considered a copy of anything. */ | |
425 | return (i < LIMIT ? last : var); | |
426 | } | |
427 | ||
428 | ||
429 | /* Set FIRST to be the first variable in the copy-of chain for DEST. | |
f3b569ca | 430 | If DEST's copy-of value or its copy-of chain has changed, return |
0bca51f0 DN |
431 | true. |
432 | ||
433 | MEM_REF is the memory reference where FIRST is stored. This is | |
434 | used when DEST is a non-register and we are copy propagating loads | |
435 | and stores. */ | |
436 | ||
437 | static inline bool | |
438 | set_copy_of_val (tree dest, tree first, tree mem_ref) | |
439 | { | |
440 | unsigned int dest_ver = SSA_NAME_VERSION (dest); | |
441 | tree old_first, old_last, new_last; | |
442 | ||
443 | /* Set FIRST to be the first link in COPY_OF[DEST]. If that | |
444 | changed, return true. */ | |
445 | old_first = copy_of[dest_ver].value; | |
446 | copy_of[dest_ver].value = first; | |
447 | copy_of[dest_ver].mem_ref = mem_ref; | |
448 | ||
449 | if (old_first != first) | |
450 | return true; | |
451 | ||
452 | /* If FIRST and OLD_FIRST are the same, we need to check whether the | |
453 | copy-of chain starting at FIRST ends in a different variable. If | |
454 | the copy-of chain starting at FIRST ends up in a different | |
455 | variable than the last cached value we had for DEST, then return | |
456 | true because DEST is now a copy of a different variable. | |
457 | ||
458 | This test is necessary because even though the first link in the | |
459 | copy-of chain may not have changed, if any of the variables in | |
460 | the copy-of chain changed its final value, DEST will now be the | |
461 | copy of a different variable, so we have to do another round of | |
462 | propagation for everything that depends on DEST. */ | |
463 | old_last = cached_last_copy_of[dest_ver]; | |
464 | new_last = get_last_copy_of (dest); | |
465 | cached_last_copy_of[dest_ver] = new_last; | |
466 | ||
467 | return (old_last != new_last); | |
468 | } | |
469 | ||
470 | ||
471 | /* Dump the copy-of value for variable VAR to DUMP_FILE. */ | |
472 | ||
473 | static void | |
474 | dump_copy_of (FILE *dump_file, tree var) | |
475 | { | |
476 | tree val; | |
fb03baf2 | 477 | sbitmap visited; |
0bca51f0 DN |
478 | |
479 | print_generic_expr (dump_file, var, dump_flags); | |
480 | ||
481 | if (TREE_CODE (var) != SSA_NAME) | |
482 | return; | |
fb03baf2 AP |
483 | |
484 | visited = sbitmap_alloc (num_ssa_names); | |
50e5241d | 485 | sbitmap_zero (visited); |
fb03baf2 AP |
486 | SET_BIT (visited, SSA_NAME_VERSION (var)); |
487 | ||
0bca51f0 DN |
488 | fprintf (dump_file, " copy-of chain: "); |
489 | ||
490 | val = var; | |
491 | print_generic_expr (dump_file, val, 0); | |
492 | fprintf (dump_file, " "); | |
fb03baf2 | 493 | while (copy_of[SSA_NAME_VERSION (val)].value) |
0bca51f0 DN |
494 | { |
495 | fprintf (dump_file, "-> "); | |
496 | val = copy_of[SSA_NAME_VERSION (val)].value; | |
497 | print_generic_expr (dump_file, val, 0); | |
498 | fprintf (dump_file, " "); | |
fb03baf2 AP |
499 | if (TEST_BIT (visited, SSA_NAME_VERSION (val))) |
500 | break; | |
501 | SET_BIT (visited, SSA_NAME_VERSION (val)); | |
0bca51f0 DN |
502 | } |
503 | ||
504 | val = get_copy_of_val (var)->value; | |
505 | if (val == NULL_TREE) | |
506 | fprintf (dump_file, "[UNDEFINED]"); | |
507 | else if (val != var) | |
508 | fprintf (dump_file, "[COPY]"); | |
509 | else | |
510 | fprintf (dump_file, "[NOT A COPY]"); | |
fb03baf2 AP |
511 | |
512 | sbitmap_free (visited); | |
0bca51f0 DN |
513 | } |
514 | ||
515 | ||
516 | /* Evaluate the RHS of STMT. If it produces a valid copy, set the LHS | |
517 | value and store the LHS into *RESULT_P. If STMT generates more | |
518 | than one name (i.e., STMT is an aliased store), it is enough to | |
519 | store the first name in the V_MAY_DEF list into *RESULT_P. After | |
520 | all, the names generated will be VUSEd in the same statements. */ | |
521 | ||
522 | static enum ssa_prop_result | |
523 | copy_prop_visit_assignment (tree stmt, tree *result_p) | |
524 | { | |
525 | tree lhs, rhs; | |
526 | prop_value_t *rhs_val; | |
527 | ||
528 | lhs = TREE_OPERAND (stmt, 0); | |
529 | rhs = TREE_OPERAND (stmt, 1); | |
530 | ||
531 | gcc_assert (TREE_CODE (rhs) == SSA_NAME); | |
532 | ||
533 | rhs_val = get_copy_of_val (rhs); | |
534 | ||
535 | if (TREE_CODE (lhs) == SSA_NAME) | |
536 | { | |
537 | /* Straight copy between two SSA names. First, make sure that | |
538 | we can propagate the RHS into uses of LHS. */ | |
539 | if (!may_propagate_copy (lhs, rhs)) | |
540 | return SSA_PROP_VARYING; | |
541 | ||
542 | /* Avoid copy propagation from an inner into an outer loop. | |
543 | Otherwise, this may move loop variant variables outside of | |
544 | their loops and prevent coalescing opportunities. If the | |
545 | value was loop invariant, it will be hoisted by LICM and | |
546 | exposed for copy propagation. */ | |
547 | if (loop_depth_of_name (rhs) > loop_depth_of_name (lhs)) | |
548 | return SSA_PROP_VARYING; | |
549 | ||
550 | /* Notice that in the case of assignments, we make the LHS be a | |
551 | copy of RHS's value, not of RHS itself. This avoids keeping | |
552 | unnecessary copy-of chains (assignments cannot be in a cycle | |
553 | like PHI nodes), speeding up the propagation process. | |
554 | This is different from what we do in copy_prop_visit_phi_node. | |
555 | In those cases, we are interested in the copy-of chains. */ | |
556 | *result_p = lhs; | |
557 | if (set_copy_of_val (*result_p, rhs_val->value, rhs_val->mem_ref)) | |
558 | return SSA_PROP_INTERESTING; | |
559 | else | |
560 | return SSA_PROP_NOT_INTERESTING; | |
561 | } | |
562 | else if (stmt_makes_single_store (stmt)) | |
563 | { | |
564 | /* Otherwise, set the names in V_MAY_DEF/V_MUST_DEF operands | |
565 | to be a copy of RHS. */ | |
566 | ssa_op_iter i; | |
567 | tree vdef; | |
568 | bool changed; | |
569 | ||
570 | /* This should only be executed when doing store copy-prop. */ | |
571 | gcc_assert (do_store_copy_prop); | |
572 | ||
573 | /* Set the value of every VDEF to RHS_VAL. */ | |
574 | changed = false; | |
575 | FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, i, SSA_OP_VIRTUAL_DEFS) | |
576 | changed |= set_copy_of_val (vdef, rhs_val->value, lhs); | |
577 | ||
578 | /* Note that for propagation purposes, we are only interested in | |
579 | visiting statements that load the exact same memory reference | |
580 | stored here. Those statements will have the exact same list | |
581 | of virtual uses, so it is enough to set the output of this | |
582 | statement to be its first virtual definition. */ | |
583 | *result_p = first_vdef (stmt); | |
584 | ||
585 | if (changed) | |
586 | return SSA_PROP_INTERESTING; | |
587 | else | |
588 | return SSA_PROP_NOT_INTERESTING; | |
589 | } | |
590 | ||
591 | ||
592 | return SSA_PROP_VARYING; | |
593 | } | |
594 | ||
595 | ||
596 | /* Visit the COND_EXPR STMT. Return SSA_PROP_INTERESTING | |
597 | if it can determine which edge will be taken. Otherwise, return | |
598 | SSA_PROP_VARYING. */ | |
599 | ||
600 | static enum ssa_prop_result | |
601 | copy_prop_visit_cond_stmt (tree stmt, edge *taken_edge_p) | |
602 | { | |
603 | enum ssa_prop_result retval; | |
604 | tree cond; | |
0bca51f0 DN |
605 | |
606 | cond = COND_EXPR_COND (stmt); | |
0bca51f0 DN |
607 | retval = SSA_PROP_VARYING; |
608 | ||
609 | /* The only conditionals that we may be able to compute statically | |
691aed8c | 610 | are predicates involving two SSA_NAMEs. */ |
7da4bf7d | 611 | if (COMPARISON_CLASS_P (cond) |
691aed8c KH |
612 | && TREE_CODE (TREE_OPERAND (cond, 0)) == SSA_NAME |
613 | && TREE_CODE (TREE_OPERAND (cond, 1)) == SSA_NAME) | |
0bca51f0 | 614 | { |
691aed8c KH |
615 | tree op0 = get_last_copy_of (TREE_OPERAND (cond, 0)); |
616 | tree op1 = get_last_copy_of (TREE_OPERAND (cond, 1)); | |
0bca51f0 DN |
617 | |
618 | /* See if we can determine the predicate's value. */ | |
619 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
620 | { | |
621 | fprintf (dump_file, "Trying to determine truth value of "); | |
622 | fprintf (dump_file, "predicate "); | |
623 | print_generic_stmt (dump_file, cond, 0); | |
624 | } | |
625 | ||
691aed8c KH |
626 | /* We can fold COND and get a useful result only when we have |
627 | the same SSA_NAME on both sides of a comparison operator. */ | |
628 | if (op0 == op1) | |
9fb6cbd9 | 629 | { |
691aed8c KH |
630 | tree folded_cond = fold_binary (TREE_CODE (cond), boolean_type_node, |
631 | op0, op1); | |
632 | if (folded_cond) | |
633 | { | |
634 | basic_block bb = bb_for_stmt (stmt); | |
635 | *taken_edge_p = find_taken_edge (bb, folded_cond); | |
636 | if (*taken_edge_p) | |
637 | retval = SSA_PROP_INTERESTING; | |
638 | } | |
9fb6cbd9 | 639 | } |
0bca51f0 DN |
640 | } |
641 | ||
642 | if (dump_file && (dump_flags & TDF_DETAILS) && *taken_edge_p) | |
643 | fprintf (dump_file, "\nConditional will always take edge %d->%d\n", | |
644 | (*taken_edge_p)->src->index, (*taken_edge_p)->dest->index); | |
645 | ||
646 | return retval; | |
647 | } | |
648 | ||
649 | ||
650 | /* Evaluate statement STMT. If the statement produces a new output | |
651 | value, return SSA_PROP_INTERESTING and store the SSA_NAME holding | |
652 | the new value in *RESULT_P. | |
653 | ||
654 | If STMT is a conditional branch and we can determine its truth | |
655 | value, set *TAKEN_EDGE_P accordingly. | |
656 | ||
657 | If the new value produced by STMT is varying, return | |
658 | SSA_PROP_VARYING. */ | |
659 | ||
660 | static enum ssa_prop_result | |
661 | copy_prop_visit_stmt (tree stmt, edge *taken_edge_p, tree *result_p) | |
662 | { | |
663 | stmt_ann_t ann; | |
664 | enum ssa_prop_result retval; | |
665 | ||
666 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
667 | { | |
668 | fprintf (dump_file, "\nVisiting statement:\n"); | |
669 | print_generic_stmt (dump_file, stmt, dump_flags); | |
670 | fprintf (dump_file, "\n"); | |
671 | } | |
672 | ||
673 | ann = stmt_ann (stmt); | |
674 | ||
675 | if (TREE_CODE (stmt) == MODIFY_EXPR | |
676 | && TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME | |
677 | && (do_store_copy_prop | |
678 | || TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME)) | |
679 | { | |
680 | /* If the statement is a copy assignment, evaluate its RHS to | |
681 | see if the lattice value of its output has changed. */ | |
682 | retval = copy_prop_visit_assignment (stmt, result_p); | |
683 | } | |
684 | else if (TREE_CODE (stmt) == COND_EXPR) | |
685 | { | |
686 | /* See if we can determine which edge goes out of a conditional | |
687 | jump. */ | |
688 | retval = copy_prop_visit_cond_stmt (stmt, taken_edge_p); | |
689 | } | |
690 | else | |
691 | retval = SSA_PROP_VARYING; | |
692 | ||
693 | if (retval == SSA_PROP_VARYING) | |
694 | { | |
695 | tree def; | |
696 | ssa_op_iter i; | |
697 | ||
698 | /* Any other kind of statement is not interesting for constant | |
699 | propagation and, therefore, not worth simulating. */ | |
700 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
701 | fprintf (dump_file, "No interesting values produced.\n"); | |
702 | ||
703 | /* The assignment is not a copy operation. Don't visit this | |
704 | statement again and mark all the definitions in the statement | |
705 | to be copies of nothing. */ | |
706 | FOR_EACH_SSA_TREE_OPERAND (def, stmt, i, SSA_OP_ALL_DEFS) | |
707 | set_copy_of_val (def, def, NULL_TREE); | |
708 | } | |
709 | ||
710 | return retval; | |
711 | } | |
712 | ||
713 | ||
714 | /* Visit PHI node PHI. If all the arguments produce the same value, | |
715 | set it to be the value of the LHS of PHI. */ | |
716 | ||
717 | static enum ssa_prop_result | |
718 | copy_prop_visit_phi_node (tree phi) | |
719 | { | |
720 | enum ssa_prop_result retval; | |
721 | int i; | |
722 | tree lhs; | |
723 | prop_value_t phi_val = { 0, NULL_TREE, NULL_TREE }; | |
724 | ||
725 | lhs = PHI_RESULT (phi); | |
726 | ||
727 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
728 | { | |
729 | fprintf (dump_file, "\nVisiting PHI node: "); | |
730 | print_generic_expr (dump_file, phi, dump_flags); | |
731 | fprintf (dump_file, "\n\n"); | |
732 | } | |
733 | ||
734 | for (i = 0; i < PHI_NUM_ARGS (phi); i++) | |
735 | { | |
736 | prop_value_t *arg_val; | |
737 | tree arg = PHI_ARG_DEF (phi, i); | |
738 | edge e = PHI_ARG_EDGE (phi, i); | |
739 | ||
740 | /* We don't care about values flowing through non-executable | |
741 | edges. */ | |
742 | if (!(e->flags & EDGE_EXECUTABLE)) | |
743 | continue; | |
744 | ||
745 | /* Constants in the argument list never generate a useful copy. | |
746 | Similarly, names that flow through abnormal edges cannot be | |
747 | used to derive copies. */ | |
748 | if (TREE_CODE (arg) != SSA_NAME || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (arg)) | |
749 | { | |
750 | phi_val.value = lhs; | |
751 | break; | |
752 | } | |
753 | ||
754 | /* Avoid copy propagation from an inner into an outer loop. | |
755 | Otherwise, this may move loop variant variables outside of | |
756 | their loops and prevent coalescing opportunities. If the | |
757 | value was loop invariant, it will be hoisted by LICM and | |
758 | exposed for copy propagation. */ | |
759 | if (loop_depth_of_name (arg) > loop_depth_of_name (lhs)) | |
760 | { | |
761 | phi_val.value = lhs; | |
762 | break; | |
763 | } | |
764 | ||
765 | /* If the LHS appears in the argument list, ignore it. It is | |
766 | irrelevant as a copy. */ | |
767 | if (arg == lhs || get_last_copy_of (arg) == lhs) | |
768 | continue; | |
769 | ||
770 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
771 | { | |
772 | fprintf (dump_file, "\tArgument #%d: ", i); | |
773 | dump_copy_of (dump_file, arg); | |
774 | fprintf (dump_file, "\n"); | |
775 | } | |
776 | ||
777 | arg_val = get_copy_of_val (arg); | |
778 | ||
779 | /* If the LHS didn't have a value yet, make it a copy of the | |
780 | first argument we find. Notice that while we make the LHS be | |
781 | a copy of the argument itself, we take the memory reference | |
782 | from the argument's value so that we can compare it to the | |
783 | memory reference of all the other arguments. */ | |
784 | if (phi_val.value == NULL_TREE) | |
785 | { | |
786 | phi_val.value = arg; | |
787 | phi_val.mem_ref = arg_val->mem_ref; | |
788 | continue; | |
789 | } | |
790 | ||
791 | /* If PHI_VAL and ARG don't have a common copy-of chain, then | |
792 | this PHI node cannot be a copy operation. Also, if we are | |
793 | copy propagating stores and these two arguments came from | |
794 | different memory references, they cannot be considered | |
795 | copies. */ | |
796 | if (get_last_copy_of (phi_val.value) != get_last_copy_of (arg) | |
797 | || (do_store_copy_prop | |
798 | && phi_val.mem_ref | |
799 | && arg_val->mem_ref | |
800 | && simple_cst_equal (phi_val.mem_ref, arg_val->mem_ref) != 1)) | |
801 | { | |
802 | phi_val.value = lhs; | |
803 | break; | |
804 | } | |
805 | } | |
806 | ||
807 | if (phi_val.value && set_copy_of_val (lhs, phi_val.value, phi_val.mem_ref)) | |
808 | retval = (phi_val.value != lhs) ? SSA_PROP_INTERESTING : SSA_PROP_VARYING; | |
809 | else | |
810 | retval = SSA_PROP_NOT_INTERESTING; | |
811 | ||
812 | if (dump_file && (dump_flags & TDF_DETAILS)) | |
813 | { | |
814 | fprintf (dump_file, "\nPHI node "); | |
815 | dump_copy_of (dump_file, lhs); | |
816 | fprintf (dump_file, "\nTelling the propagator to "); | |
817 | if (retval == SSA_PROP_INTERESTING) | |
818 | fprintf (dump_file, "add SSA edges out of this PHI and continue."); | |
819 | else if (retval == SSA_PROP_VARYING) | |
820 | fprintf (dump_file, "add SSA edges out of this PHI and never visit again."); | |
821 | else | |
822 | fprintf (dump_file, "do nothing with SSA edges and keep iterating."); | |
823 | fprintf (dump_file, "\n\n"); | |
824 | } | |
825 | ||
826 | return retval; | |
827 | } | |
828 | ||
829 | ||
830 | /* Initialize structures used for copy propagation. */ | |
831 | ||
832 | static void | |
833 | init_copy_prop (void) | |
834 | { | |
835 | basic_block bb; | |
836 | ||
837 | copy_of = xmalloc (num_ssa_names * sizeof (*copy_of)); | |
838 | memset (copy_of, 0, num_ssa_names * sizeof (*copy_of)); | |
839 | ||
840 | cached_last_copy_of = xmalloc (num_ssa_names * sizeof (*cached_last_copy_of)); | |
841 | memset (cached_last_copy_of, 0, num_ssa_names * sizeof (*cached_last_copy_of)); | |
842 | ||
843 | FOR_EACH_BB (bb) | |
844 | { | |
845 | block_stmt_iterator si; | |
846 | tree phi; | |
847 | ||
848 | for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si)) | |
849 | { | |
850 | tree stmt = bsi_stmt (si); | |
851 | ||
852 | /* The only statements that we care about are those that may | |
853 | generate useful copies. We also need to mark conditional | |
854 | jumps so that their outgoing edges are added to the work | |
855 | lists of the propagator. */ | |
856 | if (stmt_ends_bb_p (stmt)) | |
857 | DONT_SIMULATE_AGAIN (stmt) = false; | |
858 | else if (stmt_may_generate_copy (stmt)) | |
859 | DONT_SIMULATE_AGAIN (stmt) = false; | |
860 | else | |
861 | { | |
862 | tree def; | |
863 | ssa_op_iter iter; | |
864 | ||
865 | /* No need to simulate this statement anymore. */ | |
866 | DONT_SIMULATE_AGAIN (stmt) = true; | |
867 | ||
868 | /* Mark all the outputs of this statement as not being | |
869 | the copy of anything. */ | |
870 | FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS) | |
871 | set_copy_of_val (def, def, NULL_TREE); | |
872 | } | |
873 | } | |
874 | ||
875 | for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) | |
876 | DONT_SIMULATE_AGAIN (phi) = false; | |
877 | } | |
878 | } | |
879 | ||
880 | ||
881 | /* Deallocate memory used in copy propagation and do final | |
882 | substitution. */ | |
883 | ||
884 | static void | |
885 | fini_copy_prop (void) | |
886 | { | |
887 | size_t i; | |
674391b8 | 888 | prop_value_t *tmp; |
0bca51f0 DN |
889 | |
890 | /* Set the final copy-of value for each variable by traversing the | |
891 | copy-of chains. */ | |
674391b8 DN |
892 | tmp = xmalloc (num_ssa_names * sizeof (*tmp)); |
893 | memset (tmp, 0, num_ssa_names * sizeof (*tmp)); | |
0bca51f0 DN |
894 | for (i = 1; i < num_ssa_names; i++) |
895 | { | |
896 | tree var = ssa_name (i); | |
897 | if (var && copy_of[i].value && copy_of[i].value != var) | |
674391b8 | 898 | tmp[i].value = get_last_copy_of (var); |
0bca51f0 DN |
899 | } |
900 | ||
674391b8 | 901 | substitute_and_fold (tmp, false); |
0bca51f0 | 902 | |
c5f083ef | 903 | free (cached_last_copy_of); |
0bca51f0 | 904 | free (copy_of); |
674391b8 | 905 | free (tmp); |
0bca51f0 DN |
906 | } |
907 | ||
908 | ||
909 | /* Main entry point to the copy propagator. The algorithm propagates | |
910 | the value COPY-OF using ssa_propagate. For every variable X_i, | |
911 | COPY-OF(X_i) indicates which variable is X_i created from. The | |
912 | following example shows how the algorithm proceeds at a high level: | |
913 | ||
914 | 1 a_24 = x_1 | |
915 | 2 a_2 = PHI <a_24, x_1> | |
916 | 3 a_5 = PHI <a_2> | |
917 | 4 x_1 = PHI <x_298, a_5, a_2> | |
918 | ||
919 | The end result should be that a_2, a_5, a_24 and x_1 are a copy of | |
920 | x_298. Propagation proceeds as follows. | |
921 | ||
922 | Visit #1: a_24 is copy-of x_1. Value changed. | |
923 | Visit #2: a_2 is copy-of x_1. Value changed. | |
924 | Visit #3: a_5 is copy-of x_1. Value changed. | |
925 | Visit #4: x_1 is copy-of x_298. Value changed. | |
926 | Visit #1: a_24 is copy-of x_298. Value changed. | |
927 | Visit #2: a_2 is copy-of x_298. Value changed. | |
928 | Visit #3: a_5 is copy-of x_298. Value changed. | |
929 | Visit #4: x_1 is copy-of x_298. Stable state reached. | |
930 | ||
931 | When visiting PHI nodes, we only consider arguments that flow | |
932 | through edges marked executable by the propagation engine. So, | |
933 | when visiting statement #2 for the first time, we will only look at | |
934 | the first argument (a_24) and optimistically assume that its value | |
935 | is the copy of a_24 (x_1). | |
936 | ||
937 | The problem with this approach is that it may fail to discover copy | |
938 | relations in PHI cycles. Instead of propagating copy-of | |
939 | values, we actually propagate copy-of chains. For instance: | |
940 | ||
941 | A_3 = B_1; | |
942 | C_9 = A_3; | |
943 | D_4 = C_9; | |
944 | X_i = D_4; | |
945 | ||
946 | In this code fragment, COPY-OF (X_i) = { D_4, C_9, A_3, B_1 }. | |
947 | Obviously, we are only really interested in the last value of the | |
948 | chain, however the propagator needs to access the copy-of chain | |
949 | when visiting PHI nodes. | |
950 | ||
951 | To represent the copy-of chain, we use the array COPY_CHAINS, which | |
952 | holds the first link in the copy-of chain for every variable. | |
953 | If variable X_i is a copy of X_j, which in turn is a copy of X_k, | |
954 | the array will contain: | |
955 | ||
956 | COPY_CHAINS[i] = X_j | |
957 | COPY_CHAINS[j] = X_k | |
958 | COPY_CHAINS[k] = X_k | |
959 | ||
960 | Keeping copy-of chains instead of copy-of values directly becomes | |
961 | important when visiting PHI nodes. Suppose that we had the | |
962 | following PHI cycle, such that x_52 is already considered a copy of | |
963 | x_53: | |
964 | ||
965 | 1 x_54 = PHI <x_53, x_52> | |
966 | 2 x_53 = PHI <x_898, x_54> | |
967 | ||
968 | Visit #1: x_54 is copy-of x_53 (because x_52 is copy-of x_53) | |
969 | Visit #2: x_53 is copy-of x_898 (because x_54 is a copy of x_53, | |
970 | so it is considered irrelevant | |
971 | as a copy). | |
972 | Visit #1: x_54 is copy-of nothing (x_53 is a copy-of x_898 and | |
973 | x_52 is a copy of x_53, so | |
974 | they don't match) | |
975 | Visit #2: x_53 is copy-of nothing | |
976 | ||
977 | This problem is avoided by keeping a chain of copies, instead of | |
978 | the final copy-of value. Propagation will now only keep the first | |
979 | element of a variable's copy-of chain. When visiting PHI nodes, | |
980 | arguments are considered equal if their copy-of chains end in the | |
981 | same variable. So, as long as their copy-of chains overlap, we | |
982 | know that they will be a copy of the same variable, regardless of | |
983 | which variable that may be). | |
984 | ||
985 | Propagation would then proceed as follows (the notation a -> b | |
986 | means that a is a copy-of b): | |
987 | ||
988 | Visit #1: x_54 = PHI <x_53, x_52> | |
989 | x_53 -> x_53 | |
990 | x_52 -> x_53 | |
991 | Result: x_54 -> x_53. Value changed. Add SSA edges. | |
992 | ||
993 | Visit #1: x_53 = PHI <x_898, x_54> | |
994 | x_898 -> x_898 | |
995 | x_54 -> x_53 | |
996 | Result: x_53 -> x_898. Value changed. Add SSA edges. | |
997 | ||
998 | Visit #2: x_54 = PHI <x_53, x_52> | |
999 | x_53 -> x_898 | |
1000 | x_52 -> x_53 -> x_898 | |
1001 | Result: x_54 -> x_898. Value changed. Add SSA edges. | |
1002 | ||
1003 | Visit #2: x_53 = PHI <x_898, x_54> | |
1004 | x_898 -> x_898 | |
1005 | x_54 -> x_898 | |
1006 | Result: x_53 -> x_898. Value didn't change. Stable state | |
1007 | ||
1008 | Once the propagator stabilizes, we end up with the desired result | |
1009 | x_53 and x_54 are both copies of x_898. */ | |
1010 | ||
1011 | static void | |
1012 | execute_copy_prop (bool store_copy_prop) | |
1013 | { | |
1014 | do_store_copy_prop = store_copy_prop; | |
1015 | init_copy_prop (); | |
1016 | ssa_propagate (copy_prop_visit_stmt, copy_prop_visit_phi_node); | |
1017 | fini_copy_prop (); | |
1018 | } | |
1019 | ||
1020 | ||
1021 | static bool | |
1022 | gate_copy_prop (void) | |
1023 | { | |
1024 | return flag_tree_copy_prop != 0; | |
1025 | } | |
1026 | ||
1027 | static void | |
1028 | do_copy_prop (void) | |
1029 | { | |
1030 | execute_copy_prop (false); | |
1031 | } | |
1032 | ||
1033 | struct tree_opt_pass pass_copy_prop = | |
1034 | { | |
1035 | "copyprop", /* name */ | |
1036 | gate_copy_prop, /* gate */ | |
1037 | do_copy_prop, /* execute */ | |
1038 | NULL, /* sub */ | |
1039 | NULL, /* next */ | |
1040 | 0, /* static_pass_number */ | |
1041 | TV_TREE_COPY_PROP, /* tv_id */ | |
1042 | PROP_ssa | PROP_alias | PROP_cfg, /* properties_required */ | |
1043 | 0, /* properties_provided */ | |
1044 | 0, /* properties_destroyed */ | |
1045 | 0, /* todo_flags_start */ | |
1046 | TODO_cleanup_cfg | |
1047 | | TODO_dump_func | |
1048 | | TODO_ggc_collect | |
1049 | | TODO_verify_ssa | |
1050 | | TODO_update_ssa, /* todo_flags_finish */ | |
1051 | 0 /* letter */ | |
1052 | }; | |
1053 | ||
1054 | ||
1055 | static bool | |
1056 | gate_store_copy_prop (void) | |
1057 | { | |
1058 | /* STORE-COPY-PROP is enabled only with -ftree-store-copy-prop, but | |
1059 | when -fno-tree-store-copy-prop is specified, we should run | |
1060 | regular COPY-PROP. That's why the pass is enabled with either | |
1061 | flag. */ | |
1062 | return flag_tree_store_copy_prop != 0 || flag_tree_copy_prop != 0; | |
1063 | } | |
1064 | ||
1065 | static void | |
1066 | store_copy_prop (void) | |
1067 | { | |
1068 | /* If STORE-COPY-PROP is not enabled, we just run regular COPY-PROP. */ | |
1069 | execute_copy_prop (flag_tree_store_copy_prop != 0); | |
1070 | } | |
1071 | ||
1072 | struct tree_opt_pass pass_store_copy_prop = | |
1073 | { | |
1074 | "store_copyprop", /* name */ | |
1075 | gate_store_copy_prop, /* gate */ | |
1076 | store_copy_prop, /* execute */ | |
1077 | NULL, /* sub */ | |
1078 | NULL, /* next */ | |
1079 | 0, /* static_pass_number */ | |
1080 | TV_TREE_STORE_COPY_PROP, /* tv_id */ | |
1081 | PROP_ssa | PROP_alias | PROP_cfg, /* properties_required */ | |
1082 | 0, /* properties_provided */ | |
1083 | 0, /* properties_destroyed */ | |
1084 | 0, /* todo_flags_start */ | |
1085 | TODO_dump_func | |
1086 | | TODO_cleanup_cfg | |
1087 | | TODO_ggc_collect | |
1088 | | TODO_verify_ssa | |
1089 | | TODO_update_ssa, /* todo_flags_finish */ | |
1090 | 0 /* letter */ | |
1091 | }; |