]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-uncprop.c
PR middle-end/58564
[thirdparty/gcc.git] / gcc / tree-ssa-uncprop.c
CommitLineData
5f718c29 1/* Routines for discovering and unpropagating edge equivalences.
711789cc 2 Copyright (C) 2005-2013 Free Software Foundation, Inc.
5f718c29 3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8c4c00c1 8the Free Software Foundation; either version 3, or (at your option)
5f718c29 9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
8c4c00c1 17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
5f718c29 19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "tm.h"
24#include "tree.h"
25#include "flags.h"
5f718c29 26#include "tm_p.h"
5f718c29 27#include "basic-block.h"
5f718c29 28#include "function.h"
69ee5dbb 29#include "tree-ssa.h"
5f718c29 30#include "domwalk.h"
5f718c29 31#include "tree-pass.h"
32#include "tree-ssa-propagate.h"
5f718c29 33
34/* The basic structure describing an equivalency created by traversing
35 an edge. Traversing the edge effectively means that we can assume
36 that we've seen an assignment LHS = RHS. */
37struct edge_equivalency
38{
39 tree rhs;
40 tree lhs;
41};
42
43/* This routine finds and records edge equivalences for every edge
44 in the CFG.
45
46 When complete, each edge that creates an equivalency will have an
48e1416a 47 EDGE_EQUIVALENCY structure hanging off the edge's AUX field.
5f718c29 48 The caller is responsible for freeing the AUX fields. */
49
50static void
51associate_equivalences_with_edges (void)
52{
53 basic_block bb;
54
55 /* Walk over each block. If the block ends with a control statement,
56 then it might create a useful equivalence. */
57 FOR_EACH_BB (bb)
58 {
75a70cf9 59 gimple_stmt_iterator gsi = gsi_last_bb (bb);
60 gimple stmt;
5f718c29 61
62 /* If the block does not end with a COND_EXPR or SWITCH_EXPR
63 then there is nothing to do. */
75a70cf9 64 if (gsi_end_p (gsi))
5f718c29 65 continue;
66
75a70cf9 67 stmt = gsi_stmt (gsi);
5f718c29 68
69 if (!stmt)
70 continue;
71
72 /* A COND_EXPR may create an equivalency in a variety of different
73 ways. */
75a70cf9 74 if (gimple_code (stmt) == GIMPLE_COND)
5f718c29 75 {
5f718c29 76 edge true_edge;
77 edge false_edge;
78 struct edge_equivalency *equivalency;
75a70cf9 79 enum tree_code code = gimple_cond_code (stmt);
5f718c29 80
81 extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
82
5f718c29 83 /* Equality tests may create one or two equivalences. */
75a70cf9 84 if (code == EQ_EXPR || code == NE_EXPR)
5f718c29 85 {
75a70cf9 86 tree op0 = gimple_cond_lhs (stmt);
87 tree op1 = gimple_cond_rhs (stmt);
5f718c29 88
89 /* Special case comparing booleans against a constant as we
90 know the value of OP0 on both arms of the branch. i.e., we
91 can record an equivalence for OP0 rather than COND. */
92 if (TREE_CODE (op0) == SSA_NAME
932540b6 93 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
5f718c29 94 && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
95 && is_gimple_min_invariant (op1))
96 {
75a70cf9 97 if (code == EQ_EXPR)
5f718c29 98 {
945865c5 99 equivalency = XNEW (struct edge_equivalency);
5f718c29 100 equivalency->lhs = op0;
101 equivalency->rhs = (integer_zerop (op1)
102 ? boolean_false_node
103 : boolean_true_node);
104 true_edge->aux = equivalency;
105
945865c5 106 equivalency = XNEW (struct edge_equivalency);
5f718c29 107 equivalency->lhs = op0;
108 equivalency->rhs = (integer_zerop (op1)
109 ? boolean_true_node
110 : boolean_false_node);
111 false_edge->aux = equivalency;
112 }
113 else
114 {
945865c5 115 equivalency = XNEW (struct edge_equivalency);
5f718c29 116 equivalency->lhs = op0;
117 equivalency->rhs = (integer_zerop (op1)
118 ? boolean_true_node
119 : boolean_false_node);
120 true_edge->aux = equivalency;
121
945865c5 122 equivalency = XNEW (struct edge_equivalency);
5f718c29 123 equivalency->lhs = op0;
124 equivalency->rhs = (integer_zerop (op1)
125 ? boolean_false_node
126 : boolean_true_node);
127 false_edge->aux = equivalency;
128 }
129 }
130
024e445d 131 else if (TREE_CODE (op0) == SSA_NAME
132 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
133 && (is_gimple_min_invariant (op1)
134 || (TREE_CODE (op1) == SSA_NAME
135 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
5f718c29 136 {
137 /* For IEEE, -0.0 == 0.0, so we don't necessarily know
138 the sign of a variable compared against zero. If
139 we're honoring signed zeros, then we cannot record
140 this value unless we know that the value is nonzero. */
141 if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (op0)))
142 && (TREE_CODE (op1) != REAL_CST
143 || REAL_VALUES_EQUAL (dconst0, TREE_REAL_CST (op1))))
144 continue;
145
945865c5 146 equivalency = XNEW (struct edge_equivalency);
5f718c29 147 equivalency->lhs = op0;
148 equivalency->rhs = op1;
75a70cf9 149 if (code == EQ_EXPR)
5f718c29 150 true_edge->aux = equivalency;
48e1416a 151 else
5f718c29 152 false_edge->aux = equivalency;
153
154 }
155 }
156
157 /* ??? TRUTH_NOT_EXPR can create an equivalence too. */
158 }
159
160 /* For a SWITCH_EXPR, a case label which represents a single
161 value and which is the only case label which reaches the
162 target block creates an equivalence. */
75a70cf9 163 else if (gimple_code (stmt) == GIMPLE_SWITCH)
5f718c29 164 {
75a70cf9 165 tree cond = gimple_switch_index (stmt);
5f718c29 166
932540b6 167 if (TREE_CODE (cond) == SSA_NAME
168 && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
5f718c29 169 {
75a70cf9 170 int i, n_labels = gimple_switch_num_labels (stmt);
87490e08 171 tree *info = XCNEWVEC (tree, last_basic_block);
5f718c29 172
173 /* Walk over the case label vector. Record blocks
174 which are reached by a single case label which represents
175 a single value. */
176 for (i = 0; i < n_labels; i++)
177 {
75a70cf9 178 tree label = gimple_switch_label (stmt, i);
5f718c29 179 basic_block bb = label_to_block (CASE_LABEL (label));
180
5f718c29 181 if (CASE_HIGH (label)
182 || !CASE_LOW (label)
183 || info[bb->index])
184 info[bb->index] = error_mark_node;
185 else
186 info[bb->index] = label;
187 }
188
189 /* Now walk over the blocks to determine which ones were
190 marked as being reached by a useful case label. */
191 for (i = 0; i < n_basic_blocks; i++)
192 {
193 tree node = info[i];
194
195 if (node != NULL
196 && node != error_mark_node)
197 {
198 tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
199 struct edge_equivalency *equivalency;
200
201 /* Record an equivalency on the edge from BB to basic
202 block I. */
945865c5 203 equivalency = XNEW (struct edge_equivalency);
5f718c29 204 equivalency->rhs = x;
205 equivalency->lhs = cond;
206 find_edge (bb, BASIC_BLOCK (i))->aux = equivalency;
207 }
208 }
209 free (info);
210 }
211 }
212
213 }
214}
215
216
217/* Translating out of SSA sometimes requires inserting copies and
218 constant initializations on edges to eliminate PHI nodes.
219
220 In some cases those copies and constant initializations are
221 redundant because the target already has the value on the
222 RHS of the assignment.
223
224 We previously tried to catch these cases after translating
225 out of SSA form. However, that code often missed cases. Worse
226 yet, the cases it missed were also often missed by the RTL
227 optimizers. Thus the resulting code had redundant instructions.
228
229 This pass attempts to detect these situations before translating
230 out of SSA form.
231
232 The key concept that this pass is built upon is that these
233 redundant copies and constant initializations often occur
234 due to constant/copy propagating equivalences resulting from
235 COND_EXPRs and SWITCH_EXPRs.
236
237 We want to do those propagations as they can sometimes allow
25f6297d 238 the SSA optimizers to do a better job. However, in the cases
5f718c29 239 where such propagations do not result in further optimization,
240 we would like to "undo" the propagation to avoid the redundant
241 copies and constant initializations.
242
243 This pass works by first associating equivalences with edges in
244 the CFG. For example, the edge leading from a SWITCH_EXPR to
245 its associated CASE_LABEL will have an equivalency between
246 SWITCH_COND and the value in the case label.
247
248 Once we have found the edge equivalences, we proceed to walk
249 the CFG in dominator order. As we traverse edges we record
250 equivalences associated with those edges we traverse.
251
252 When we encounter a PHI node, we walk its arguments to see if we
253 have an equivalence for the PHI argument. If so, then we replace
254 the argument.
255
256 Equivalences are looked up based on their value (think of it as
257 the RHS of an assignment). A value may be an SSA_NAME or an
258 invariant. We may have several SSA_NAMEs with the same value,
259 so with each value we have a list of SSA_NAMEs that have the
260 same value. */
261
5f718c29 262
5f718c29 263/* Main structure for recording equivalences into our hash table. */
264struct equiv_hash_elt
265{
266 /* The value/key of this entry. */
267 tree value;
268
269 /* List of SSA_NAMEs which have the same value/key. */
f1f41a6c 270 vec<tree> equivalences;
5f718c29 271};
272
d9dd21a8 273/* Value to ssa name equivalence hashtable helpers. */
5f718c29 274
d9dd21a8 275struct val_ssa_equiv_hasher
276{
277 typedef equiv_hash_elt value_type;
278 typedef equiv_hash_elt compare_type;
279 static inline hashval_t hash (const value_type *);
280 static inline bool equal (const value_type *, const compare_type *);
281 static inline void remove (value_type *);
282};
5f718c29 283
d9dd21a8 284inline hashval_t
285val_ssa_equiv_hasher::hash (const value_type *p)
5f718c29 286{
d9dd21a8 287 tree const value = p->value;
5f718c29 288 return iterative_hash_expr (value, 0);
289}
290
d9dd21a8 291inline bool
292val_ssa_equiv_hasher::equal (const value_type *p1, const compare_type *p2)
5f718c29 293{
d9dd21a8 294 tree value1 = p1->value;
295 tree value2 = p2->value;
5f718c29 296
297 return operand_equal_p (value1, value2, 0);
298}
299
96a7ab57 300/* Free an instance of equiv_hash_elt. */
301
d9dd21a8 302inline void
303val_ssa_equiv_hasher::remove (value_type *elt)
96a7ab57 304{
f1f41a6c 305 elt->equivalences.release ();
96a7ab57 306 free (elt);
307}
308
d9dd21a8 309/* Global hash table implementing a mapping from invariant values
310 to a list of SSA_NAMEs which have the same value. We might be
311 able to reuse tree-vn for this code. */
312static hash_table <val_ssa_equiv_hasher> val_ssa_equiv;
313
d9dd21a8 314static void uncprop_into_successor_phis (basic_block);
315
5f718c29 316/* Remove the most recently recorded equivalency for VALUE. */
317
318static void
319remove_equivalence (tree value)
320{
d9dd21a8 321 struct equiv_hash_elt an_equiv_elt, *an_equiv_elt_p;
322 equiv_hash_elt **slot;
5f718c29 323
d9dd21a8 324 an_equiv_elt.value = value;
325 an_equiv_elt.equivalences.create (0);
5f718c29 326
d9dd21a8 327 slot = val_ssa_equiv.find_slot (&an_equiv_elt, NO_INSERT);
5f718c29 328
d9dd21a8 329 an_equiv_elt_p = *slot;
330 an_equiv_elt_p->equivalences.pop ();
5f718c29 331}
332
333/* Record EQUIVALENCE = VALUE into our hash table. */
334
335static void
336record_equiv (tree value, tree equivalence)
337{
d9dd21a8 338 equiv_hash_elt *an_equiv_elt_p;
339 equiv_hash_elt **slot;
5f718c29 340
d9dd21a8 341 an_equiv_elt_p = XNEW (struct equiv_hash_elt);
342 an_equiv_elt_p->value = value;
343 an_equiv_elt_p->equivalences.create (0);
5f718c29 344
d9dd21a8 345 slot = val_ssa_equiv.find_slot (an_equiv_elt_p, INSERT);
5f718c29 346
347 if (*slot == NULL)
d9dd21a8 348 *slot = an_equiv_elt_p;
5f718c29 349 else
d9dd21a8 350 free (an_equiv_elt_p);
5f718c29 351
d9dd21a8 352 an_equiv_elt_p = *slot;
48e1416a 353
d9dd21a8 354 an_equiv_elt_p->equivalences.safe_push (equivalence);
5f718c29 355}
356
54c91640 357class uncprop_dom_walker : public dom_walker
358{
359public:
360 uncprop_dom_walker (cdi_direction direction)
361 : dom_walker (direction)
362 {
363 equiv_stack_.create (2);
364 }
365 ~uncprop_dom_walker ()
366 {
367 equiv_stack_.release ();
368 }
369
370 virtual void before_dom_children (basic_block);
371 virtual void after_dom_children (basic_block);
372
373private:
374
375/* As we enter each block we record the value for any edge equivalency
376 leading to this block. If no such edge equivalency exists, then we
377 record NULL. These equivalences are live until we leave the dominator
378 subtree rooted at the block where we record the equivalency. */
379 vec<tree> equiv_stack_;
380};
381
5f718c29 382/* Main driver for un-cprop. */
383
2a1990e9 384static unsigned int
5f718c29 385tree_ssa_uncprop (void)
386{
5f718c29 387 basic_block bb;
388
389 associate_equivalences_with_edges ();
390
391 /* Create our global data structures. */
d9dd21a8 392 val_ssa_equiv.create (1024);
5f718c29 393
394 /* We're going to do a dominator walk, so ensure that we have
395 dominance information. */
396 calculate_dominance_info (CDI_DOMINATORS);
397
5f718c29 398 /* Recursively walk the dominator tree undoing unprofitable
399 constant/copy propagations. */
54c91640 400 uncprop_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
5f718c29 401
54c91640 402 /* we just need to empty elements out of the hash table, and cleanup the
403 AUX field on the edges. */
d9dd21a8 404 val_ssa_equiv.dispose ();
5f718c29 405 FOR_EACH_BB (bb)
406 {
407 edge e;
408 edge_iterator ei;
409
410 FOR_EACH_EDGE (e, ei, bb->succs)
411 {
412 if (e->aux)
413 {
414 free (e->aux);
415 e->aux = NULL;
416 }
417 }
418 }
2a1990e9 419 return 0;
5f718c29 420}
421
422
423/* We have finished processing the dominator children of BB, perform
424 any finalization actions in preparation for leaving this node in
425 the dominator tree. */
426
54c91640 427void
428uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
5f718c29 429{
5f718c29 430 /* Pop the topmost value off the equiv stack. */
54c91640 431 tree value = equiv_stack_.pop ();
5f718c29 432
433 /* If that value was non-null, then pop the topmost equivalency off
434 its equivalency stack. */
435 if (value != NULL)
436 remove_equivalence (value);
437}
438
439/* Unpropagate values from PHI nodes in successor blocks of BB. */
440
441static void
6bf320fb 442uncprop_into_successor_phis (basic_block bb)
5f718c29 443{
444 edge e;
445 edge_iterator ei;
446
447 /* For each successor edge, first temporarily record any equivalence
448 on that edge. Then unpropagate values in any PHI nodes at the
449 destination of the edge. Then remove the temporary equivalence. */
450 FOR_EACH_EDGE (e, ei, bb->succs)
451 {
75a70cf9 452 gimple_seq phis = phi_nodes (e->dest);
453 gimple_stmt_iterator gsi;
5f718c29 454
455 /* If there are no PHI nodes in this destination, then there is
456 no sense in recording any equivalences. */
be2517f5 457 if (gimple_seq_empty_p (phis))
5f718c29 458 continue;
459
460 /* Record any equivalency associated with E. */
461 if (e->aux)
462 {
945865c5 463 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
5f718c29 464 record_equiv (equiv->rhs, equiv->lhs);
465 }
466
467 /* Walk over the PHI nodes, unpropagating values. */
75a70cf9 468 for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi))
5f718c29 469 {
75a70cf9 470 gimple phi = gsi_stmt (gsi);
5f718c29 471 tree arg = PHI_ARG_DEF (phi, e->dest_idx);
ec11736b 472 tree res = PHI_RESULT (phi);
d9dd21a8 473 equiv_hash_elt an_equiv_elt;
474 equiv_hash_elt **slot;
5f718c29 475
f82f0ea5 476 /* If the argument is not an invariant and can be potentially
477 coalesced with the result, then there's no point in
478 un-propagating the argument. */
5f718c29 479 if (!is_gimple_min_invariant (arg)
f82f0ea5 480 && gimple_can_coalesce_p (arg, res))
5f718c29 481 continue;
482
483 /* Lookup this argument's value in the hash table. */
d9dd21a8 484 an_equiv_elt.value = arg;
485 an_equiv_elt.equivalences.create (0);
486 slot = val_ssa_equiv.find_slot (&an_equiv_elt, NO_INSERT);
5f718c29 487
488 if (slot)
489 {
d9dd21a8 490 struct equiv_hash_elt *elt = *slot;
5f718c29 491 int j;
492
493 /* Walk every equivalence with the same value. If we find
f82f0ea5 494 one that can potentially coalesce with the PHI rsult,
5f718c29 495 then replace the value in the argument with its equivalent
25f6297d 496 SSA_NAME. Use the most recent equivalence as hopefully
5f718c29 497 that results in shortest lifetimes. */
f1f41a6c 498 for (j = elt->equivalences.length () - 1; j >= 0; j--)
5f718c29 499 {
f1f41a6c 500 tree equiv = elt->equivalences[j];
5f718c29 501
f82f0ea5 502 if (gimple_can_coalesce_p (equiv, res))
5f718c29 503 {
504 SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
505 break;
506 }
507 }
508 }
509 }
510
511 /* If we had an equivalence associated with this edge, remove it. */
512 if (e->aux)
513 {
945865c5 514 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
5f718c29 515 remove_equivalence (equiv->rhs);
516 }
517 }
518}
519
520/* Ignoring loop backedges, if BB has precisely one incoming edge then
521 return that edge. Otherwise return NULL. */
522static edge
523single_incoming_edge_ignoring_loop_edges (basic_block bb)
524{
525 edge retval = NULL;
526 edge e;
527 edge_iterator ei;
528
529 FOR_EACH_EDGE (e, ei, bb->preds)
530 {
531 /* A loop back edge can be identified by the destination of
532 the edge dominating the source of the edge. */
533 if (dominated_by_p (CDI_DOMINATORS, e->src, e->dest))
534 continue;
535
536 /* If we have already seen a non-loop edge, then we must have
537 multiple incoming non-loop edges and thus we return NULL. */
538 if (retval)
539 return NULL;
540
541 /* This is the first non-loop incoming edge we have found. Record
542 it. */
543 retval = e;
544 }
545
546 return retval;
547}
548
54c91640 549void
550uncprop_dom_walker::before_dom_children (basic_block bb)
5f718c29 551{
552 basic_block parent;
553 edge e;
554 bool recorded = false;
555
556 /* If this block is dominated by a single incoming edge and that edge
557 has an equivalency, then record the equivalency and push the
558 VALUE onto EQUIV_STACK. Else push a NULL entry on EQUIV_STACK. */
559 parent = get_immediate_dominator (CDI_DOMINATORS, bb);
560 if (parent)
561 {
562 e = single_incoming_edge_ignoring_loop_edges (bb);
563
564 if (e && e->src == parent && e->aux)
565 {
945865c5 566 struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
5f718c29 567
568 record_equiv (equiv->rhs, equiv->lhs);
54c91640 569 equiv_stack_.safe_push (equiv->rhs);
5f718c29 570 recorded = true;
571 }
572 }
573
574 if (!recorded)
54c91640 575 equiv_stack_.safe_push (NULL_TREE);
6bf320fb 576
577 uncprop_into_successor_phis (bb);
5f718c29 578}
579
580static bool
581gate_uncprop (void)
582{
583 return flag_tree_dom != 0;
584}
585
cbe8bda8 586namespace {
587
588const pass_data pass_data_uncprop =
5f718c29 589{
cbe8bda8 590 GIMPLE_PASS, /* type */
591 "uncprop", /* name */
592 OPTGROUP_NONE, /* optinfo_flags */
593 true, /* has_gate */
594 true, /* has_execute */
595 TV_TREE_SSA_UNCPROP, /* tv_id */
596 ( PROP_cfg | PROP_ssa ), /* properties_required */
597 0, /* properties_provided */
598 0, /* properties_destroyed */
599 0, /* todo_flags_start */
600 TODO_verify_ssa, /* todo_flags_finish */
5f718c29 601};
cbe8bda8 602
603class pass_uncprop : public gimple_opt_pass
604{
605public:
9af5ce0c 606 pass_uncprop (gcc::context *ctxt)
607 : gimple_opt_pass (pass_data_uncprop, ctxt)
cbe8bda8 608 {}
609
610 /* opt_pass methods: */
611 opt_pass * clone () { return new pass_uncprop (ctxt_); }
612 bool gate () { return gate_uncprop (); }
613 unsigned int execute () { return tree_ssa_uncprop (); }
614
615}; // class pass_uncprop
616
617} // anon namespace
618
619gimple_opt_pass *
620make_pass_uncprop (gcc::context *ctxt)
621{
622 return new pass_uncprop (ctxt);
623}