fix __builtin___clear_cache overrider fallout
[official-gcc.git] / gcc / tree-ssa-threadbackward.c
blob30f692672d965ef251f9e43a29e618a454a2d3d7
1 /* SSA Jump Threading
2 Copyright (C) 2005-2020 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
20 #include "config.h"
21 #include "system.h"
22 #include "coretypes.h"
23 #include "backend.h"
24 #include "predict.h"
25 #include "tree.h"
26 #include "gimple.h"
27 #include "fold-const.h"
28 #include "cfgloop.h"
29 #include "gimple-iterator.h"
30 #include "tree-cfg.h"
31 #include "tree-ssa-threadupdate.h"
32 #include "tree-ssa-loop.h"
33 #include "cfganal.h"
34 #include "tree-pass.h"
35 #include "gimple-ssa.h"
36 #include "tree-phinodes.h"
37 #include "tree-inline.h"
38 #include "tree-vectorizer.h"
40 class thread_jumps
42 public:
43 void find_jump_threads_backwards (basic_block bb, bool speed_p);
44 private:
45 edge profitable_jump_thread_path (basic_block bbi, tree name, tree arg,
46 bool *creates_irreducible_loop);
47 void convert_and_register_current_path (edge taken_edge);
48 void register_jump_thread_path_if_profitable (tree name, tree arg,
49 basic_block def_bb);
50 void handle_assignment (gimple *stmt, tree name, basic_block def_bb);
51 void handle_phi (gphi *phi, tree name, basic_block def_bb);
52 void fsm_find_control_statement_thread_paths (tree name);
53 bool check_subpath_and_update_thread_path (basic_block last_bb,
54 basic_block new_bb,
55 int *next_path_length);
57 /* Maximum number of BBs we are allowed to thread. */
58 int m_max_threaded_paths;
59 /* Hash to keep track of seen bbs. */
60 hash_set<basic_block> m_visited_bbs;
61 /* Current path we're analyzing. */
62 auto_vec<basic_block> m_path;
63 /* Tracks if we have recursed through a loop PHI node. */
64 bool m_seen_loop_phi;
65 /* Indicate that we could increase code size to improve the
66 code path. */
67 bool m_speed_p;
70 /* Simple helper to get the last statement from BB, which is assumed
71 to be a control statement. Return NULL if the last statement is
72 not a control statement. */
74 static gimple *
75 get_gimple_control_stmt (basic_block bb)
77 gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
79 if (gsi_end_p (gsi))
80 return NULL;
82 gimple *stmt = gsi_stmt (gsi);
83 enum gimple_code code = gimple_code (stmt);
84 if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
85 return stmt;
86 return NULL;
89 /* Return true if the CFG contains at least one path from START_BB to
90 END_BB. When a path is found, record in PATH the blocks from
91 END_BB to START_BB. LOCAL_VISITED_BBS is used to make sure we
92 don't fall into an infinite loop. Bound the recursion to basic
93 blocks belonging to LOOP. */
95 static bool
96 fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
97 vec<basic_block> &path,
98 hash_set<basic_block> &local_visited_bbs,
99 loop_p loop)
101 if (loop != start_bb->loop_father)
102 return false;
104 if (start_bb == end_bb)
106 path.safe_push (start_bb);
107 return true;
110 if (!local_visited_bbs.add (start_bb))
112 edge e;
113 edge_iterator ei;
114 FOR_EACH_EDGE (e, ei, start_bb->succs)
115 if (fsm_find_thread_path (e->dest, end_bb, path, local_visited_bbs,
116 loop))
118 path.safe_push (start_bb);
119 return true;
123 return false;
126 /* Examine jump threading path PATH to which we want to add BBI.
128 If the resulting path is profitable to thread, then return the
129 final taken edge from the path, NULL otherwise.
131 NAME is the SSA_NAME of the variable we found to have a constant
132 value on PATH. ARG is the constant value of NAME on that path.
134 BBI will be appended to PATH when we have a profitable jump
135 threading path. Callers are responsible for removing BBI from PATH
136 in that case. */
138 edge
139 thread_jumps::profitable_jump_thread_path (basic_block bbi, tree name,
140 tree arg,
141 bool *creates_irreducible_loop)
143 /* Note BBI is not in the path yet, hence the +1 in the test below
144 to make sure BBI is accounted for in the path length test. */
146 /* We can get a length of 0 here when the statement that
147 makes a conditional generate a compile-time constant
148 result is in the same block as the conditional.
150 That's not really a jump threading opportunity, but instead is
151 simple cprop & simplification. We could handle it here if we
152 wanted by wiring up all the incoming edges. If we run this
153 early in IPA, that might be worth doing. For now we just
154 reject that case. */
155 if (m_path.is_empty ())
156 return NULL;
158 if (m_path.length () + 1
159 > (unsigned) param_max_fsm_thread_length)
161 if (dump_file && (dump_flags & TDF_DETAILS))
162 fprintf (dump_file, "FSM jump-thread path not considered: "
163 "the number of basic blocks on the path "
164 "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n");
165 return NULL;
168 if (m_max_threaded_paths <= 0)
170 if (dump_file && (dump_flags & TDF_DETAILS))
171 fprintf (dump_file, "FSM jump-thread path not considered: "
172 "the number of previously recorded FSM paths to "
173 "thread exceeds PARAM_MAX_FSM_THREAD_PATHS.\n");
174 return NULL;
177 /* Add BBI to the path.
178 From this point onward, if we decide we the path is not profitable
179 to thread, we must remove BBI from the path. */
180 m_path.safe_push (bbi);
182 int n_insns = 0;
183 gimple_stmt_iterator gsi;
184 loop_p loop = m_path[0]->loop_father;
185 bool path_crosses_loops = false;
186 bool threaded_through_latch = false;
187 bool multiway_branch_in_path = false;
188 bool threaded_multiway_branch = false;
189 bool contains_hot_bb = false;
191 if (dump_file && (dump_flags & TDF_DETAILS))
192 fprintf (dump_file, "Checking profitability of path (backwards): ");
194 /* Count the number of instructions on the path: as these instructions
195 will have to be duplicated, we will not record the path if there
196 are too many instructions on the path. Also check that all the
197 blocks in the path belong to a single loop. */
198 for (unsigned j = 0; j < m_path.length (); j++)
200 basic_block bb = m_path[j];
202 if (dump_file && (dump_flags & TDF_DETAILS))
203 fprintf (dump_file, " bb:%i", bb->index);
204 /* Remember, blocks in the path are stored in opposite order
205 in the PATH array. The last entry in the array represents
206 the block with an outgoing edge that we will redirect to the
207 jump threading path. Thus we don't care about that block's
208 loop father, nor how many statements are in that block because
209 it will not be copied or whether or not it ends in a multiway
210 branch. */
211 if (j < m_path.length () - 1)
213 int orig_n_insns = n_insns;
214 if (bb->loop_father != loop)
216 path_crosses_loops = true;
217 break;
220 /* PHIs in the path will create degenerate PHIS in the
221 copied path which will then get propagated away, so
222 looking at just the duplicate path the PHIs would
223 seem unimportant.
225 But those PHIs, because they're assignments to objects
226 typically with lives that exist outside the thread path,
227 will tend to generate PHIs (or at least new PHI arguments)
228 at points where we leave the thread path and rejoin
229 the original blocks. So we do want to account for them.
231 We ignore virtual PHIs. We also ignore cases where BB
232 has a single incoming edge. That's the most common
233 degenerate PHI we'll see here. Finally we ignore PHIs
234 that are associated with the value we're tracking as
235 that object likely dies. */
236 if (EDGE_COUNT (bb->succs) > 1 && EDGE_COUNT (bb->preds) > 1)
238 for (gphi_iterator gsip = gsi_start_phis (bb);
239 !gsi_end_p (gsip);
240 gsi_next (&gsip))
242 gphi *phi = gsip.phi ();
243 tree dst = gimple_phi_result (phi);
245 /* Note that if both NAME and DST are anonymous
246 SSA_NAMEs, then we do not have enough information
247 to consider them associated. */
248 if (dst != name
249 && (SSA_NAME_VAR (dst) != SSA_NAME_VAR (name)
250 || !SSA_NAME_VAR (dst))
251 && !virtual_operand_p (dst))
252 ++n_insns;
256 if (!contains_hot_bb && m_speed_p)
257 contains_hot_bb |= optimize_bb_for_speed_p (bb);
258 for (gsi = gsi_after_labels (bb);
259 !gsi_end_p (gsi);
260 gsi_next_nondebug (&gsi))
262 /* Do not allow OpenACC loop markers and __builtin_constant_p on
263 threading paths. The latter is disallowed, because an
264 expression might be constant on two threading paths, and
265 become non-constant (i.e.: phi) when they merge. */
266 gimple *stmt = gsi_stmt (gsi);
267 if (gimple_call_internal_p (stmt, IFN_UNIQUE)
268 || gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
270 m_path.pop ();
271 return NULL;
273 /* Do not count empty statements and labels. */
274 if (gimple_code (stmt) != GIMPLE_NOP
275 && !(gimple_code (stmt) == GIMPLE_ASSIGN
276 && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
277 && !is_gimple_debug (stmt))
278 n_insns += estimate_num_insns (stmt, &eni_size_weights);
280 if (dump_file && (dump_flags & TDF_DETAILS))
281 fprintf (dump_file, " (%i insns)", n_insns-orig_n_insns);
283 /* We do not look at the block with the threaded branch
284 in this loop. So if any block with a last statement that
285 is a GIMPLE_SWITCH or GIMPLE_GOTO is seen, then we have a
286 multiway branch on our path.
288 The block in PATH[0] is special, it's the block were we're
289 going to be able to eliminate its branch. */
290 gimple *last = last_stmt (bb);
291 if (last && (gimple_code (last) == GIMPLE_SWITCH
292 || gimple_code (last) == GIMPLE_GOTO))
294 if (j == 0)
295 threaded_multiway_branch = true;
296 else
297 multiway_branch_in_path = true;
301 /* Note if we thread through the latch, we will want to include
302 the last entry in the array when determining if we thread
303 through the loop latch. */
304 if (loop->latch == bb)
305 threaded_through_latch = true;
308 gimple *stmt = get_gimple_control_stmt (m_path[0]);
309 gcc_assert (stmt);
311 /* We are going to remove the control statement at the end of the
312 last block in the threading path. So don't count it against our
313 statement count. */
315 int stmt_insns = estimate_num_insns (stmt, &eni_size_weights);
316 n_insns-= stmt_insns;
318 if (dump_file && (dump_flags & TDF_DETAILS))
319 fprintf (dump_file, "\n Control statement insns: %i\n"
320 " Overall: %i insns\n",
321 stmt_insns, n_insns);
323 /* We have found a constant value for ARG. For GIMPLE_SWITCH
324 and GIMPLE_GOTO, we use it as-is. However, for a GIMPLE_COND
325 we need to substitute, fold and simplify so we can determine
326 the edge taken out of the last block. */
327 if (gimple_code (stmt) == GIMPLE_COND)
329 enum tree_code cond_code = gimple_cond_code (stmt);
331 /* We know the underyling format of the condition. */
332 arg = fold_binary (cond_code, boolean_type_node,
333 arg, gimple_cond_rhs (stmt));
336 /* If this path threaded through the loop latch back into the
337 same loop and the destination does not dominate the loop
338 latch, then this thread would create an irreducible loop.
340 We have to know the outgoing edge to figure this out. */
341 edge taken_edge = find_taken_edge (m_path[0], arg);
343 /* There are cases where we may not be able to extract the
344 taken edge. For example, a computed goto to an absolute
345 address. Handle those cases gracefully. */
346 if (taken_edge == NULL)
348 m_path.pop ();
349 return NULL;
352 *creates_irreducible_loop = false;
353 if (threaded_through_latch
354 && loop == taken_edge->dest->loop_father
355 && (determine_bb_domination_status (loop, taken_edge->dest)
356 == DOMST_NONDOMINATING))
357 *creates_irreducible_loop = true;
359 if (path_crosses_loops)
361 if (dump_file && (dump_flags & TDF_DETAILS))
362 fprintf (dump_file, "FSM jump-thread path not considered: "
363 "the path crosses loops.\n");
364 m_path.pop ();
365 return NULL;
368 /* Threading is profitable if the path duplicated is hot but also
369 in a case we separate cold path from hot path and permit optimization
370 of the hot path later. Be on the agressive side here. In some testcases,
371 as in PR 78407 this leads to noticeable improvements. */
372 if (m_speed_p && (optimize_edge_for_speed_p (taken_edge) || contains_hot_bb))
374 if (n_insns >= param_max_fsm_thread_path_insns)
376 if (dump_file && (dump_flags & TDF_DETAILS))
377 fprintf (dump_file, "FSM jump-thread path not considered: "
378 "the number of instructions on the path "
379 "exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
380 m_path.pop ();
381 return NULL;
384 else if (n_insns > 1)
386 if (dump_file && (dump_flags & TDF_DETAILS))
387 fprintf (dump_file, "FSM jump-thread path not considered: "
388 "duplication of %i insns is needed and optimizing for size.\n",
389 n_insns);
390 m_path.pop ();
391 return NULL;
394 /* We avoid creating irreducible inner loops unless we thread through
395 a multiway branch, in which case we have deemed it worth losing
396 other loop optimizations later.
398 We also consider it worth creating an irreducible inner loop if
399 the number of copied statement is low relative to the length of
400 the path -- in that case there's little the traditional loop
401 optimizer would have done anyway, so an irreducible loop is not
402 so bad. */
403 if (!threaded_multiway_branch && *creates_irreducible_loop
404 && (n_insns * (unsigned) param_fsm_scale_path_stmts
405 > (m_path.length () *
406 (unsigned) param_fsm_scale_path_blocks)))
409 if (dump_file && (dump_flags & TDF_DETAILS))
410 fprintf (dump_file,
411 "FSM would create irreducible loop without threading "
412 "multiway branch.\n");
413 m_path.pop ();
414 return NULL;
418 /* If this path does not thread through the loop latch, then we are
419 using the FSM threader to find old style jump threads. This
420 is good, except the FSM threader does not re-use an existing
421 threading path to reduce code duplication.
423 So for that case, drastically reduce the number of statements
424 we are allowed to copy. */
425 if (!(threaded_through_latch && threaded_multiway_branch)
426 && (n_insns * param_fsm_scale_path_stmts
427 >= param_max_jump_thread_duplication_stmts))
429 if (dump_file && (dump_flags & TDF_DETAILS))
430 fprintf (dump_file,
431 "FSM did not thread around loop and would copy too "
432 "many statements.\n");
433 m_path.pop ();
434 return NULL;
437 /* When there is a multi-way branch on the path, then threading can
438 explode the CFG due to duplicating the edges for that multi-way
439 branch. So like above, only allow a multi-way branch on the path
440 if we actually thread a multi-way branch. */
441 if (!threaded_multiway_branch && multiway_branch_in_path)
443 if (dump_file && (dump_flags & TDF_DETAILS))
444 fprintf (dump_file,
445 "FSM Thread through multiway branch without threading "
446 "a multiway branch.\n");
447 m_path.pop ();
448 return NULL;
450 return taken_edge;
453 /* The current path PATH is a vector of blocks forming a jump threading
454 path in reverse order. TAKEN_EDGE is the edge taken from path[0].
456 Convert the current path into the form used by register_jump_thread and
457 register it. */
459 void
460 thread_jumps::convert_and_register_current_path (edge taken_edge)
462 vec<jump_thread_edge *> *jump_thread_path = new vec<jump_thread_edge *> ();
464 /* Record the edges between the blocks in PATH. */
465 for (unsigned int j = 0; j + 1 < m_path.length (); j++)
467 basic_block bb1 = m_path[m_path.length () - j - 1];
468 basic_block bb2 = m_path[m_path.length () - j - 2];
470 edge e = find_edge (bb1, bb2);
471 gcc_assert (e);
472 jump_thread_edge *x = new jump_thread_edge (e, EDGE_FSM_THREAD);
473 jump_thread_path->safe_push (x);
476 /* Add the edge taken when the control variable has value ARG. */
477 jump_thread_edge *x
478 = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
479 jump_thread_path->safe_push (x);
481 register_jump_thread (jump_thread_path);
482 --m_max_threaded_paths;
485 /* While following a chain of SSA_NAME definitions, we jumped from a
486 definition in LAST_BB to a definition in NEW_BB (walking
487 backwards).
489 Verify there is a single path between the blocks and none of the
490 blocks in the path is already in VISITED_BBS. If so, then update
491 VISISTED_BBS, add the new blocks to PATH and return TRUE.
492 Otherwise return FALSE.
494 Store the length of the subpath in NEXT_PATH_LENGTH. */
496 bool
497 thread_jumps::check_subpath_and_update_thread_path (basic_block last_bb,
498 basic_block new_bb,
499 int *next_path_length)
501 edge e;
502 int e_count = 0;
503 edge_iterator ei;
504 auto_vec<basic_block> next_path;
506 FOR_EACH_EDGE (e, ei, last_bb->preds)
508 hash_set<basic_block> local_visited_bbs;
510 if (fsm_find_thread_path (new_bb, e->src, next_path,
511 local_visited_bbs, e->src->loop_father))
512 ++e_count;
514 /* If there is more than one path, stop. */
515 if (e_count > 1)
516 return false;
519 /* Stop if we have not found a path: this could occur when the recursion
520 is stopped by one of the bounds. */
521 if (e_count == 0)
522 return false;
524 /* Make sure we haven't already visited any of the nodes in
525 NEXT_PATH. Don't add them here to avoid pollution. */
526 for (unsigned int i = 0; i + 1 < next_path.length (); i++)
528 if (m_visited_bbs.contains (next_path[i]))
529 return false;
532 /* Now add the nodes to VISISTED_BBS. */
533 for (unsigned int i = 0; i + 1 < next_path.length (); i++)
534 m_visited_bbs.add (next_path[i]);
536 /* Append all the nodes from NEXT_PATH to PATH. */
537 m_path.safe_splice (next_path);
538 *next_path_length = next_path.length ();
540 return true;
543 /* If this is a profitable jump thread path, register it.
545 NAME is an SSA NAME with a possible constant value of ARG on PATH.
547 DEF_BB is the basic block that ultimately defines the constant. */
549 void
550 thread_jumps::register_jump_thread_path_if_profitable (tree name, tree arg,
551 basic_block def_bb)
553 if (TREE_CODE_CLASS (TREE_CODE (arg)) != tcc_constant)
554 return;
556 bool irreducible = false;
557 edge taken_edge = profitable_jump_thread_path (def_bb, name, arg,
558 &irreducible);
559 if (taken_edge)
561 convert_and_register_current_path (taken_edge);
562 m_path.pop ();
564 if (irreducible)
565 vect_free_loop_info_assumptions (m_path[0]->loop_father);
569 /* Given PHI which defines NAME in block DEF_BB, recurse through the
570 PHI's arguments searching for paths where NAME will ultimately have
571 a constant value.
573 PATH contains the series of blocks to traverse that will result in
574 NAME having a constant value. */
576 void
577 thread_jumps::handle_phi (gphi *phi, tree name, basic_block def_bb)
579 /* Iterate over the arguments of PHI. */
580 for (unsigned int i = 0; i < gimple_phi_num_args (phi); i++)
582 tree arg = gimple_phi_arg_def (phi, i);
583 basic_block bbi = gimple_phi_arg_edge (phi, i)->src;
585 /* Skip edges pointing outside the current loop. */
586 if (!arg || def_bb->loop_father != bbi->loop_father)
587 continue;
589 if (TREE_CODE (arg) == SSA_NAME)
591 m_path.safe_push (bbi);
592 /* Recursively follow SSA_NAMEs looking for a constant
593 definition. */
594 fsm_find_control_statement_thread_paths (arg);
596 m_path.pop ();
597 continue;
600 register_jump_thread_path_if_profitable (name, arg, bbi);
604 /* Return TRUE if STMT is a gimple assignment we want to either directly
605 handle or recurse through. Return FALSE otherwise.
607 Note that adding more cases here requires adding cases to handle_assignment
608 below. */
610 static bool
611 handle_assignment_p (gimple *stmt)
613 if (is_gimple_assign (stmt))
615 enum tree_code def_code = gimple_assign_rhs_code (stmt);
617 /* If the RHS is an SSA_NAME, then we will recurse through it.
618 Go ahead and filter out cases where the SSA_NAME is a default
619 definition. There's little to be gained by trying to handle that. */
620 if (def_code == SSA_NAME
621 && !SSA_NAME_IS_DEFAULT_DEF (gimple_assign_rhs1 (stmt)))
622 return true;
624 /* If the RHS is a constant, then it's a terminal that we'll want
625 to handle as well. */
626 if (TREE_CODE_CLASS (def_code) == tcc_constant)
627 return true;
630 /* Anything not explicitly allowed is not handled. */
631 return false;
634 /* Given STMT which defines NAME in block DEF_BB, recurse through the
635 PHI's arguments searching for paths where NAME will ultimately have
636 a constant value.
638 PATH contains the series of blocks to traverse that will result in
639 NAME having a constant value. */
641 void
642 thread_jumps::handle_assignment (gimple *stmt, tree name, basic_block def_bb)
644 tree arg = gimple_assign_rhs1 (stmt);
646 if (TREE_CODE (arg) == SSA_NAME)
647 fsm_find_control_statement_thread_paths (arg);
649 else
651 /* register_jump_thread_path_if_profitable will push the current
652 block onto the path. But the path will always have the current
653 block at this point. So we can just pop it. */
654 m_path.pop ();
656 register_jump_thread_path_if_profitable (name, arg, def_bb);
658 /* And put the current block back onto the path so that the
659 state of the stack is unchanged when we leave. */
660 m_path.safe_push (def_bb);
664 /* We trace the value of the SSA_NAME NAME back through any phi nodes
665 looking for places where it gets a constant value and save the
666 path. */
668 void
669 thread_jumps::fsm_find_control_statement_thread_paths (tree name)
671 /* If NAME appears in an abnormal PHI, then don't try to trace its
672 value back through PHI nodes. */
673 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
674 return;
676 gimple *def_stmt = SSA_NAME_DEF_STMT (name);
677 basic_block def_bb = gimple_bb (def_stmt);
679 if (def_bb == NULL)
680 return;
682 /* We allow the SSA chain to contains PHIs and simple copies and constant
683 initializations. */
684 if (gimple_code (def_stmt) != GIMPLE_PHI
685 && gimple_code (def_stmt) != GIMPLE_ASSIGN)
686 return;
688 if (gimple_code (def_stmt) == GIMPLE_PHI
689 && (gimple_phi_num_args (def_stmt)
690 >= (unsigned) param_fsm_maximum_phi_arguments))
691 return;
693 if (is_gimple_assign (def_stmt)
694 && ! handle_assignment_p (def_stmt))
695 return;
697 /* Avoid infinite recursion. */
698 if (m_visited_bbs.add (def_bb))
699 return;
701 int next_path_length = 0;
702 basic_block last_bb_in_path = m_path.last ();
704 if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt))
706 /* Do not walk through more than one loop PHI node. */
707 if (m_seen_loop_phi)
708 return;
709 m_seen_loop_phi = true;
712 /* Following the chain of SSA_NAME definitions, we jumped from a definition in
713 LAST_BB_IN_PATH to a definition in DEF_BB. When these basic blocks are
714 different, append to PATH the blocks from LAST_BB_IN_PATH to DEF_BB. */
715 if (def_bb != last_bb_in_path)
717 /* When DEF_BB == LAST_BB_IN_PATH, then the first block in the path
718 will already be in VISITED_BBS. When they are not equal, then we
719 must ensure that first block is accounted for to ensure we do not
720 create bogus jump threading paths. */
721 m_visited_bbs.add (m_path[0]);
722 if (!check_subpath_and_update_thread_path (last_bb_in_path, def_bb,
723 &next_path_length))
724 return;
727 gcc_assert (m_path.last () == def_bb);
729 if (gimple_code (def_stmt) == GIMPLE_PHI)
730 handle_phi (as_a <gphi *> (def_stmt), name, def_bb);
731 else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
732 handle_assignment (def_stmt, name, def_bb);
734 /* Remove all the nodes that we added from NEXT_PATH. */
735 if (next_path_length)
736 m_path.truncate (m_path.length () - next_path_length);
739 /* Search backwards from BB looking for paths where NAME (an SSA_NAME)
740 is a constant. Record such paths for jump threading.
742 It is assumed that BB ends with a control statement and that by
743 finding a path where NAME is a constant, we can thread the path.
744 SPEED_P indicates that we could increase code size to improve the
745 code path. */
747 void
748 thread_jumps::find_jump_threads_backwards (basic_block bb, bool speed_p)
750 gimple *stmt = get_gimple_control_stmt (bb);
751 if (!stmt)
752 return;
754 enum gimple_code code = gimple_code (stmt);
755 tree name = NULL;
756 if (code == GIMPLE_SWITCH)
757 name = gimple_switch_index (as_a <gswitch *> (stmt));
758 else if (code == GIMPLE_GOTO)
759 name = gimple_goto_dest (stmt);
760 else if (code == GIMPLE_COND)
762 if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
763 && TREE_CODE_CLASS (TREE_CODE (gimple_cond_rhs (stmt))) == tcc_constant
764 && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
765 || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
766 name = gimple_cond_lhs (stmt);
769 if (!name || TREE_CODE (name) != SSA_NAME)
770 return;
772 /* Initialize pass local data that's different for each BB. */
773 m_path.truncate (0);
774 m_path.safe_push (bb);
775 m_visited_bbs.empty ();
776 m_seen_loop_phi = false;
777 m_speed_p = speed_p;
778 m_max_threaded_paths = param_max_fsm_thread_paths;
780 fsm_find_control_statement_thread_paths (name);
783 namespace {
785 const pass_data pass_data_thread_jumps =
787 GIMPLE_PASS,
788 "thread",
789 OPTGROUP_NONE,
790 TV_TREE_SSA_THREAD_JUMPS,
791 ( PROP_cfg | PROP_ssa ),
795 TODO_update_ssa,
798 class pass_thread_jumps : public gimple_opt_pass
800 public:
801 pass_thread_jumps (gcc::context *ctxt)
802 : gimple_opt_pass (pass_data_thread_jumps, ctxt)
805 opt_pass * clone (void) { return new pass_thread_jumps (m_ctxt); }
806 virtual bool gate (function *);
807 virtual unsigned int execute (function *);
810 bool
811 pass_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
813 return flag_expensive_optimizations;
817 unsigned int
818 pass_thread_jumps::execute (function *fun)
820 loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
822 /* Try to thread each block with more than one successor. */
823 thread_jumps threader;
824 basic_block bb;
825 FOR_EACH_BB_FN (bb, fun)
827 if (EDGE_COUNT (bb->succs) > 1)
828 threader.find_jump_threads_backwards (bb, true);
830 bool changed = thread_through_all_blocks (true);
832 loop_optimizer_finalize ();
833 return changed ? TODO_cleanup_cfg : 0;
838 gimple_opt_pass *
839 make_pass_thread_jumps (gcc::context *ctxt)
841 return new pass_thread_jumps (ctxt);
844 namespace {
846 const pass_data pass_data_early_thread_jumps =
848 GIMPLE_PASS,
849 "ethread",
850 OPTGROUP_NONE,
851 TV_TREE_SSA_THREAD_JUMPS,
852 ( PROP_cfg | PROP_ssa ),
856 ( TODO_cleanup_cfg | TODO_update_ssa ),
859 class pass_early_thread_jumps : public gimple_opt_pass
861 public:
862 pass_early_thread_jumps (gcc::context *ctxt)
863 : gimple_opt_pass (pass_data_early_thread_jumps, ctxt)
866 opt_pass * clone (void) { return new pass_early_thread_jumps (m_ctxt); }
867 virtual bool gate (function *);
868 virtual unsigned int execute (function *);
871 bool
872 pass_early_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
874 return true;
878 unsigned int
879 pass_early_thread_jumps::execute (function *fun)
881 loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
883 /* Try to thread each block with more than one successor. */
884 thread_jumps threader;
885 basic_block bb;
886 FOR_EACH_BB_FN (bb, fun)
888 if (EDGE_COUNT (bb->succs) > 1)
889 threader.find_jump_threads_backwards (bb, false);
891 thread_through_all_blocks (true);
893 loop_optimizer_finalize ();
894 return 0;
899 gimple_opt_pass *
900 make_pass_early_thread_jumps (gcc::context *ctxt)
902 return new pass_early_thread_jumps (ctxt);