Mercurial > hg > CbC > CbC_gcc
comparison gcc/tree-ssa-uncprop.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Routines for discovering and unpropagating edge equivalences. | 1 /* Routines for discovering and unpropagating edge equivalences. |
2 Copyright (C) 2005, 2007, 2008, 2010 | 2 Copyright (C) 2005-2017 Free Software Foundation, Inc. |
3 Free Software Foundation, Inc. | |
4 | 3 |
5 This file is part of GCC. | 4 This file is part of GCC. |
6 | 5 |
7 GCC is free software; you can redistribute it and/or modify | 6 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 | 7 it under the terms of the GNU General Public License as published by |
19 <http://www.gnu.org/licenses/>. */ | 18 <http://www.gnu.org/licenses/>. */ |
20 | 19 |
21 #include "config.h" | 20 #include "config.h" |
22 #include "system.h" | 21 #include "system.h" |
23 #include "coretypes.h" | 22 #include "coretypes.h" |
24 #include "tm.h" | 23 #include "backend.h" |
25 #include "tree.h" | 24 #include "tree.h" |
26 #include "flags.h" | 25 #include "gimple.h" |
27 #include "tm_p.h" | 26 #include "tree-pass.h" |
28 #include "basic-block.h" | 27 #include "ssa.h" |
29 #include "output.h" | 28 #include "fold-const.h" |
30 #include "function.h" | 29 #include "cfganal.h" |
31 #include "timevar.h" | 30 #include "gimple-iterator.h" |
32 #include "tree-dump.h" | 31 #include "tree-cfg.h" |
33 #include "tree-flow.h" | |
34 #include "domwalk.h" | 32 #include "domwalk.h" |
35 #include "tree-pass.h" | 33 #include "tree-hash-traits.h" |
36 #include "tree-ssa-propagate.h" | 34 #include "tree-ssa-live.h" |
37 #include "langhooks.h" | 35 #include "tree-ssa-coalesce.h" |
38 | 36 |
39 /* The basic structure describing an equivalency created by traversing | 37 /* The basic structure describing an equivalency created by traversing |
40 an edge. Traversing the edge effectively means that we can assume | 38 an edge. Traversing the edge effectively means that we can assume |
41 that we've seen an assignment LHS = RHS. */ | 39 that we've seen an assignment LHS = RHS. */ |
42 struct edge_equivalency | 40 struct edge_equivalency |
57 { | 55 { |
58 basic_block bb; | 56 basic_block bb; |
59 | 57 |
60 /* Walk over each block. If the block ends with a control statement, | 58 /* Walk over each block. If the block ends with a control statement, |
61 then it might create a useful equivalence. */ | 59 then it might create a useful equivalence. */ |
62 FOR_EACH_BB (bb) | 60 FOR_EACH_BB_FN (bb, cfun) |
63 { | 61 { |
64 gimple_stmt_iterator gsi = gsi_last_bb (bb); | 62 gimple_stmt_iterator gsi = gsi_last_bb (bb); |
65 gimple stmt; | 63 gimple *stmt; |
66 | 64 |
67 /* If the block does not end with a COND_EXPR or SWITCH_EXPR | 65 /* If the block does not end with a COND_EXPR or SWITCH_EXPR |
68 then there is nothing to do. */ | 66 then there is nothing to do. */ |
69 if (gsi_end_p (gsi)) | 67 if (gsi_end_p (gsi)) |
70 continue; | 68 continue; |
94 /* Special case comparing booleans against a constant as we | 92 /* Special case comparing booleans against a constant as we |
95 know the value of OP0 on both arms of the branch. i.e., we | 93 know the value of OP0 on both arms of the branch. i.e., we |
96 can record an equivalence for OP0 rather than COND. */ | 94 can record an equivalence for OP0 rather than COND. */ |
97 if (TREE_CODE (op0) == SSA_NAME | 95 if (TREE_CODE (op0) == SSA_NAME |
98 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0) | 96 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0) |
99 && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE | 97 && ssa_name_has_boolean_range (op0) |
100 && is_gimple_min_invariant (op1)) | 98 && is_gimple_min_invariant (op1) |
99 && (integer_zerop (op1) || integer_onep (op1))) | |
101 { | 100 { |
101 tree true_val = constant_boolean_node (true, TREE_TYPE (op0)); | |
102 tree false_val = constant_boolean_node (false, | |
103 TREE_TYPE (op0)); | |
102 if (code == EQ_EXPR) | 104 if (code == EQ_EXPR) |
103 { | 105 { |
104 equivalency = XNEW (struct edge_equivalency); | 106 equivalency = XNEW (struct edge_equivalency); |
105 equivalency->lhs = op0; | 107 equivalency->lhs = op0; |
106 equivalency->rhs = (integer_zerop (op1) | 108 equivalency->rhs = (integer_zerop (op1) |
107 ? boolean_false_node | 109 ? false_val |
108 : boolean_true_node); | 110 : true_val); |
109 true_edge->aux = equivalency; | 111 true_edge->aux = equivalency; |
110 | 112 |
111 equivalency = XNEW (struct edge_equivalency); | 113 equivalency = XNEW (struct edge_equivalency); |
112 equivalency->lhs = op0; | 114 equivalency->lhs = op0; |
113 equivalency->rhs = (integer_zerop (op1) | 115 equivalency->rhs = (integer_zerop (op1) |
114 ? boolean_true_node | 116 ? true_val |
115 : boolean_false_node); | 117 : false_val); |
116 false_edge->aux = equivalency; | 118 false_edge->aux = equivalency; |
117 } | 119 } |
118 else | 120 else |
119 { | 121 { |
120 equivalency = XNEW (struct edge_equivalency); | 122 equivalency = XNEW (struct edge_equivalency); |
121 equivalency->lhs = op0; | 123 equivalency->lhs = op0; |
122 equivalency->rhs = (integer_zerop (op1) | 124 equivalency->rhs = (integer_zerop (op1) |
123 ? boolean_true_node | 125 ? true_val |
124 : boolean_false_node); | 126 : false_val); |
125 true_edge->aux = equivalency; | 127 true_edge->aux = equivalency; |
126 | 128 |
127 equivalency = XNEW (struct edge_equivalency); | 129 equivalency = XNEW (struct edge_equivalency); |
128 equivalency->lhs = op0; | 130 equivalency->lhs = op0; |
129 equivalency->rhs = (integer_zerop (op1) | 131 equivalency->rhs = (integer_zerop (op1) |
130 ? boolean_false_node | 132 ? false_val |
131 : boolean_true_node); | 133 : true_val); |
132 false_edge->aux = equivalency; | 134 false_edge->aux = equivalency; |
133 } | 135 } |
134 } | 136 } |
135 | 137 |
136 else if (TREE_CODE (op0) == SSA_NAME | 138 else if (TREE_CODE (op0) == SSA_NAME |
141 { | 143 { |
142 /* For IEEE, -0.0 == 0.0, so we don't necessarily know | 144 /* For IEEE, -0.0 == 0.0, so we don't necessarily know |
143 the sign of a variable compared against zero. If | 145 the sign of a variable compared against zero. If |
144 we're honoring signed zeros, then we cannot record | 146 we're honoring signed zeros, then we cannot record |
145 this value unless we know that the value is nonzero. */ | 147 this value unless we know that the value is nonzero. */ |
146 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0))) | 148 if (HONOR_SIGNED_ZEROS (op0) |
147 && (TREE_CODE (op1) != REAL_CST | 149 && (TREE_CODE (op1) != REAL_CST |
148 || REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (op1)))) | 150 || real_equal (&dconst0, &TREE_REAL_CST (op1)))) |
149 continue; | 151 continue; |
150 | 152 |
151 equivalency = XNEW (struct edge_equivalency); | 153 equivalency = XNEW (struct edge_equivalency); |
152 equivalency->lhs = op0; | 154 equivalency->lhs = op0; |
153 equivalency->rhs = op1; | 155 equivalency->rhs = op1; |
165 /* For a SWITCH_EXPR, a case label which represents a single | 167 /* For a SWITCH_EXPR, a case label which represents a single |
166 value and which is the only case label which reaches the | 168 value and which is the only case label which reaches the |
167 target block creates an equivalence. */ | 169 target block creates an equivalence. */ |
168 else if (gimple_code (stmt) == GIMPLE_SWITCH) | 170 else if (gimple_code (stmt) == GIMPLE_SWITCH) |
169 { | 171 { |
170 tree cond = gimple_switch_index (stmt); | 172 gswitch *switch_stmt = as_a <gswitch *> (stmt); |
173 tree cond = gimple_switch_index (switch_stmt); | |
171 | 174 |
172 if (TREE_CODE (cond) == SSA_NAME | 175 if (TREE_CODE (cond) == SSA_NAME |
173 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond)) | 176 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond)) |
174 { | 177 { |
175 int i, n_labels = gimple_switch_num_labels (stmt); | 178 int i, n_labels = gimple_switch_num_labels (switch_stmt); |
176 tree *info = XCNEWVEC (tree, last_basic_block); | 179 tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun)); |
177 | 180 |
178 /* Walk over the case label vector. Record blocks | 181 /* Walk over the case label vector. Record blocks |
179 which are reached by a single case label which represents | 182 which are reached by a single case label which represents |
180 a single value. */ | 183 a single value. */ |
181 for (i = 0; i < n_labels; i++) | 184 for (i = 0; i < n_labels; i++) |
182 { | 185 { |
183 tree label = gimple_switch_label (stmt, i); | 186 tree label = gimple_switch_label (switch_stmt, i); |
184 basic_block bb = label_to_block (CASE_LABEL (label)); | 187 basic_block bb = label_to_block (CASE_LABEL (label)); |
185 | 188 |
186 if (CASE_HIGH (label) | 189 if (CASE_HIGH (label) |
187 || !CASE_LOW (label) | 190 || !CASE_LOW (label) |
188 || info[bb->index]) | 191 || info[bb->index]) |
191 info[bb->index] = label; | 194 info[bb->index] = label; |
192 } | 195 } |
193 | 196 |
194 /* Now walk over the blocks to determine which ones were | 197 /* Now walk over the blocks to determine which ones were |
195 marked as being reached by a useful case label. */ | 198 marked as being reached by a useful case label. */ |
196 for (i = 0; i < n_basic_blocks; i++) | 199 for (i = 0; i < n_basic_blocks_for_fn (cfun); i++) |
197 { | 200 { |
198 tree node = info[i]; | 201 tree node = info[i]; |
199 | 202 |
200 if (node != NULL | 203 if (node != NULL |
201 && node != error_mark_node) | 204 && node != error_mark_node) |
206 /* Record an equivalency on the edge from BB to basic | 209 /* Record an equivalency on the edge from BB to basic |
207 block I. */ | 210 block I. */ |
208 equivalency = XNEW (struct edge_equivalency); | 211 equivalency = XNEW (struct edge_equivalency); |
209 equivalency->rhs = x; | 212 equivalency->rhs = x; |
210 equivalency->lhs = cond; | 213 equivalency->lhs = cond; |
211 find_edge (bb, BASIC_BLOCK (i))->aux = equivalency; | 214 find_edge (bb, BASIC_BLOCK_FOR_FN (cfun, i))->aux = |
215 equivalency; | |
212 } | 216 } |
213 } | 217 } |
214 free (info); | 218 free (info); |
215 } | 219 } |
216 } | 220 } |
262 the RHS of an assignment). A value may be an SSA_NAME or an | 266 the RHS of an assignment). A value may be an SSA_NAME or an |
263 invariant. We may have several SSA_NAMEs with the same value, | 267 invariant. We may have several SSA_NAMEs with the same value, |
264 so with each value we have a list of SSA_NAMEs that have the | 268 so with each value we have a list of SSA_NAMEs that have the |
265 same value. */ | 269 same value. */ |
266 | 270 |
267 /* As we enter each block we record the value for any edge equivalency | 271 |
268 leading to this block. If no such edge equivalency exists, then we | 272 /* Main structure for recording equivalences into our hash table. */ |
269 record NULL. These equivalences are live until we leave the dominator | 273 struct equiv_hash_elt |
270 subtree rooted at the block where we record the equivalency. */ | 274 { |
271 static VEC(tree,heap) *equiv_stack; | 275 /* The value/key of this entry. */ |
276 tree value; | |
277 | |
278 /* List of SSA_NAMEs which have the same value/key. */ | |
279 vec<tree> equivalences; | |
280 }; | |
272 | 281 |
273 /* Global hash table implementing a mapping from invariant values | 282 /* Global hash table implementing a mapping from invariant values |
274 to a list of SSA_NAMEs which have the same value. We might be | 283 to a list of SSA_NAMEs which have the same value. We might be |
275 able to reuse tree-vn for this code. */ | 284 able to reuse tree-vn for this code. */ |
276 static htab_t equiv; | 285 static hash_map<tree, auto_vec<tree> > *val_ssa_equiv; |
277 | 286 |
278 /* Main structure for recording equivalences into our hash table. */ | |
279 struct equiv_hash_elt | |
280 { | |
281 /* The value/key of this entry. */ | |
282 tree value; | |
283 | |
284 /* List of SSA_NAMEs which have the same value/key. */ | |
285 VEC(tree,heap) *equivalences; | |
286 }; | |
287 | |
288 static void uncprop_enter_block (struct dom_walk_data *, basic_block); | |
289 static void uncprop_leave_block (struct dom_walk_data *, basic_block); | |
290 static void uncprop_into_successor_phis (basic_block); | 287 static void uncprop_into_successor_phis (basic_block); |
291 | |
292 /* Hashing and equality routines for the hash table. */ | |
293 | |
294 static hashval_t | |
295 equiv_hash (const void *p) | |
296 { | |
297 tree const value = ((const struct equiv_hash_elt *)p)->value; | |
298 return iterative_hash_expr (value, 0); | |
299 } | |
300 | |
301 static int | |
302 equiv_eq (const void *p1, const void *p2) | |
303 { | |
304 tree value1 = ((const struct equiv_hash_elt *)p1)->value; | |
305 tree value2 = ((const struct equiv_hash_elt *)p2)->value; | |
306 | |
307 return operand_equal_p (value1, value2, 0); | |
308 } | |
309 | |
310 /* Free an instance of equiv_hash_elt. */ | |
311 | |
312 static void | |
313 equiv_free (void *p) | |
314 { | |
315 struct equiv_hash_elt *elt = (struct equiv_hash_elt *) p; | |
316 VEC_free (tree, heap, elt->equivalences); | |
317 free (elt); | |
318 } | |
319 | 288 |
320 /* Remove the most recently recorded equivalency for VALUE. */ | 289 /* Remove the most recently recorded equivalency for VALUE. */ |
321 | 290 |
322 static void | 291 static void |
323 remove_equivalence (tree value) | 292 remove_equivalence (tree value) |
324 { | 293 { |
325 struct equiv_hash_elt equiv_hash_elt, *equiv_hash_elt_p; | 294 val_ssa_equiv->get (value)->pop (); |
326 void **slot; | |
327 | |
328 equiv_hash_elt.value = value; | |
329 equiv_hash_elt.equivalences = NULL; | |
330 | |
331 slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT); | |
332 | |
333 equiv_hash_elt_p = (struct equiv_hash_elt *) *slot; | |
334 VEC_pop (tree, equiv_hash_elt_p->equivalences); | |
335 } | 295 } |
336 | 296 |
337 /* Record EQUIVALENCE = VALUE into our hash table. */ | 297 /* Record EQUIVALENCE = VALUE into our hash table. */ |
338 | 298 |
339 static void | 299 static void |
340 record_equiv (tree value, tree equivalence) | 300 record_equiv (tree value, tree equivalence) |
341 { | 301 { |
342 struct equiv_hash_elt *equiv_hash_elt; | 302 val_ssa_equiv->get_or_insert (value).safe_push (equivalence); |
343 void **slot; | 303 } |
344 | 304 |
345 equiv_hash_elt = XNEW (struct equiv_hash_elt); | 305 class uncprop_dom_walker : public dom_walker |
346 equiv_hash_elt->value = value; | 306 { |
347 equiv_hash_elt->equivalences = NULL; | 307 public: |
348 | 308 uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {} |
349 slot = htab_find_slot (equiv, equiv_hash_elt, INSERT); | 309 |
350 | 310 virtual edge before_dom_children (basic_block); |
351 if (*slot == NULL) | 311 virtual void after_dom_children (basic_block); |
352 *slot = (void *) equiv_hash_elt; | 312 |
353 else | 313 private: |
354 free (equiv_hash_elt); | 314 |
355 | 315 /* As we enter each block we record the value for any edge equivalency |
356 equiv_hash_elt = (struct equiv_hash_elt *) *slot; | 316 leading to this block. If no such edge equivalency exists, then we |
357 | 317 record NULL. These equivalences are live until we leave the dominator |
358 VEC_safe_push (tree, heap, equiv_hash_elt->equivalences, equivalence); | 318 subtree rooted at the block where we record the equivalency. */ |
359 } | 319 auto_vec<tree, 2> m_equiv_stack; |
360 | 320 }; |
361 /* Main driver for un-cprop. */ | |
362 | |
363 static unsigned int | |
364 tree_ssa_uncprop (void) | |
365 { | |
366 struct dom_walk_data walk_data; | |
367 basic_block bb; | |
368 | |
369 associate_equivalences_with_edges (); | |
370 | |
371 /* Create our global data structures. */ | |
372 equiv = htab_create (1024, equiv_hash, equiv_eq, equiv_free); | |
373 equiv_stack = VEC_alloc (tree, heap, 2); | |
374 | |
375 /* We're going to do a dominator walk, so ensure that we have | |
376 dominance information. */ | |
377 calculate_dominance_info (CDI_DOMINATORS); | |
378 | |
379 /* Setup callbacks for the generic dominator tree walker. */ | |
380 walk_data.dom_direction = CDI_DOMINATORS; | |
381 walk_data.initialize_block_local_data = NULL; | |
382 walk_data.before_dom_children = uncprop_enter_block; | |
383 walk_data.after_dom_children = uncprop_leave_block; | |
384 walk_data.global_data = NULL; | |
385 walk_data.block_local_data_size = 0; | |
386 | |
387 /* Now initialize the dominator walker. */ | |
388 init_walk_dominator_tree (&walk_data); | |
389 | |
390 /* Recursively walk the dominator tree undoing unprofitable | |
391 constant/copy propagations. */ | |
392 walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR); | |
393 | |
394 /* Finalize and clean up. */ | |
395 fini_walk_dominator_tree (&walk_data); | |
396 | |
397 /* EQUIV_STACK should already be empty at this point, so we just | |
398 need to empty elements out of the hash table, free EQUIV_STACK, | |
399 and cleanup the AUX field on the edges. */ | |
400 htab_delete (equiv); | |
401 VEC_free (tree, heap, equiv_stack); | |
402 FOR_EACH_BB (bb) | |
403 { | |
404 edge e; | |
405 edge_iterator ei; | |
406 | |
407 FOR_EACH_EDGE (e, ei, bb->succs) | |
408 { | |
409 if (e->aux) | |
410 { | |
411 free (e->aux); | |
412 e->aux = NULL; | |
413 } | |
414 } | |
415 } | |
416 return 0; | |
417 } | |
418 | |
419 | 321 |
420 /* We have finished processing the dominator children of BB, perform | 322 /* We have finished processing the dominator children of BB, perform |
421 any finalization actions in preparation for leaving this node in | 323 any finalization actions in preparation for leaving this node in |
422 the dominator tree. */ | 324 the dominator tree. */ |
423 | 325 |
424 static void | 326 void |
425 uncprop_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, | 327 uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED) |
426 basic_block bb ATTRIBUTE_UNUSED) | |
427 { | 328 { |
428 /* Pop the topmost value off the equiv stack. */ | 329 /* Pop the topmost value off the equiv stack. */ |
429 tree value = VEC_pop (tree, equiv_stack); | 330 tree value = m_equiv_stack.pop (); |
430 | 331 |
431 /* If that value was non-null, then pop the topmost equivalency off | 332 /* If that value was non-null, then pop the topmost equivalency off |
432 its equivalency stack. */ | 333 its equivalency stack. */ |
433 if (value != NULL) | 334 if (value != NULL) |
434 remove_equivalence (value); | 335 remove_equivalence (value); |
463 } | 364 } |
464 | 365 |
465 /* Walk over the PHI nodes, unpropagating values. */ | 366 /* Walk over the PHI nodes, unpropagating values. */ |
466 for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi)) | 367 for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi)) |
467 { | 368 { |
468 gimple phi = gsi_stmt (gsi); | 369 gimple *phi = gsi_stmt (gsi); |
469 tree arg = PHI_ARG_DEF (phi, e->dest_idx); | 370 tree arg = PHI_ARG_DEF (phi, e->dest_idx); |
470 struct equiv_hash_elt equiv_hash_elt; | 371 tree res = PHI_RESULT (phi); |
471 void **slot; | 372 |
472 | 373 /* If the argument is not an invariant and can be potentially |
473 /* If the argument is not an invariant, or refers to the same | 374 coalesced with the result, then there's no point in |
474 underlying variable as the PHI result, then there's no | 375 un-propagating the argument. */ |
475 point in un-propagating the argument. */ | |
476 if (!is_gimple_min_invariant (arg) | 376 if (!is_gimple_min_invariant (arg) |
477 && SSA_NAME_VAR (arg) != SSA_NAME_VAR (PHI_RESULT (phi))) | 377 && gimple_can_coalesce_p (arg, res)) |
478 continue; | 378 continue; |
479 | 379 |
480 /* Lookup this argument's value in the hash table. */ | 380 /* Lookup this argument's value in the hash table. */ |
481 equiv_hash_elt.value = arg; | 381 vec<tree> *equivalences = val_ssa_equiv->get (arg); |
482 equiv_hash_elt.equivalences = NULL; | 382 if (equivalences) |
483 slot = htab_find_slot (equiv, &equiv_hash_elt, NO_INSERT); | |
484 | |
485 if (slot) | |
486 { | 383 { |
487 struct equiv_hash_elt *elt = (struct equiv_hash_elt *) *slot; | |
488 int j; | |
489 | |
490 /* Walk every equivalence with the same value. If we find | 384 /* Walk every equivalence with the same value. If we find |
491 one with the same underlying variable as the PHI result, | 385 one that can potentially coalesce with the PHI rsult, |
492 then replace the value in the argument with its equivalent | 386 then replace the value in the argument with its equivalent |
493 SSA_NAME. Use the most recent equivalence as hopefully | 387 SSA_NAME. Use the most recent equivalence as hopefully |
494 that results in shortest lifetimes. */ | 388 that results in shortest lifetimes. */ |
495 for (j = VEC_length (tree, elt->equivalences) - 1; j >= 0; j--) | 389 for (int j = equivalences->length () - 1; j >= 0; j--) |
496 { | 390 { |
497 tree equiv = VEC_index (tree, elt->equivalences, j); | 391 tree equiv = (*equivalences)[j]; |
498 | 392 |
499 if (SSA_NAME_VAR (equiv) == SSA_NAME_VAR (PHI_RESULT (phi))) | 393 if (gimple_can_coalesce_p (equiv, res)) |
500 { | 394 { |
501 SET_PHI_ARG_DEF (phi, e->dest_idx, equiv); | 395 SET_PHI_ARG_DEF (phi, e->dest_idx, equiv); |
502 break; | 396 break; |
503 } | 397 } |
504 } | 398 } |
541 } | 435 } |
542 | 436 |
543 return retval; | 437 return retval; |
544 } | 438 } |
545 | 439 |
546 static void | 440 edge |
547 uncprop_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, | 441 uncprop_dom_walker::before_dom_children (basic_block bb) |
548 basic_block bb) | |
549 { | 442 { |
550 basic_block parent; | 443 basic_block parent; |
551 edge e; | 444 edge e; |
552 bool recorded = false; | 445 bool recorded = false; |
553 | 446 |
562 if (e && e->src == parent && e->aux) | 455 if (e && e->src == parent && e->aux) |
563 { | 456 { |
564 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux; | 457 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux; |
565 | 458 |
566 record_equiv (equiv->rhs, equiv->lhs); | 459 record_equiv (equiv->rhs, equiv->lhs); |
567 VEC_safe_push (tree, heap, equiv_stack, equiv->rhs); | 460 m_equiv_stack.safe_push (equiv->rhs); |
568 recorded = true; | 461 recorded = true; |
569 } | 462 } |
570 } | 463 } |
571 | 464 |
572 if (!recorded) | 465 if (!recorded) |
573 VEC_safe_push (tree, heap, equiv_stack, NULL_TREE); | 466 m_equiv_stack.safe_push (NULL_TREE); |
574 | 467 |
575 uncprop_into_successor_phis (bb); | 468 uncprop_into_successor_phis (bb); |
576 } | 469 return NULL; |
577 | 470 } |
578 static bool | 471 |
579 gate_uncprop (void) | 472 namespace { |
580 { | 473 |
581 return flag_tree_dom != 0; | 474 const pass_data pass_data_uncprop = |
582 } | 475 { |
583 | 476 GIMPLE_PASS, /* type */ |
584 struct gimple_opt_pass pass_uncprop = | 477 "uncprop", /* name */ |
585 { | 478 OPTGROUP_NONE, /* optinfo_flags */ |
586 { | 479 TV_TREE_SSA_UNCPROP, /* tv_id */ |
587 GIMPLE_PASS, | 480 ( PROP_cfg | PROP_ssa ), /* properties_required */ |
588 "uncprop", /* name */ | 481 0, /* properties_provided */ |
589 gate_uncprop, /* gate */ | 482 0, /* properties_destroyed */ |
590 tree_ssa_uncprop, /* execute */ | 483 0, /* todo_flags_start */ |
591 NULL, /* sub */ | 484 0, /* todo_flags_finish */ |
592 NULL, /* next */ | |
593 0, /* static_pass_number */ | |
594 TV_TREE_SSA_UNCPROP, /* tv_id */ | |
595 PROP_cfg | PROP_ssa, /* properties_required */ | |
596 0, /* properties_provided */ | |
597 0, /* properties_destroyed */ | |
598 0, /* todo_flags_start */ | |
599 TODO_dump_func | TODO_verify_ssa /* todo_flags_finish */ | |
600 } | |
601 }; | 485 }; |
602 | 486 |
487 class pass_uncprop : public gimple_opt_pass | |
488 { | |
489 public: | |
490 pass_uncprop (gcc::context *ctxt) | |
491 : gimple_opt_pass (pass_data_uncprop, ctxt) | |
492 {} | |
493 | |
494 /* opt_pass methods: */ | |
495 opt_pass * clone () { return new pass_uncprop (m_ctxt); } | |
496 virtual bool gate (function *) { return flag_tree_dom != 0; } | |
497 virtual unsigned int execute (function *); | |
498 | |
499 }; // class pass_uncprop | |
500 | |
501 unsigned int | |
502 pass_uncprop::execute (function *fun) | |
503 { | |
504 basic_block bb; | |
505 | |
506 associate_equivalences_with_edges (); | |
507 | |
508 /* Create our global data structures. */ | |
509 val_ssa_equiv = new hash_map<tree, auto_vec<tree> > (1024); | |
510 | |
511 /* We're going to do a dominator walk, so ensure that we have | |
512 dominance information. */ | |
513 calculate_dominance_info (CDI_DOMINATORS); | |
514 | |
515 /* Recursively walk the dominator tree undoing unprofitable | |
516 constant/copy propagations. */ | |
517 uncprop_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr); | |
518 | |
519 /* we just need to empty elements out of the hash table, and cleanup the | |
520 AUX field on the edges. */ | |
521 delete val_ssa_equiv; | |
522 val_ssa_equiv = NULL; | |
523 FOR_EACH_BB_FN (bb, fun) | |
524 { | |
525 edge e; | |
526 edge_iterator ei; | |
527 | |
528 FOR_EACH_EDGE (e, ei, bb->succs) | |
529 { | |
530 if (e->aux) | |
531 { | |
532 free (e->aux); | |
533 e->aux = NULL; | |
534 } | |
535 } | |
536 } | |
537 return 0; | |
538 } | |
539 | |
540 } // anon namespace | |
541 | |
542 gimple_opt_pass * | |
543 make_pass_uncprop (gcc::context *ctxt) | |
544 { | |
545 return new pass_uncprop (ctxt); | |
546 } |