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 }