Branch data Line data Source code
1 : : /* Routines for discovering and unpropagating edge equivalences.
2 : : Copyright (C) 2005-2025 Free Software Foundation, Inc.
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 3, 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 COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "backend.h"
24 : : #include "tree.h"
25 : : #include "gimple.h"
26 : : #include "tree-pass.h"
27 : : #include "ssa.h"
28 : : #include "fold-const.h"
29 : : #include "cfganal.h"
30 : : #include "gimple-iterator.h"
31 : : #include "tree-cfg.h"
32 : : #include "domwalk.h"
33 : : #include "tree-hash-traits.h"
34 : : #include "tree-ssa-live.h"
35 : : #include "tree-ssa-coalesce.h"
36 : :
37 : : /* The basic structure describing an equivalency created by traversing
38 : : an edge. Traversing the edge effectively means that we can assume
39 : : that we've seen an assignment LHS = RHS. */
40 : : struct edge_equivalency
41 : : {
42 : : tree rhs;
43 : : tree lhs;
44 : : };
45 : :
46 : : /* This routine finds and records edge equivalences for every edge
47 : : in the CFG.
48 : :
49 : : When complete, each edge that creates an equivalency will have an
50 : : EDGE_EQUIVALENCY structure hanging off the edge's AUX field.
51 : : The caller is responsible for freeing the AUX fields. */
52 : :
53 : : static void
54 : 1008683 : associate_equivalences_with_edges (void)
55 : : {
56 : 1008683 : basic_block bb;
57 : :
58 : : /* Walk over each block. If the block ends with a control statement,
59 : : then it might create a useful equivalence. */
60 : 14205513 : FOR_EACH_BB_FN (bb, cfun)
61 : : {
62 : 13196830 : gimple_stmt_iterator gsi = gsi_last_bb (bb);
63 : 13196830 : gimple *stmt;
64 : :
65 : : /* If the block does not end with a COND_EXPR or SWITCH_EXPR
66 : : then there is nothing to do. */
67 : 13196830 : if (gsi_end_p (gsi))
68 : 13196830 : continue;
69 : :
70 : 9257316 : stmt = gsi_stmt (gsi);
71 : :
72 : 9257316 : if (!stmt)
73 : : continue;
74 : :
75 : : /* A COND_EXPR may create an equivalency in a variety of different
76 : : ways. */
77 : 9257316 : if (gimple_code (stmt) == GIMPLE_COND)
78 : : {
79 : 4082471 : edge true_edge;
80 : 4082471 : edge false_edge;
81 : 4082471 : struct edge_equivalency *equivalency;
82 : 4082471 : enum tree_code code = gimple_cond_code (stmt);
83 : :
84 : 4082471 : extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
85 : :
86 : : /* Equality tests may create one or two equivalences. */
87 : 4082471 : if (code == EQ_EXPR || code == NE_EXPR)
88 : : {
89 : 3326690 : tree op0 = gimple_cond_lhs (stmt);
90 : 3326690 : tree op1 = gimple_cond_rhs (stmt);
91 : :
92 : : /* Special case comparing booleans against a constant as we
93 : : know the value of OP0 on both arms of the branch. i.e., we
94 : : can record an equivalence for OP0 rather than COND. */
95 : 3326690 : if (TREE_CODE (op0) == SSA_NAME
96 : 3252919 : && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
97 : 3252795 : && ssa_name_has_boolean_range (op0)
98 : 450250 : && is_gimple_min_invariant (op1)
99 : 3761846 : && (integer_zerop (op1) || integer_onep (op1)))
100 : : {
101 : 435156 : tree true_val = constant_boolean_node (true, TREE_TYPE (op0));
102 : 435156 : tree false_val = constant_boolean_node (false,
103 : 435156 : TREE_TYPE (op0));
104 : 435156 : if (code == EQ_EXPR)
105 : : {
106 : 13499 : equivalency = XNEW (struct edge_equivalency);
107 : 13499 : equivalency->lhs = op0;
108 : 13499 : equivalency->rhs = (integer_zerop (op1)
109 : 13499 : ? false_val
110 : : : true_val);
111 : 13499 : true_edge->aux = equivalency;
112 : :
113 : 13499 : equivalency = XNEW (struct edge_equivalency);
114 : 13499 : equivalency->lhs = op0;
115 : 13499 : equivalency->rhs = (integer_zerop (op1)
116 : 13499 : ? true_val
117 : : : false_val);
118 : 13499 : false_edge->aux = equivalency;
119 : : }
120 : : else
121 : : {
122 : 421657 : equivalency = XNEW (struct edge_equivalency);
123 : 421657 : equivalency->lhs = op0;
124 : 421657 : equivalency->rhs = (integer_zerop (op1)
125 : 421657 : ? true_val
126 : : : false_val);
127 : 421657 : true_edge->aux = equivalency;
128 : :
129 : 421657 : equivalency = XNEW (struct edge_equivalency);
130 : 421657 : equivalency->lhs = op0;
131 : 421657 : equivalency->rhs = (integer_zerop (op1)
132 : 421657 : ? false_val
133 : : : true_val);
134 : 421657 : false_edge->aux = equivalency;
135 : : }
136 : : }
137 : :
138 : 2891534 : else if (TREE_CODE (op0) == SSA_NAME
139 : 2817763 : && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op0)
140 : 5709173 : && (is_gimple_min_invariant (op1)
141 : 635407 : || (TREE_CODE (op1) == SSA_NAME
142 : 635407 : && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (op1))))
143 : : {
144 : : /* For IEEE, -0.0 == 0.0, so we don't necessarily know
145 : : the sign of a variable compared against zero. If
146 : : we're honoring signed zeros, then we cannot record
147 : : this value unless we know that the value is nonzero. */
148 : 2817638 : if (HONOR_SIGNED_ZEROS (op0)
149 : 2817638 : && (TREE_CODE (op1) != REAL_CST
150 : 85932 : || real_equal (&dconst0, &TREE_REAL_CST (op1))))
151 : 50531 : continue;
152 : :
153 : 2767107 : equivalency = XNEW (struct edge_equivalency);
154 : 2767107 : equivalency->lhs = op0;
155 : 2767107 : equivalency->rhs = op1;
156 : 2767107 : if (code == EQ_EXPR)
157 : 1230703 : true_edge->aux = equivalency;
158 : : else
159 : 1536404 : false_edge->aux = equivalency;
160 : :
161 : : }
162 : : }
163 : :
164 : : /* ??? TRUTH_NOT_EXPR can create an equivalence too. */
165 : : }
166 : :
167 : : /* For a SWITCH_EXPR, a case label which represents a single
168 : : value and which is the only case label which reaches the
169 : : target block creates an equivalence. */
170 : 5174845 : else if (gimple_code (stmt) == GIMPLE_SWITCH)
171 : : {
172 : 6579 : gswitch *switch_stmt = as_a <gswitch *> (stmt);
173 : 6579 : tree cond = gimple_switch_index (switch_stmt);
174 : :
175 : 6579 : if (TREE_CODE (cond) == SSA_NAME
176 : 6579 : && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (cond))
177 : : {
178 : 6579 : int i, n_labels = gimple_switch_num_labels (switch_stmt);
179 : 6579 : tree *info = XCNEWVEC (tree, last_basic_block_for_fn (cfun));
180 : :
181 : : /* Walk over the case label vector. Record blocks
182 : : which are reached by a single case label which represents
183 : : a single value. */
184 : 91545 : for (i = 0; i < n_labels; i++)
185 : : {
186 : 84966 : tree label = gimple_switch_label (switch_stmt, i);
187 : 84966 : basic_block bb = label_to_block (cfun, CASE_LABEL (label));
188 : :
189 : 84966 : if (CASE_HIGH (label)
190 : 81066 : || !CASE_LOW (label)
191 : 159453 : || info[bb->index])
192 : 17868 : info[bb->index] = error_mark_node;
193 : : else
194 : 67098 : info[bb->index] = label;
195 : : }
196 : :
197 : : /* Now walk over the blocks to determine which ones were
198 : : marked as being reached by a useful case label. */
199 : 1123827 : for (i = 0; i < n_basic_blocks_for_fn (cfun); i++)
200 : : {
201 : 1117248 : tree node = info[i];
202 : :
203 : 1117248 : if (node != NULL
204 : 76763 : && node != error_mark_node)
205 : : {
206 : 61709 : tree x = fold_convert (TREE_TYPE (cond), CASE_LOW (node));
207 : 61709 : struct edge_equivalency *equivalency;
208 : :
209 : : /* Record an equivalency on the edge from BB to basic
210 : : block I. */
211 : 61709 : equivalency = XNEW (struct edge_equivalency);
212 : 61709 : equivalency->rhs = x;
213 : 61709 : equivalency->lhs = cond;
214 : 61709 : find_edge (bb, BASIC_BLOCK_FOR_FN (cfun, i))->aux =
215 : : equivalency;
216 : : }
217 : : }
218 : 6579 : free (info);
219 : : }
220 : : }
221 : :
222 : : }
223 : 1008683 : }
224 : :
225 : :
226 : : /* Translating out of SSA sometimes requires inserting copies and
227 : : constant initializations on edges to eliminate PHI nodes.
228 : :
229 : : In some cases those copies and constant initializations are
230 : : redundant because the target already has the value on the
231 : : RHS of the assignment.
232 : :
233 : : We previously tried to catch these cases after translating
234 : : out of SSA form. However, that code often missed cases. Worse
235 : : yet, the cases it missed were also often missed by the RTL
236 : : optimizers. Thus the resulting code had redundant instructions.
237 : :
238 : : This pass attempts to detect these situations before translating
239 : : out of SSA form.
240 : :
241 : : The key concept that this pass is built upon is that these
242 : : redundant copies and constant initializations often occur
243 : : due to constant/copy propagating equivalences resulting from
244 : : COND_EXPRs and SWITCH_EXPRs.
245 : :
246 : : We want to do those propagations as they can sometimes allow
247 : : the SSA optimizers to do a better job. However, in the cases
248 : : where such propagations do not result in further optimization,
249 : : we would like to "undo" the propagation to avoid the redundant
250 : : copies and constant initializations.
251 : :
252 : : This pass works by first associating equivalences with edges in
253 : : the CFG. For example, the edge leading from a SWITCH_EXPR to
254 : : its associated CASE_LABEL will have an equivalency between
255 : : SWITCH_COND and the value in the case label.
256 : :
257 : : Once we have found the edge equivalences, we proceed to walk
258 : : the CFG in dominator order. As we traverse edges we record
259 : : equivalences associated with those edges we traverse.
260 : :
261 : : When we encounter a PHI node, we walk its arguments to see if we
262 : : have an equivalence for the PHI argument. If so, then we replace
263 : : the argument.
264 : :
265 : : Equivalences are looked up based on their value (think of it as
266 : : the RHS of an assignment). A value may be an SSA_NAME or an
267 : : invariant. We may have several SSA_NAMEs with the same value,
268 : : so with each value we have a list of SSA_NAMEs that have the
269 : : same value. */
270 : :
271 : : typedef hash_map<tree_operand_hash, auto_vec<tree> > val_ssa_equiv_t;
272 : :
273 : : /* Global hash table implementing a mapping from invariant values
274 : : to a list of SSA_NAMEs which have the same value. We might be
275 : : able to reuse tree-vn for this code. */
276 : : val_ssa_equiv_t *val_ssa_equiv;
277 : :
278 : : static void uncprop_into_successor_phis (basic_block);
279 : :
280 : : /* Remove the most recently recorded equivalency for VALUE. */
281 : :
282 : : static void
283 : 3698548 : remove_equivalence (tree value)
284 : : {
285 : 3698548 : val_ssa_equiv->get (value)->pop ();
286 : 3698548 : }
287 : :
288 : : /* Record EQUIVALENCE = VALUE into our hash table. */
289 : :
290 : : static void
291 : 3698548 : record_equiv (tree value, tree equivalence)
292 : : {
293 : 3698548 : val_ssa_equiv->get_or_insert (value).safe_push (equivalence);
294 : 3698548 : }
295 : :
296 : : class uncprop_dom_walker : public dom_walker
297 : : {
298 : : public:
299 : 1008683 : uncprop_dom_walker (cdi_direction direction) : dom_walker (direction) {}
300 : :
301 : : edge before_dom_children (basic_block) final override;
302 : : void after_dom_children (basic_block) final override;
303 : :
304 : : private:
305 : :
306 : : /* As we enter each block we record the value for any edge equivalency
307 : : leading to this block. If no such edge equivalency exists, then we
308 : : record NULL. These equivalences are live until we leave the dominator
309 : : subtree rooted at the block where we record the equivalency. */
310 : : auto_vec<tree, 2> m_equiv_stack;
311 : : };
312 : :
313 : : /* We have finished processing the dominator children of BB, perform
314 : : any finalization actions in preparation for leaving this node in
315 : : the dominator tree. */
316 : :
317 : : void
318 : 14205513 : uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
319 : : {
320 : : /* Pop the topmost value off the equiv stack. */
321 : 14205513 : tree value = m_equiv_stack.pop ();
322 : :
323 : : /* If that value was non-null, then pop the topmost equivalency off
324 : : its equivalency stack. */
325 : 14205513 : if (value != NULL)
326 : 3697354 : remove_equivalence (value);
327 : 14205513 : }
328 : :
329 : : /* Unpropagate values from PHI nodes in successor blocks of BB. */
330 : :
331 : : static void
332 : 14205513 : uncprop_into_successor_phis (basic_block bb)
333 : : {
334 : 14205513 : edge e;
335 : 14205513 : edge_iterator ei;
336 : :
337 : : /* For each successor edge, first temporarily record any equivalence
338 : : on that edge. Then unpropagate values in any PHI nodes at the
339 : : destination of the edge. Then remove the temporary equivalence. */
340 : 32668114 : FOR_EACH_EDGE (e, ei, bb->succs)
341 : : {
342 : 18462601 : gimple_seq phis = phi_nodes (e->dest);
343 : 18462601 : gimple_stmt_iterator gsi;
344 : :
345 : : /* If there are no PHI nodes in this destination, then there is
346 : : no sense in recording any equivalences. */
347 : 18462601 : if (gimple_seq_empty_p (phis))
348 : 12279775 : continue;
349 : :
350 : : /* Record any equivalency associated with E. */
351 : 6182826 : if (e->aux)
352 : : {
353 : 1194 : struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
354 : 1194 : record_equiv (equiv->rhs, equiv->lhs);
355 : : }
356 : :
357 : : /* Walk over the PHI nodes, unpropagating values. */
358 : 17048444 : for (gsi = gsi_start (phis) ; !gsi_end_p (gsi); gsi_next (&gsi))
359 : : {
360 : 10865618 : gimple *phi = gsi_stmt (gsi);
361 : 10865618 : tree arg = PHI_ARG_DEF (phi, e->dest_idx);
362 : 10865618 : tree res = PHI_RESULT (phi);
363 : :
364 : : /* If the argument is not an invariant and can be potentially
365 : : coalesced with the result, then there's no point in
366 : : un-propagating the argument. */
367 : 10865618 : if (!is_gimple_min_invariant (arg)
368 : 10865618 : && gimple_can_coalesce_p (arg, res))
369 : 9457776 : continue;
370 : :
371 : : /* Lookup this argument's value in the hash table. */
372 : 1407842 : vec<tree> *equivalences = val_ssa_equiv->get (arg);
373 : 1407842 : if (equivalences)
374 : : {
375 : : /* Walk every equivalence with the same value. If we find
376 : : one that can potentially coalesce with the PHI rsult,
377 : : then replace the value in the argument with its equivalent
378 : : SSA_NAME. Use the most recent equivalence as hopefully
379 : : that results in shortest lifetimes. */
380 : 1821001 : for (int j = equivalences->length () - 1; j >= 0; j--)
381 : : {
382 : 638720 : tree equiv = (*equivalences)[j];
383 : :
384 : 638720 : if (gimple_can_coalesce_p (equiv, res))
385 : : {
386 : 144417 : SET_PHI_ARG_DEF (phi, e->dest_idx, equiv);
387 : 144417 : break;
388 : : }
389 : : }
390 : : }
391 : : }
392 : :
393 : : /* If we had an equivalence associated with this edge, remove it. */
394 : 6182826 : if (e->aux)
395 : : {
396 : 1194 : struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
397 : 1194 : remove_equivalence (equiv->rhs);
398 : : }
399 : : }
400 : 14205513 : }
401 : :
402 : : edge
403 : 14205513 : uncprop_dom_walker::before_dom_children (basic_block bb)
404 : : {
405 : 14205513 : basic_block parent;
406 : 14205513 : bool recorded = false;
407 : :
408 : : /* If this block is dominated by a single incoming edge and that edge
409 : : has an equivalency, then record the equivalency and push the
410 : : VALUE onto EQUIV_STACK. Else push a NULL entry on EQUIV_STACK. */
411 : 14205513 : parent = get_immediate_dominator (CDI_DOMINATORS, bb);
412 : 14205513 : if (parent)
413 : : {
414 : 13196830 : edge e = single_pred_edge_ignoring_loop_edges (bb, false);
415 : :
416 : 13196830 : if (e && e->src == parent && e->aux)
417 : : {
418 : 3697354 : struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
419 : :
420 : 3697354 : record_equiv (equiv->rhs, equiv->lhs);
421 : 3697354 : m_equiv_stack.safe_push (equiv->rhs);
422 : 3697354 : recorded = true;
423 : : }
424 : : }
425 : :
426 : 3697354 : if (!recorded)
427 : 10508159 : m_equiv_stack.safe_push (NULL_TREE);
428 : :
429 : 14205513 : uncprop_into_successor_phis (bb);
430 : 14205513 : return NULL;
431 : : }
432 : :
433 : : namespace {
434 : :
435 : : const pass_data pass_data_uncprop =
436 : : {
437 : : GIMPLE_PASS, /* type */
438 : : "uncprop", /* name */
439 : : OPTGROUP_NONE, /* optinfo_flags */
440 : : TV_TREE_SSA_UNCPROP, /* tv_id */
441 : : ( PROP_cfg | PROP_ssa ), /* properties_required */
442 : : 0, /* properties_provided */
443 : : 0, /* properties_destroyed */
444 : : 0, /* todo_flags_start */
445 : : 0, /* todo_flags_finish */
446 : : };
447 : :
448 : : class pass_uncprop : public gimple_opt_pass
449 : : {
450 : : public:
451 : 566314 : pass_uncprop (gcc::context *ctxt)
452 : 1132628 : : gimple_opt_pass (pass_data_uncprop, ctxt)
453 : : {}
454 : :
455 : : /* opt_pass methods: */
456 : 283157 : opt_pass * clone () final override { return new pass_uncprop (m_ctxt); }
457 : 1009010 : bool gate (function *) final override { return flag_tree_dom != 0; }
458 : : unsigned int execute (function *) final override;
459 : :
460 : : }; // class pass_uncprop
461 : :
462 : : unsigned int
463 : 1008683 : pass_uncprop::execute (function *fun)
464 : : {
465 : 1008683 : basic_block bb;
466 : :
467 : 1008683 : associate_equivalences_with_edges ();
468 : :
469 : : /* Create our global data structures. */
470 : 1008683 : val_ssa_equiv = new val_ssa_equiv_t (1024);
471 : :
472 : : /* We're going to do a dominator walk, so ensure that we have
473 : : dominance information. */
474 : 1008683 : calculate_dominance_info (CDI_DOMINATORS);
475 : :
476 : : /* Recursively walk the dominator tree undoing unprofitable
477 : : constant/copy propagations. */
478 : 1008683 : uncprop_dom_walker (CDI_DOMINATORS).walk (fun->cfg->x_entry_block_ptr);
479 : :
480 : : /* we just need to empty elements out of the hash table, and cleanup the
481 : : AUX field on the edges. */
482 : 2017366 : delete val_ssa_equiv;
483 : 1008683 : val_ssa_equiv = NULL;
484 : 14205513 : FOR_EACH_BB_FN (bb, fun)
485 : : {
486 : 13196830 : edge e;
487 : 13196830 : edge_iterator ei;
488 : :
489 : 30650748 : FOR_EACH_EDGE (e, ei, bb->succs)
490 : : {
491 : 17453918 : if (e->aux)
492 : : {
493 : 3699128 : free (e->aux);
494 : 3699128 : e->aux = NULL;
495 : : }
496 : : }
497 : : }
498 : 1008683 : return 0;
499 : : }
500 : :
501 : : } // anon namespace
502 : :
503 : : gimple_opt_pass *
504 : 283157 : make_pass_uncprop (gcc::context *ctxt)
505 : : {
506 : 283157 : return new pass_uncprop (ctxt);
507 : : }
|