Bug Summary

File:build/gcc/tree-ssa-loop-unswitch.cc
Warning:line 1091, column 7
Value stored to 'changed' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-suse-linux -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name tree-ssa-loop-unswitch.cc -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model static -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -resource-dir /usr/lib64/clang/15.0.7 -D IN_GCC -D HAVE_CONFIG_H -I . -I . -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/. -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../include -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcpp/include -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libcody -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libdecnumber/bid -I ../libdecnumber -I /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/../libbacktrace -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/x86_64-suse-linux -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../include/c++/13/backward -internal-isystem /usr/lib64/clang/15.0.7/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib64/gcc/x86_64-suse-linux/13/../../../../x86_64-suse-linux/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-narrowing -Wwrite-strings -Wno-long-long -Wno-variadic-macros -Wno-overlength-strings -fdeprecated-macro -fdebug-compilation-dir=/buildworker/marxinbox-gcc-clang-static-analyzer/objdir/gcc -ferror-limit 19 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=plist-html -analyzer-config silence-checkers=core.NullDereference -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /buildworker/marxinbox-gcc-clang-static-analyzer/objdir/clang-static-analyzer/2023-03-27-141847-20772-1/report-n7Hnh2.plist -x c++ /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc
1/* Loop unswitching.
2 Copyright (C) 2004-2023 Free Software Foundation, Inc.
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it
7under the terms of the GNU General Public License as published by the
8Free Software Foundation; either version 3, or (at your option) any
9later version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT
12ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along 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 "gimplify.h"
30#include "tree-cfg.h"
31#include "tree-ssa.h"
32#include "tree-ssa-loop-niter.h"
33#include "tree-ssa-loop.h"
34#include "tree-into-ssa.h"
35#include "cfgloop.h"
36#include "tree-inline.h"
37#include "gimple-iterator.h"
38#include "cfghooks.h"
39#include "tree-ssa-loop-manip.h"
40#include "tree-vectorizer.h"
41#include "tree-pretty-print.h"
42#include "gimple-range.h"
43#include "dbgcnt.h"
44#include "cfganal.h"
45
46/* This file implements the loop unswitching, i.e. transformation of loops like
47
48 while (A)
49 {
50 if (inv)
51 B;
52
53 X;
54
55 if (!inv)
56 C;
57 }
58
59 where inv is the loop invariant, into
60
61 if (inv)
62 {
63 while (A)
64 {
65 B;
66 X;
67 }
68 }
69 else
70 {
71 while (A)
72 {
73 X;
74 C;
75 }
76 }
77
78 Inv is considered invariant iff the values it compares are both invariant;
79 tree-ssa-loop-im.cc ensures that all the suitable conditions are in this
80 shape. */
81
82/* Loop unswitching algorithm for innermost loops works in the following steps:
83
84 1) Number of instructions is estimated for each BB that belongs to a loop.
85 2) Unswitching candidates are found for gcond and gswitch statements
86 (note that an unswitching predicate for a gswitch actually corresponds
87 to a non-default edge so it can contain multiple cases).
88 3) The so called unswitch predicates are stored in a cache where the
89 gimple_uid of the last stmt in a basic-block is an index to the cache.
90 4) We consider one by one the unswitching candidates and calculate BBs that
91 will be reachable in the unswitch version.
92 5) A selected predicate is chosen and we simplify the CFG (dead edges) in
93 both versions of the loop. We utilize both Ranger for condition
94 simplification and also symbol equivalence. The folded if conditions
95 are replaced with true/false values, while for gswitch we mark the
96 corresponding edges with a pass-defined unreachable flag.
97 6) Every time we unswitch a loop, we save unswitch_predicate to a vector
98 together with information if true or false edge was taken. Doing that
99 we have a so called PREDICATE_PATH that is utilized for simplification
100 of the cloned loop.
101 7) The process is repeated until we reach a growth threshold or all
102 unswitching opportunities are taken. */
103
104/* A tuple that holds a GENERIC condition and value range for an unswitching
105 predicate. */
106
107struct unswitch_predicate
108{
109 /* CTOR for a switch edge predicate. */
110 unswitch_predicate (tree cond, tree lhs_, int edge_index_, edge e,
111 const int_range_max& edge_range)
112 : condition (cond), lhs (lhs_),
113 true_range (edge_range), edge_index (edge_index_), switch_p (true)
114 {
115 gcc_assert (!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE))((void)(!(!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE
)) && irange::supports_p (((contains_struct_check ((lhs
), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 116, __FUNCTION__))->typed.type))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 116, __FUNCTION__), 0 : 0))
116 && irange::supports_p (TREE_TYPE (lhs)))((void)(!(!(e->flags & (EDGE_TRUE_VALUE|EDGE_FALSE_VALUE
)) && irange::supports_p (((contains_struct_check ((lhs
), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 116, __FUNCTION__))->typed.type))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 116, __FUNCTION__), 0 : 0))
;
117 false_range = true_range;
118 if (!false_range.varying_p ()
119 && !false_range.undefined_p ())
120 false_range.invert ();
121 count = e->count ();
122 num = predicates->length ();
123 predicates->safe_push (this);
124 }
125
126 /* CTOR for a GIMPLE condition statement. */
127 unswitch_predicate (gcond *stmt)
128 : switch_p (false)
129 {
130 basic_block bb = gimple_bb (stmt);
131 if (EDGE_SUCC (bb, 0)(*(bb)->succs)[(0)]->flags & EDGE_TRUE_VALUE)
132 edge_index = 0;
133 else
134 edge_index = 1;
135 lhs = gimple_cond_lhs (stmt);
136 tree rhs = gimple_cond_rhs (stmt);
137 enum tree_code code = gimple_cond_code (stmt);
138 condition = build2 (code, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], lhs, rhs);
139 count = EDGE_SUCC (bb, 0)(*(bb)->succs)[(0)]->count ().max (EDGE_SUCC (bb, 1)(*(bb)->succs)[(1)]->count ());
140 if (irange::supports_p (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 140, __FUNCTION__))->typed.type)
))
141 {
142 auto range_op = range_op_handler (code, TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 142, __FUNCTION__))->typed.type)
);
143 int_range<2> rhs_range (TREE_TYPE (rhs)((contains_struct_check ((rhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 143, __FUNCTION__))->typed.type)
);
144 if (CONSTANT_CLASS_P (rhs)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code
) (rhs)->base.code))] == tcc_constant)
)
145 rhs_range.set (rhs, rhs);
146 if (!range_op.op1_range (true_range, TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 146, __FUNCTION__))->typed.type)
,
147 int_range<2> (boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE],
148 boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]), rhs_range)
149 || !range_op.op1_range (false_range, TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 149, __FUNCTION__))->typed.type)
,
150 int_range<2> (boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE],
151 boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]),
152 rhs_range))
153 {
154 true_range.set_varying (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 154, __FUNCTION__))->typed.type)
);
155 false_range.set_varying (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 155, __FUNCTION__))->typed.type)
);
156 }
157 }
158 num = predicates->length ();
159 predicates->safe_push (this);
160 }
161
162 /* Copy ranges for purpose of usage in predicate path. */
163
164 inline void
165 copy_merged_ranges ()
166 {
167 merged_true_range = true_range;
168 merged_false_range = false_range;
169 }
170
171 /* GENERIC unswitching expression testing LHS against CONSTANT. */
172 tree condition;
173
174 /* LHS of the expression. */
175 tree lhs;
176
177 /* Initial ranges (when the expression is true/false) for the expression. */
178 int_range_max true_range = {}, false_range = {};
179
180 /* Modified range that is part of a predicate path. */
181 int_range_max merged_true_range = {}, merged_false_range = {};
182
183 /* Index of the edge the predicate belongs to in the successor vector. */
184 int edge_index;
185
186 /* The profile count of this predicate. */
187 profile_count count;
188
189 /* Whether the predicate was created from a switch statement. */
190 bool switch_p;
191
192 /* The number of the predicate in the predicates vector below. */
193 unsigned num;
194
195 /* Vector of all used predicates, used for assigning a unique id that
196 can be used for bitmap operations. */
197 static vec<unswitch_predicate *> *predicates;
198};
199
200vec<unswitch_predicate *> *unswitch_predicate::predicates;
201
202/* Ranger instance used in the pass. */
203static gimple_ranger *ranger = NULLnullptr;
204
205/* Cache storage for unswitch_predicate belonging to a basic block. */
206static vec<vec<unswitch_predicate *>> *bb_predicates;
207
208/* The type represents a predicate path leading to a basic block. */
209typedef vec<std::pair<unswitch_predicate *, bool>> predicate_vector;
210
211static class loop *tree_unswitch_loop (class loop *, edge, tree);
212static bool tree_unswitch_single_loop (class loop *, dump_user_location_t,
213 predicate_vector &predicate_path,
214 unsigned loop_size, unsigned &budget,
215 int ignored_edge_flag, bitmap,
216 unswitch_predicate * = NULLnullptr,
217 basic_block = NULLnullptr);
218static void
219find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
220 class loop *&outer_loop,
221 vec<unswitch_predicate *> &candidates,
222 unswitch_predicate *&hottest,
223 basic_block &hottest_bb);
224static bool tree_unswitch_outer_loop (class loop *);
225static edge find_loop_guard (class loop *, vec<gimple *>&);
226static bool empty_bb_without_guard_p (class loop *, basic_block,
227 vec<gimple *>&);
228static bool used_outside_loop_p (class loop *, tree, vec<gimple *>&);
229static void hoist_guard (class loop *, edge);
230static bool check_exit_phi (class loop *);
231static tree get_vop_from_header (class loop *);
232static void clean_up_after_unswitching (int);
233
234/* Return vector of predicates that belong to a basic block. */
235
236static vec<unswitch_predicate *> &
237get_predicates_for_bb (basic_block bb)
238{
239 gimple *last = last_stmt (bb);
240 return (*bb_predicates)[last == NULLnullptr ? 0 : gimple_uid (last)];
241}
242
243/* Save predicates that belong to a basic block. */
244
245static void
246set_predicates_for_bb (basic_block bb, vec<unswitch_predicate *> predicates)
247{
248 gimple_set_uid (last_stmt (bb), bb_predicates->length ());
249 bb_predicates->safe_push (predicates);
250}
251
252/* Initialize LOOP information reused during the unswitching pass.
253 Return total number of instructions in the loop. Adjusts LOOP to
254 the outermost loop all candidates are invariant in. */
255
256static unsigned
257init_loop_unswitch_info (class loop *&loop, unswitch_predicate *&hottest,
258 basic_block &hottest_bb)
259{
260 unsigned total_insns = 0;
261
262 basic_block *bbs = get_loop_body (loop);
263
264 /* Unswitch only nests with no sibling loops. */
265 class loop *outer_loop = loop;
266 unsigned max_depth = param_max_unswitch_depthglobal_options.x_param_max_unswitch_depth;
267 while (loop_outer (outer_loop)->num != 0
268 && !loop_outer (outer_loop)->inner->next
269 && --max_depth != 0)
270 outer_loop = loop_outer (outer_loop);
271 hottest = NULLnullptr;
272 hottest_bb = NULLnullptr;
273 /* Find all unswitching candidates in the innermost loop. */
274 for (unsigned i = 0; i != loop->num_nodes; i++)
275 {
276 /* Find a bb to unswitch on. */
277 vec<unswitch_predicate *> candidates;
278 candidates.create (1);
279 find_unswitching_predicates_for_bb (bbs[i], loop, outer_loop, candidates,
280 hottest, hottest_bb);
281 if (!candidates.is_empty ())
282 set_predicates_for_bb (bbs[i], candidates);
283 else
284 {
285 candidates.release ();
286 gimple *last = last_stmt (bbs[i]);
287 if (last != NULLnullptr)
288 gimple_set_uid (last, 0);
289 }
290 }
291
292 if (outer_loop != loop)
293 {
294 free (bbs);
295 bbs = get_loop_body (outer_loop);
296 }
297
298 /* Calculate instruction count. */
299 for (unsigned i = 0; i < outer_loop->num_nodes; i++)
300 {
301 unsigned insns = 0;
302 for (gimple_stmt_iterator gsi = gsi_start_bb (bbs[i]); !gsi_end_p (gsi);
303 gsi_next (&gsi))
304 insns += estimate_num_insns (gsi_stmt (gsi), &eni_size_weights);
305 /* No predicates to unswitch on in the outer loops. */
306 if (!flow_bb_inside_loop_p (loop, bbs[i]))
307 {
308 gimple *last = last_stmt (bbs[i]);
309 if (last != NULLnullptr)
310 gimple_set_uid (last, 0);
311 }
312
313 bbs[i]->aux = (void *)(uintptr_t)insns;
314 total_insns += insns;
315 }
316
317 free (bbs);
318
319 loop = outer_loop;
320 return total_insns;
321}
322
323/* Main entry point. Perform loop unswitching on all suitable loops. */
324
325unsigned int
326tree_ssa_unswitch_loops (function *fun)
327{
328 bool changed_unswitch = false;
329 bool changed_hoist = false;
330 auto_edge_flag ignored_edge_flag (fun);
331
332 ranger = enable_ranger (fun);
333
334 /* Go through all loops starting from innermost, hoisting guards. */
335 for (auto loop : loops_list (fun, LI_FROM_INNERMOST))
336 {
337 if (loop->inner)
338 changed_hoist |= tree_unswitch_outer_loop (loop);
339 }
340
341 /* Go through innermost loops, unswitching on invariant predicates
342 within those. */
343 for (auto loop : loops_list (fun, LI_ONLY_INNERMOST))
344 {
345 /* Perform initial tests if unswitch is eligible. */
346 dump_user_location_t loc = find_loop_location (loop);
347
348 /* Do not unswitch in cold regions. */
349 if (optimize_loop_for_size_p (loop))
350 {
351 if (dump_enabled_p ())
352 dump_printf_loc (MSG_NOTE, loc,
353 "Not unswitching cold loops\n");
354 continue;
355 }
356
357 /* If the loop is not expected to iterate, there is no need
358 for unswitching. */
359 HOST_WIDE_INTlong iterations = estimated_loop_iterations_int (loop);
360 if (iterations < 0)
361 iterations = likely_max_loop_iterations_int (loop);
362 if (iterations >= 0 && iterations <= 1)
363 {
364 if (dump_enabled_p ())
365 dump_printf_loc (MSG_NOTE, loc,
366 "Not unswitching, loop is not expected"
367 " to iterate\n");
368 continue;
369 }
370
371 bb_predicates = new vec<vec<unswitch_predicate *>> ();
372 bb_predicates->safe_push (vec<unswitch_predicate *> ());
373 unswitch_predicate::predicates = new vec<unswitch_predicate *> ();
374
375 /* Unswitch loop. */
376 unswitch_predicate *hottest;
377 basic_block hottest_bb;
378 unsigned int loop_size = init_loop_unswitch_info (loop, hottest,
379 hottest_bb);
380 unsigned int budget = loop_size + param_max_unswitch_insnsglobal_options.x_param_max_unswitch_insns;
381
382 predicate_vector predicate_path;
383 predicate_path.create (8);
384 auto_bitmap handled;
385 changed_unswitch |= tree_unswitch_single_loop (loop, loc, predicate_path,
386 loop_size, budget,
387 ignored_edge_flag, handled,
388 hottest, hottest_bb);
389 predicate_path.release ();
390
391 for (auto predlist : bb_predicates)
392 predlist.release ();
393 bb_predicates->release ();
394 delete bb_predicates;
395 bb_predicates = NULLnullptr;
396
397 for (auto pred : unswitch_predicate::predicates)
398 delete pred;
399 unswitch_predicate::predicates->release ();
400 delete unswitch_predicate::predicates;
401 unswitch_predicate::predicates = NULLnullptr;
402 }
403
404 disable_ranger (fun);
405 clear_aux_for_blocks ();
406
407 if (changed_unswitch)
408 clean_up_after_unswitching (ignored_edge_flag);
409
410 if (changed_unswitch || changed_hoist)
411 return TODO_cleanup_cfg(1 << 5);
412
413 return 0;
414}
415
416/* Return TRUE if an SSA_NAME maybe undefined and is therefore
417 unsuitable for unswitching. STMT is the statement we are
418 considering for unswitching and LOOP is the loop it appears in. */
419
420static bool
421is_maybe_undefined (const tree name, gimple *stmt, class loop *loop)
422{
423 /* The loop header is the only block we can trivially determine that
424 will always be executed. If the comparison is in the loop
425 header, we know it's OK to unswitch on it. */
426 if (gimple_bb (stmt) == loop->header)
427 return false;
428
429 auto_bitmap visited_ssa;
430 auto_vec<tree> worklist;
431 worklist.safe_push (name);
432 bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (name)(tree_check ((name), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 432, __FUNCTION__, (SSA_NAME)))->base.u.version
);
433 while (!worklist.is_empty ())
434 {
435 tree t = worklist.pop ();
436
437 /* If it's obviously undefined, avoid further computations. */
438 if (ssa_undefined_value_p (t, true))
439 return true;
440
441 if (ssa_defined_default_def_p (t))
442 continue;
443
444 gimple *def = SSA_NAME_DEF_STMT (t)(tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 444, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
445
446 /* Check that all the PHI args are fully defined. */
447 if (gphi *phi = dyn_cast <gphi *> (def))
448 {
449 for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i)
450 {
451 tree t = gimple_phi_arg_def (phi, i);
452 /* If an SSA has already been seen, it may be a loop,
453 but we can continue and ignore this use. Otherwise,
454 add the SSA_NAME to the queue and visit it later. */
455 if (TREE_CODE (t)((enum tree_code) (t)->base.code) == SSA_NAME
456 && bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)(tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 456, __FUNCTION__, (SSA_NAME)))->base.u.version
))
457 worklist.safe_push (t);
458 }
459 continue;
460 }
461
462 /* Uses in stmts always executed when the region header executes
463 are fine. */
464 if (dominated_by_p (CDI_DOMINATORS, loop->header, gimple_bb (def)))
465 continue;
466
467 /* Handle calls and memory loads conservatively. */
468 if (!is_gimple_assign (def)
469 || (gimple_assign_single_p (def)
470 && gimple_vuse (def)))
471 return true;
472
473 /* Check that any SSA names used to define NAME are also fully
474 defined. */
475 use_operand_p use_p;
476 ssa_op_iter iter;
477 FOR_EACH_SSA_USE_OPERAND (use_p, def, iter, SSA_OP_USE)for (use_p = op_iter_init_use (&(iter), def, 0x01); !op_iter_done
(&(iter)); use_p = op_iter_next_use (&(iter)))
478 {
479 tree t = USE_FROM_PTR (use_p)get_use_from_ptr (use_p);
480 /* If an SSA has already been seen, it may be a loop,
481 but we can continue and ignore this use. Otherwise,
482 add the SSA_NAME to the queue and visit it later. */
483 if (bitmap_set_bit (visited_ssa, SSA_NAME_VERSION (t)(tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 483, __FUNCTION__, (SSA_NAME)))->base.u.version
))
484 worklist.safe_push (t);
485 }
486 }
487 return false;
488}
489
490/* Checks whether we can unswitch LOOP on condition at end of BB -- one of its
491 basic blocks (for what it means see comments below).
492 All candidates all filled to the provided vector CANDIDATES.
493 OUTER_LOOP is updated to the innermost loop all found candidates are
494 invariant in. */
495
496static void
497find_unswitching_predicates_for_bb (basic_block bb, class loop *loop,
498 class loop *&outer_loop,
499 vec<unswitch_predicate *> &candidates,
500 unswitch_predicate *&hottest,
501 basic_block &hottest_bb)
502{
503 gimple *last, *def;
504 tree use;
505 basic_block def_bb;
506 ssa_op_iter iter;
507
508 /* BB must end in a simple conditional jump. */
509 last = last_stmt (bb);
510 if (!last)
511 return;
512
513 if (gcond *stmt = safe_dyn_cast <gcond *> (last))
514 {
515 /* To keep the things simple, we do not directly remove the conditions,
516 but just replace tests with 0 != 0 resp. 1 != 0. Prevent the infinite
517 loop where we would unswitch again on such a condition. */
518 if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt))
519 return;
520
521 /* At least the LHS needs to be symbolic. */
522 if (TREE_CODE (gimple_cond_lhs (stmt))((enum tree_code) (gimple_cond_lhs (stmt))->base.code) != SSA_NAME)
523 return;
524
525 /* Condition must be invariant. */
526 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)for (use = op_iter_init_tree (&(iter), stmt, 0x01); !op_iter_done
(&(iter)); (void) (use = op_iter_next_tree (&(iter))
))
527 {
528 def = SSA_NAME_DEF_STMT (use)(tree_check ((use), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 528, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
529 def_bb = gimple_bb (def);
530 if (def_bb
531 && flow_bb_inside_loop_p (loop, def_bb))
532 return;
533 /* Unswitching on undefined values would introduce undefined
534 behavior that the original program might never exercise. */
535 if (is_maybe_undefined (use, stmt, loop))
536 return;
537 }
538 /* Narrow OUTER_LOOP. */
539 if (outer_loop != loop)
540 FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)for (use = op_iter_init_tree (&(iter), stmt, 0x01); !op_iter_done
(&(iter)); (void) (use = op_iter_next_tree (&(iter))
))
541 {
542 def = SSA_NAME_DEF_STMT (use)(tree_check ((use), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 542, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
543 def_bb = gimple_bb (def);
544 while (outer_loop != loop
545 && ((def_bb && flow_bb_inside_loop_p (outer_loop, def_bb))
546 || is_maybe_undefined (use, stmt, outer_loop)))
547 outer_loop = superloop_at_depth (loop,
548 loop_depth (outer_loop) + 1);
549 }
550
551 unswitch_predicate *predicate = new unswitch_predicate (stmt);
552 candidates.safe_push (predicate);
553 /* If we unswitch on this predicate we isolate both paths, so
554 pick the highest count for updating of the hottest predicate
555 to unswitch on first. */
556 if (!hottest || predicate->count > hottest->count)
557 {
558 hottest = predicate;
559 hottest_bb = bb;
560 }
561 }
562 else if (gswitch *stmt = safe_dyn_cast <gswitch *> (last))
563 {
564 unsigned nlabels = gimple_switch_num_labels (stmt);
565 tree idx = gimple_switch_index (stmt);
566 tree idx_type = TREE_TYPE (idx)((contains_struct_check ((idx), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 566, __FUNCTION__))->typed.type)
;
567 if (!gimple_range_ssa_p (idx) || nlabels < 1)
568 return;
569 /* Index must be invariant. */
570 def = SSA_NAME_DEF_STMT (idx)(tree_check ((idx), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 570, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
571 def_bb = gimple_bb (def);
572 if (def_bb
573 && flow_bb_inside_loop_p (loop, def_bb))
574 return;
575 /* Unswitching on undefined values would introduce undefined
576 behavior that the original program might never exercise. */
577 if (is_maybe_undefined (idx, stmt, loop))
578 return;
579 /* Narrow OUTER_LOOP. */
580 while (outer_loop != loop
581 && ((def_bb && flow_bb_inside_loop_p (outer_loop, def_bb))
582 || is_maybe_undefined (idx, stmt, outer_loop)))
583 outer_loop = superloop_at_depth (loop,
584 loop_depth (outer_loop) + 1);
585
586 /* Build compound expression for all outgoing edges of the switch. */
587 auto_vec<tree, 16> preds;
588 auto_vec<int_range_max> edge_range;
589 preds.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs)vec_safe_length (gimple_bb (stmt)->succs), true);
590 edge_range.safe_grow_cleared (EDGE_COUNT (gimple_bb (stmt)->succs)vec_safe_length (gimple_bb (stmt)->succs), true);
591 edge e;
592 edge_iterator ei;
593 unsigned edge_index = 0;
594 FOR_EACH_EDGE (e, ei, gimple_bb (stmt)->succs)for ((ei) = ei_start_1 (&((gimple_bb (stmt)->succs)));
ei_cond ((ei), &(e)); ei_next (&(ei)))
595 e->aux = (void *)(uintptr_t)edge_index++;
596 for (unsigned i = 1; i < gimple_switch_num_labels (stmt); ++i)
597 {
598 tree lab = gimple_switch_label (stmt, i);
599 tree cmp;
600 int_range<2> lab_range;
601 tree low = fold_convert (idx_type, CASE_LOW (lab))fold_convert_loc (((location_t) 0), idx_type, (*((const_cast<
tree*> (tree_operand_check (((tree_check ((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 601, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 601, __FUNCTION__))))))
;
602 if (CASE_HIGH (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 602, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 602, __FUNCTION__)))))
!= NULL_TREE(tree) nullptr)
603 {
604 tree high = fold_convert (idx_type, CASE_HIGH (lab))fold_convert_loc (((location_t) 0), idx_type, (*((const_cast<
tree*> (tree_operand_check (((tree_check ((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 604, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 604, __FUNCTION__))))))
;
605 tree cmp1 = fold_build2 (GE_EXPR, boolean_type_node, idx, low)fold_build2_loc (((location_t) 0), GE_EXPR, global_trees[TI_BOOLEAN_TYPE
], idx, low )
;
606 tree cmp2 = fold_build2 (LE_EXPR, boolean_type_node, idx, high)fold_build2_loc (((location_t) 0), LE_EXPR, global_trees[TI_BOOLEAN_TYPE
], idx, high )
;
607 cmp = fold_build2 (BIT_AND_EXPR, boolean_type_node, cmp1, cmp2)fold_build2_loc (((location_t) 0), BIT_AND_EXPR, global_trees
[TI_BOOLEAN_TYPE], cmp1, cmp2 )
;
608 lab_range.set (low, high);
609 }
610 else
611 {
612 cmp = fold_build2 (EQ_EXPR, boolean_type_node, idx, low)fold_build2_loc (((location_t) 0), EQ_EXPR, global_trees[TI_BOOLEAN_TYPE
], idx, low )
;
613 lab_range.set (low, low);
614 }
615
616 /* Combine the expression with the existing one. */
617 basic_block dest = label_to_block (cfun(cfun + 0), CASE_LABEL (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 617, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 617, __FUNCTION__)))))
);
618 e = find_edge (gimple_bb (stmt), dest);
619 tree &expr = preds[(uintptr_t)e->aux];
620 if (expr == NULL_TREE(tree) nullptr)
621 expr = cmp;
622 else
623 expr = fold_build2 (BIT_IOR_EXPR, boolean_type_node, expr, cmp)fold_build2_loc (((location_t) 0), BIT_IOR_EXPR, global_trees
[TI_BOOLEAN_TYPE], expr, cmp )
;
624 edge_range[(uintptr_t)e->aux].union_ (lab_range);
625 }
626
627 /* Now register the predicates. */
628 for (edge_index = 0; edge_index < preds.length (); ++edge_index)
629 {
630 edge e = EDGE_SUCC (gimple_bb (stmt), edge_index)(*(gimple_bb (stmt))->succs)[(edge_index)];
631 e->aux = NULLnullptr;
632 if (preds[edge_index] != NULL_TREE(tree) nullptr)
633 {
634 unswitch_predicate *predicate
635 = new unswitch_predicate (preds[edge_index], idx,
636 edge_index, e,
637 edge_range[edge_index]);
638 candidates.safe_push (predicate);
639 if (!hottest || predicate->count > hottest->count)
640 {
641 hottest = predicate;
642 hottest_bb = bb;
643 }
644 }
645 }
646 }
647}
648
649/* Merge ranges for the last item of PREDICATE_PATH with a predicate
650 that shared the same LHS. */
651
652static void
653merge_last (predicate_vector &predicate_path)
654{
655 unswitch_predicate *last_predicate = predicate_path.last ().first;
656
657 for (int i = predicate_path.length () - 2; i >= 0; i--)
658 {
659 unswitch_predicate *predicate = predicate_path[i].first;
660 bool true_edge = predicate_path[i].second;
661
662 if (operand_equal_p (predicate->lhs, last_predicate->lhs, 0))
663 {
664 irange &other = (true_edge ? predicate->merged_true_range
665 : predicate->merged_false_range);
666 last_predicate->merged_true_range.intersect (other);
667 last_predicate->merged_false_range.intersect (other);
668 return;
669 }
670 }
671}
672
673/* Add PREDICATE to PREDICATE_PATH on TRUE_EDGE. */
674
675static void
676add_predicate_to_path (predicate_vector &predicate_path,
677 unswitch_predicate *predicate, bool true_edge)
678{
679 predicate->copy_merged_ranges ();
680 predicate_path.safe_push (std::make_pair (predicate, true_edge));
681 merge_last (predicate_path);
682}
683
684static bool
685find_range_for_lhs (predicate_vector &predicate_path, tree lhs,
686 int_range_max &range)
687{
688 for (int i = predicate_path.length () - 1; i >= 0; i--)
689 {
690 unswitch_predicate *predicate = predicate_path[i].first;
691 bool true_edge = predicate_path[i].second;
692
693 if (operand_equal_p (predicate->lhs, lhs, 0))
694 {
695 range = (true_edge ? predicate->merged_true_range
696 : predicate->merged_false_range);
697 return !range.undefined_p ();
698 }
699 }
700
701 return false;
702}
703
704/* Simplifies STMT using the predicate we unswitched on which is the last
705 in PREDICATE_PATH. For switch statements add newly unreachable edges
706 to IGNORED_EDGES (but do not set IGNORED_EDGE_FLAG on them). */
707
708static tree
709evaluate_control_stmt_using_entry_checks (gimple *stmt,
710 predicate_vector &predicate_path,
711 int ignored_edge_flag,
712 hash_set<edge> *ignored_edges)
713{
714 unswitch_predicate *last_predicate = predicate_path.last ().first;
715 bool true_edge = predicate_path.last ().second;
716
717 if (gcond *cond = dyn_cast<gcond *> (stmt))
718 {
719 tree lhs = gimple_cond_lhs (cond);
720 if (!operand_equal_p (lhs, last_predicate->lhs))
721 return NULL_TREE(tree) nullptr;
722 /* Try a symbolic match which works for floating point and fully
723 symbolic conditions. */
724 if (gimple_cond_code (cond) == TREE_CODE (last_predicate->condition)((enum tree_code) (last_predicate->condition)->base.code
)
725 && operand_equal_p (gimple_cond_rhs (cond),
726 TREE_OPERAND (last_predicate->condition, 1)(*((const_cast<tree*> (tree_operand_check ((last_predicate
->condition), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 726, __FUNCTION__)))))
))
727 return true_edge ? boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] : boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
728 /* Else try ranger if it supports LHS. */
729 else if (irange::supports_p (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 729, __FUNCTION__))->typed.type)
))
730 {
731 int_range<2> r;
732 int_range_max path_range;
733
734 if (find_range_for_lhs (predicate_path, lhs, path_range)
735 && fold_range (r, cond, path_range)
736 && r.singleton_p ())
737 return r.zero_p () ? boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE] : boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE];
738 }
739 }
740 else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
741 {
742 unsigned nlabels = gimple_switch_num_labels (swtch);
743
744 tree idx = gimple_switch_index (swtch);
745
746 /* Already folded switch. */
747 if (TREE_CONSTANT (idx)((non_type_check ((idx), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 747, __FUNCTION__))->base.constant_flag)
)
748 return NULL_TREE(tree) nullptr;
749
750 int_range_max path_range;
751 if (!find_range_for_lhs (predicate_path, idx, path_range))
752 return NULL_TREE(tree) nullptr;
753
754 tree result = NULL_TREE(tree) nullptr;
755 edge single_edge = NULLnullptr;
756 for (unsigned i = 0; i < nlabels; ++i)
757 {
758 tree lab = gimple_switch_label (swtch, i);
759 basic_block dest = label_to_block (cfun(cfun + 0), CASE_LABEL (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 759, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 759, __FUNCTION__)))))
);
760 edge e = find_edge (gimple_bb (stmt), dest);
761 if (e->flags & ignored_edge_flag)
762 continue;
763
764 int_range_max r;
765 if (!ranger->gori ().outgoing_edge_range_p (r, e, idx,
766 *get_global_range_query ()))
767 continue;
768 r.intersect (path_range);
769 if (r.undefined_p ())
770 ignored_edges->add (e);
771 else
772 {
773 if (!single_edge)
774 {
775 single_edge = e;
776 result = CASE_LOW (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 776, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 776, __FUNCTION__)))))
;
777 }
778 else if (single_edge != e)
779 result = NULLnullptr;
780 }
781 }
782
783 /* Only one edge from the switch is alive. */
784 if (single_edge && result)
785 return result;
786 }
787
788 return NULL_TREE(tree) nullptr;
789}
790
791/* Simplify LOOP based on PREDICATE_PATH where dead edges are properly
792 marked. */
793
794static bool
795simplify_loop_version (class loop *loop, predicate_vector &predicate_path,
796 int ignored_edge_flag, bitmap handled)
797{
798 bool changed = false;
799 basic_block *bbs = get_loop_body (loop);
800
801 hash_set<edge> ignored_edges;
802 for (unsigned i = 0; i != loop->num_nodes; i++)
803 {
804 vec<unswitch_predicate *> &predicates = get_predicates_for_bb (bbs[i]);
805 if (predicates.is_empty ())
806 continue;
807
808 gimple *stmt = last_stmt (bbs[i]);
809 tree folded = evaluate_control_stmt_using_entry_checks (stmt,
810 predicate_path,
811 ignored_edge_flag,
812 &ignored_edges);
813
814 if (gcond *cond = dyn_cast<gcond *> (stmt))
815 {
816 if (folded)
817 {
818 /* Remove path. */
819 if (integer_nonzerop (folded))
820 gimple_cond_set_condition_from_tree (cond, boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]);
821 else
822 gimple_cond_set_condition_from_tree (cond, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]);
823
824 gcc_assert (predicates.length () == 1)((void)(!(predicates.length () == 1) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 824, __FUNCTION__), 0 : 0))
;
825 bitmap_set_bit (handled, predicates[0]->num);
826
827 update_stmt (cond);
828 changed = true;
829 }
830 }
831 else if (gswitch *swtch = dyn_cast<gswitch *> (stmt))
832 {
833 edge e;
834 edge_iterator ei;
835 FOR_EACH_EDGE (e, ei, bbs[i]->succs)for ((ei) = ei_start_1 (&((bbs[i]->succs))); ei_cond (
(ei), &(e)); ei_next (&(ei)))
836 if (ignored_edges.contains (e))
837 e->flags |= ignored_edge_flag;
838
839 for (unsigned j = 0; j < predicates.length (); j++)
840 {
841 edge e = EDGE_SUCC (bbs[i], predicates[j]->edge_index)(*(bbs[i])->succs)[(predicates[j]->edge_index)];
842 if (ignored_edges.contains (e))
843 bitmap_set_bit (handled, predicates[j]->num);
844 }
845
846 if (folded)
847 {
848 gimple_switch_set_index (swtch, folded);
849 update_stmt (swtch);
850 changed = true;
851 }
852 }
853 }
854
855 free (bbs);
856 return changed;
857}
858
859/* Evaluate reachable blocks in LOOP and call VISIT on them, aborting the
860 DFS walk if VISIT returns true. When PREDICATE_PATH is specified then
861 take into account that when computing reachability, otherwise just
862 look at the simplified state and IGNORED_EDGE_FLAG. */
863
864template <typename VisitOp>
865static void
866evaluate_bbs (class loop *loop, predicate_vector *predicate_path,
867 int ignored_edge_flag, VisitOp visit)
868{
869 auto_bb_flag reachable_flag (cfun(cfun + 0));
870 auto_vec<basic_block, 10> worklist (loop->num_nodes);
871 auto_vec<basic_block, 10> reachable (loop->num_nodes);
872 hash_set<edge> ignored_edges;
873
874 loop->header->flags |= reachable_flag;
875 worklist.quick_push (loop->header);
876 reachable.safe_push (loop->header);
877
878 while (!worklist.is_empty ())
879 {
880 edge e;
881 edge_iterator ei;
882 int flags = ignored_edge_flag;
883 basic_block bb = worklist.pop ();
884
885 if (visit (bb))
886 break;
887
888 gimple *last = last_stmt (bb);
889 if (gcond *cond = safe_dyn_cast <gcond *> (last))
890 {
891 if (gimple_cond_true_p (cond))
892 flags = EDGE_FALSE_VALUE;
893 else if (gimple_cond_false_p (cond))
894 flags = EDGE_TRUE_VALUE;
895 else if (predicate_path)
896 {
897 tree res;
898 if (!get_predicates_for_bb (bb).is_empty ()
899 && (res = evaluate_control_stmt_using_entry_checks
900 (cond, *predicate_path, ignored_edge_flag,
901 &ignored_edges)))
902 flags = (integer_nonzerop (res)
903 ? EDGE_FALSE_VALUE : EDGE_TRUE_VALUE);
904 }
905 }
906 else if (gswitch *swtch = safe_dyn_cast<gswitch *> (last))
907 if (predicate_path
908 && !get_predicates_for_bb (bb).is_empty ())
909 evaluate_control_stmt_using_entry_checks (swtch, *predicate_path,
910 ignored_edge_flag,
911 &ignored_edges);
912
913 /* Note that for the moment we do not account reachable conditions
914 which are simplified to take a known edge as zero size nor
915 are we accounting for the required addition of the versioning
916 condition. Those should cancel out conservatively. */
917
918 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
919 {
920 basic_block dest = e->dest;
921
922 if (flow_bb_inside_loop_p (loop, dest)
923 && !(dest->flags & reachable_flag)
924 && !(e->flags & flags)
925 && !ignored_edges.contains (e))
926 {
927 dest->flags |= reachable_flag;
928 worklist.safe_push (dest);
929 reachable.safe_push (dest);
930 }
931 }
932 }
933
934 /* Clear the flag from basic blocks. */
935 while (!reachable.is_empty ())
936 reachable.pop ()->flags &= ~reachable_flag;
937}
938
939/* Evaluate how many instruction will we have if we unswitch LOOP (with BBS)
940 based on PREDICATE predicate (using PREDICATE_PATH). Store the
941 result in TRUE_SIZE and FALSE_SIZE. */
942
943static void
944evaluate_loop_insns_for_predicate (class loop *loop,
945 predicate_vector &predicate_path,
946 unswitch_predicate *predicate,
947 int ignored_edge_flag,
948 unsigned *true_size, unsigned *false_size)
949{
950 unsigned size = 0;
951 auto sum_size = [&](basic_block bb) -> bool
952 { size += (uintptr_t)bb->aux; return false; };
953
954 add_predicate_to_path (predicate_path, predicate, true);
955 evaluate_bbs (loop, &predicate_path, ignored_edge_flag, sum_size);
956 predicate_path.pop ();
957 unsigned true_loop_cost = size;
958
959 size = 0;
960 add_predicate_to_path (predicate_path, predicate, false);
961 evaluate_bbs (loop, &predicate_path, ignored_edge_flag, sum_size);
962 predicate_path.pop ();
963 unsigned false_loop_cost = size;
964
965 *true_size = true_loop_cost;
966 *false_size = false_loop_cost;
967}
968
969/* Unswitch single LOOP. PREDICATE_PATH contains so far used predicates
970 for unswitching. BUDGET is number of instruction for which we can increase
971 the loop and is updated when unswitching occurs. If HOTTEST is not
972 NULL then pick this candidate as the one to unswitch on. */
973
974static bool
975tree_unswitch_single_loop (class loop *loop, dump_user_location_t loc,
976 predicate_vector &predicate_path,
977 unsigned loop_size, unsigned &budget,
978 int ignored_edge_flag, bitmap handled,
979 unswitch_predicate *hottest, basic_block hottest_bb)
980{
981 class loop *nloop;
982 bool changed = false;
983 unswitch_predicate *predicate = NULLnullptr;
984 basic_block predicate_bb = NULLnullptr;
985 unsigned true_size = 0, false_size = 0;
986
987 auto check_predicates = [&](basic_block bb) -> bool
988 {
989 for (auto pred : get_predicates_for_bb (bb))
990 {
991 if (bitmap_bit_p (handled, pred->num))
992 continue;
993
994 evaluate_loop_insns_for_predicate (loop, predicate_path,
995 pred, ignored_edge_flag,
996 &true_size, &false_size);
997
998 /* We'll get LOOP replaced with a simplified version according
999 to PRED estimated to TRUE_SIZE and a copy simplified
1000 according to the inverted PRED estimated to FALSE_SIZE. */
1001 if (true_size + false_size < budget + loop_size)
1002 {
1003 predicate = pred;
1004 predicate_bb = bb;
1005
1006 /* There are cases where true_size and false_size add up to
1007 less than the original loop_size. We do not want to
1008 grow the remaining budget because of that. */
1009 if (true_size + false_size > loop_size)
1010 budget -= (true_size + false_size - loop_size);
1011
1012 /* FIXME: right now we select first candidate, but we can
1013 choose the cheapest or hottest one. */
1014 return true;
1015 }
1016 else if (dump_enabled_p ())
1017 dump_printf_loc (MSG_NOTE, loc,
1018 "not unswitching condition, cost too big "
1019 "(%u insns copied to %u and %u)\n", loop_size,
1020 true_size, false_size);
1021 }
1022 return false;
1023 };
1024
1025 if (hottest)
1026 {
1027 predicate = hottest;
1028 predicate_bb = hottest_bb;
1029 }
1030 else
1031 /* Check predicates of reachable blocks. */
1032 evaluate_bbs (loop, NULLnullptr, ignored_edge_flag, check_predicates);
1033
1034 if (predicate != NULLnullptr)
1035 {
1036 if (!dbg_cnt (loop_unswitch))
1037 goto exit;
1038
1039 if (dump_enabled_p ())
1040 {
1041 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
1042 "unswitching %sloop %d on %qs with condition: %T\n",
1043 loop->inner ? "outer " : "",
1044 loop->num, predicate->switch_p ? "switch" : "if",
1045 predicate->condition);
1046 dump_printf_loc (MSG_NOTE, loc,
1047 "optimized sizes estimated to %u (true) "
1048 "and %u (false) from original size %u\n",
1049 true_size, false_size, loop_size);
1050 }
1051
1052 bitmap_set_bit (handled, predicate->num);
1053 initialize_original_copy_tables ();
1054 /* Unswitch the loop on this condition. */
1055 nloop = tree_unswitch_loop (loop, EDGE_SUCC (predicate_bb,(*(predicate_bb)->succs)[(predicate->edge_index)]
1056 predicate->edge_index)(*(predicate_bb)->succs)[(predicate->edge_index)],
1057 predicate->condition);
1058 if (!nloop)
1059 {
1060 free_original_copy_tables ();
1061 goto exit;
1062 }
1063
1064 /* Copy BB costs. */
1065 basic_block *bbs2 = get_loop_body (nloop);
1066 for (unsigned i = 0; i < nloop->num_nodes; i++)
1067 bbs2[i]->aux = get_bb_original (bbs2[i])->aux;
1068 free (bbs2);
1069
1070 free_original_copy_tables ();
1071
1072 /* Update the SSA form after unswitching. */
1073 update_ssa (TODO_update_ssa_no_phi(1 << 12));
1074
1075 /* Invoke itself on modified loops. */
1076 bitmap handled_copy = BITMAP_ALLOCbitmap_alloc (NULLnullptr);
1077 bitmap_copy (handled_copy, handled);
1078 add_predicate_to_path (predicate_path, predicate, false);
1079 changed |= simplify_loop_version (nloop, predicate_path,
1080 ignored_edge_flag, handled_copy);
1081 tree_unswitch_single_loop (nloop, loc, predicate_path,
1082 false_size, budget,
1083 ignored_edge_flag, handled_copy);
1084 predicate_path.pop ();
1085 BITMAP_FREE (handled_copy)((void) (bitmap_obstack_free ((bitmap) handled_copy), (handled_copy
) = (bitmap) nullptr))
;
1086
1087 /* FIXME: After unwinding above we have to reset all ->handled
1088 flags as otherwise we fail to realize unswitching opportunities
1089 in the below recursion. See gcc.dg/loop-unswitch-16.c */
1090 add_predicate_to_path (predicate_path, predicate, true);
1091 changed |= simplify_loop_version (loop, predicate_path,
Value stored to 'changed' is never read
1092 ignored_edge_flag, handled);
1093 tree_unswitch_single_loop (loop, loc, predicate_path,
1094 true_size, budget,
1095 ignored_edge_flag, handled);
1096 predicate_path.pop ();
1097 changed = true;
1098 }
1099
1100exit:
1101 return changed;
1102}
1103
1104/* Unswitch a LOOP w.r. to given EDGE_TRUE. We only support unswitching of
1105 innermost loops. COND is the condition determining which loop is entered;
1106 the new loop is entered if COND is true. Returns NULL if impossible, new
1107 loop otherwise. */
1108
1109static class loop *
1110tree_unswitch_loop (class loop *loop, edge edge_true, tree cond)
1111{
1112 /* Some sanity checking. */
1113 gcc_assert (flow_bb_inside_loop_p (loop, edge_true->src))((void)(!(flow_bb_inside_loop_p (loop, edge_true->src)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1113, __FUNCTION__), 0 : 0))
;
1114 gcc_assert (EDGE_COUNT (edge_true->src->succs) >= 2)((void)(!(vec_safe_length (edge_true->src->succs) >=
2) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1114, __FUNCTION__), 0 : 0))
;
1115
1116 profile_probability prob_true = edge_true->probability;
1117 return loop_version (loop, unshare_expr (cond),
1118 NULLnullptr, prob_true,
1119 prob_true.invert (),
1120 prob_true, prob_true.invert (),
1121 false);
1122}
1123
1124/* Unswitch outer loops by hoisting invariant guard on
1125 inner loop without code duplication. */
1126static bool
1127tree_unswitch_outer_loop (class loop *loop)
1128{
1129 edge exit, guard;
1130 HOST_WIDE_INTlong iterations;
1131
1132 gcc_assert (loop->inner)((void)(!(loop->inner) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1132, __FUNCTION__), 0 : 0))
;
1133 if (loop->inner->next)
1134 return false;
1135 /* Accept loops with single exit only which is not from inner loop. */
1136 exit = single_exit (loop);
1137 if (!exit || exit->src->loop_father != loop)
1138 return false;
1139 /* Check that phi argument of exit edge is not defined inside loop. */
1140 if (!check_exit_phi (loop))
1141 return false;
1142 /* If the loop is not expected to iterate, there is no need
1143 for unswitching. */
1144 iterations = estimated_loop_iterations_int (loop);
1145 if (iterations < 0)
1146 iterations = likely_max_loop_iterations_int (loop);
1147 if (iterations >= 0 && iterations <= 1)
1148 {
1149 if (dump_enabled_p ())
1150 dump_printf_loc (MSG_MISSED_OPTIMIZATION, find_loop_location (loop),
1151 "Not unswitching, loop is not expected"
1152 " to iterate\n");
1153 return false;
1154 }
1155
1156 bool changed = false;
1157 auto_vec<gimple *> dbg_to_reset;
1158 while ((guard = find_loop_guard (loop, dbg_to_reset)))
1159 {
1160 hoist_guard (loop, guard);
1161 for (gimple *debug_stmt : dbg_to_reset)
1162 {
1163 gimple_debug_bind_reset_value (debug_stmt);
1164 update_stmt (debug_stmt);
1165 }
1166 dbg_to_reset.truncate (0);
1167 changed = true;
1168 }
1169 return changed;
1170}
1171
1172/* Checks if the body of the LOOP is within an invariant guard. If this
1173 is the case, returns the edge that jumps over the real body of the loop,
1174 otherwise returns NULL. */
1175
1176static edge
1177find_loop_guard (class loop *loop, vec<gimple *> &dbg_to_reset)
1178{
1179 basic_block header = loop->header;
1180 edge guard_edge, te, fe;
1181 basic_block *body = NULLnullptr;
1182 unsigned i;
1183 tree use;
1184 ssa_op_iter iter;
1185
1186 /* We check for the following situation:
1187
1188 while (1)
1189 {
1190 [header]]
1191 loop_phi_nodes;
1192 something1;
1193 if (cond1)
1194 body;
1195 nvar = phi(orig, bvar) ... for all variables changed in body;
1196 [guard_end]
1197 something2;
1198 if (cond2)
1199 break;
1200 something3;
1201 }
1202
1203 where:
1204
1205 1) cond1 is loop invariant
1206 2) If cond1 is false, then the loop is essentially empty; i.e.,
1207 a) nothing in something1, something2 and something3 has side
1208 effects
1209 b) anything defined in something1, something2 and something3
1210 is not used outside of the loop. */
1211
1212 gcond *cond;
1213 do
1214 {
1215 basic_block next = NULLnullptr;
1216 if (single_succ_p (header))
1217 next = single_succ (header);
1218 else
1219 {
1220 cond = safe_dyn_cast <gcond *> (last_stmt (header));
1221 if (! cond)
1222 return NULLnullptr;
1223 extract_true_false_edges_from_block (header, &te, &fe);
1224 /* Make sure to skip earlier hoisted guards that are left
1225 in place as if (true). */
1226 if (gimple_cond_true_p (cond))
1227 next = te->dest;
1228 else if (gimple_cond_false_p (cond))
1229 next = fe->dest;
1230 else
1231 break;
1232 }
1233 /* Never traverse a backedge. */
1234 if (header->loop_father->header == next)
1235 return NULLnullptr;
1236 header = next;
1237 }
1238 while (1);
1239 if (!flow_bb_inside_loop_p (loop, te->dest)
1240 || !flow_bb_inside_loop_p (loop, fe->dest))
1241 return NULLnullptr;
1242
1243 if (just_once_each_iteration_p (loop, te->dest)
1244 || (single_succ_p (te->dest)
1245 && just_once_each_iteration_p (loop, single_succ (te->dest))))
1246 {
1247 if (just_once_each_iteration_p (loop, fe->dest))
1248 return NULLnullptr;
1249 guard_edge = te;
1250 }
1251 else if (just_once_each_iteration_p (loop, fe->dest)
1252 || (single_succ_p (fe->dest)
1253 && just_once_each_iteration_p (loop, single_succ (fe->dest))))
1254 guard_edge = fe;
1255 else
1256 return NULLnullptr;
1257
1258 dump_user_location_t loc = find_loop_location (loop);
1259
1260 /* Guard edge must skip inner loop. */
1261 if (!dominated_by_p (CDI_DOMINATORS, loop->inner->header,
1262 guard_edge == fe ? te->dest : fe->dest))
1263 {
1264 if (dump_enabled_p ())
1265 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
1266 "Guard edge %d --> %d is not around the loop!\n",
1267 guard_edge->src->index, guard_edge->dest->index);
1268 return NULLnullptr;
1269 }
1270 if (guard_edge->dest == loop->latch)
1271 {
1272 if (dump_enabled_p ())
1273 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
1274 "Guard edge destination is loop latch.\n");
1275 return NULLnullptr;
1276 }
1277
1278 if (dump_enabled_p ())
1279 dump_printf_loc (MSG_NOTE, loc,
1280 "Considering guard %d -> %d in loop %d\n",
1281 guard_edge->src->index, guard_edge->dest->index,
1282 loop->num);
1283 /* Check if condition operands do not have definitions inside loop since
1284 any bb copying is not performed. */
1285 FOR_EACH_SSA_TREE_OPERAND (use, cond, iter, SSA_OP_USE)for (use = op_iter_init_tree (&(iter), cond, 0x01); !op_iter_done
(&(iter)); (void) (use = op_iter_next_tree (&(iter))
))
1286 {
1287 gimple *def = SSA_NAME_DEF_STMT (use)(tree_check ((use), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1287, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1288 basic_block def_bb = gimple_bb (def);
1289 if (def_bb
1290 && flow_bb_inside_loop_p (loop, def_bb))
1291 {
1292 if (dump_enabled_p ())
1293 dump_printf_loc (MSG_NOTE, loc, "guard operands have definitions"
1294 " inside loop\n");
1295 return NULLnullptr;
1296 }
1297 }
1298
1299 body = get_loop_body (loop);
1300 for (i = 0; i < loop->num_nodes; i++)
1301 {
1302 basic_block bb = body[i];
1303 if (bb->loop_father != loop)
1304 continue;
1305 if (bb->flags & BB_IRREDUCIBLE_LOOP)
1306 {
1307 if (dump_enabled_p ())
1308 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
1309 "Block %d is marked as irreducible in loop\n",
1310 bb->index);
1311 guard_edge = NULLnullptr;
1312 goto end;
1313 }
1314 if (!empty_bb_without_guard_p (loop, bb, dbg_to_reset))
1315 {
1316 if (dump_enabled_p ())
1317 dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc,
1318 "Block %d has side effects\n", bb->index);
1319 guard_edge = NULLnullptr;
1320 goto end;
1321 }
1322 }
1323
1324 if (dump_enabled_p ())
1325 dump_printf_loc (MSG_NOTE, loc,
1326 "suitable to hoist\n");
1327end:
1328 if (body)
1329 free (body);
1330 return guard_edge;
1331}
1332
1333/* Returns true if
1334 1) no statement in BB has side effects
1335 2) assuming that edge GUARD is always taken, all definitions in BB
1336 are noy used outside of the loop.
1337 KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and
1338 PROCESSED is a set of ssa names for that we already tested whether they
1339 are invariant or not. Uses in debug stmts outside of the loop are
1340 pushed to DBG_TO_RESET. */
1341
1342static bool
1343empty_bb_without_guard_p (class loop *loop, basic_block bb,
1344 vec<gimple *> &dbg_to_reset)
1345{
1346 basic_block exit_bb = single_exit (loop)->src;
1347 bool may_be_used_outside = (bb == exit_bb
1348 || !dominated_by_p (CDI_DOMINATORS, bb, exit_bb));
1349 tree name;
1350 ssa_op_iter op_iter;
1351
1352 /* Phi nodes do not have side effects, but their results might be used
1353 outside of the loop. */
1354 if (may_be_used_outside)
1355 {
1356 for (gphi_iterator gsi = gsi_start_phis (bb);
1357 !gsi_end_p (gsi); gsi_next (&gsi))
1358 {
1359 gphi *phi = gsi.phi ();
1360 name = PHI_RESULT (phi)get_def_from_ptr (gimple_phi_result_ptr (phi));
1361 if (virtual_operand_p (name))
1362 continue;
1363
1364 if (used_outside_loop_p (loop, name, dbg_to_reset))
1365 return false;
1366 }
1367 }
1368
1369 for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
1370 !gsi_end_p (gsi); gsi_next (&gsi))
1371 {
1372 gimple *stmt = gsi_stmt (gsi);
1373 if (is_gimple_debug (stmt))
1374 continue;
1375
1376 if (gimple_has_side_effects (stmt))
1377 return false;
1378
1379 if (gimple_vdef(stmt))
1380 return false;
1381
1382 FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF)for (name = op_iter_init_tree (&(op_iter), stmt, 0x02); !
op_iter_done (&(op_iter)); (void) (name = op_iter_next_tree
(&(op_iter))))
1383 {
1384 if (may_be_used_outside
1385 && used_outside_loop_p (loop, name, dbg_to_reset))
1386 return false;
1387 }
1388 }
1389 return true;
1390}
1391
1392/* Return true if NAME is used outside of LOOP. Pushes debug stmts that
1393 have such uses to DBG_TO_RESET but do not consider such uses. */
1394
1395static bool
1396used_outside_loop_p (class loop *loop, tree name, vec<gimple *> &dbg_to_reset)
1397{
1398 imm_use_iterator it;
1399 use_operand_p use;
1400
1401 FOR_EACH_IMM_USE_FAST (use, it, name)for ((use) = first_readonly_imm_use (&(it), (name)); !end_readonly_imm_use_p
(&(it)); (void) ((use) = next_readonly_imm_use (&(it
))))
1402 {
1403 gimple *stmt = USE_STMT (use)(use)->loc.stmt;
1404 if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
1405 {
1406 if (!is_gimple_debug (stmt))
1407 return true;
1408 dbg_to_reset.safe_push (stmt);
1409 }
1410 }
1411
1412 return false;
1413}
1414
1415/* Return argument for loop preheader edge in header virtual phi if any. */
1416
1417static tree
1418get_vop_from_header (class loop *loop)
1419{
1420 for (gphi_iterator gsi = gsi_start_phis (loop->header);
1421 !gsi_end_p (gsi); gsi_next (&gsi))
1422 {
1423 gphi *phi = gsi.phi ();
1424 if (!virtual_operand_p (gimple_phi_result (phi)))
1425 continue;
1426 return PHI_ARG_DEF_FROM_EDGE (phi, loop_preheader_edge (loop))gimple_phi_arg_def (((phi)), ((loop_preheader_edge (loop))->
dest_idx))
;
1427 }
1428 return NULL_TREE(tree) nullptr;
1429}
1430
1431/* Move the check of GUARD outside of LOOP. */
1432
1433static void
1434hoist_guard (class loop *loop, edge guard)
1435{
1436 edge exit = single_exit (loop);
1437 edge preh = loop_preheader_edge (loop);
1438 basic_block pre_header = preh->src;
1439 basic_block bb;
1440 edge te, fe, e, new_edge;
1441 gimple *stmt;
1442 basic_block guard_bb = guard->src;
1443 edge not_guard;
1444 gimple_stmt_iterator gsi;
1445 int flags = 0;
1446 bool fix_dom_of_exit;
1447 gcond *cond_stmt, *new_cond_stmt;
1448
1449 bb = get_immediate_dominator (CDI_DOMINATORS, exit->dest);
1450 fix_dom_of_exit = flow_bb_inside_loop_p (loop, bb);
1451 gsi = gsi_last_bb (guard_bb);
1452 stmt = gsi_stmt (gsi);
1453 gcc_assert (gimple_code (stmt) == GIMPLE_COND)((void)(!(gimple_code (stmt) == GIMPLE_COND) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1453, __FUNCTION__), 0 : 0))
;
1454 cond_stmt = as_a <gcond *> (stmt);
1455 extract_true_false_edges_from_block (guard_bb, &te, &fe);
1456 /* Insert guard to PRE_HEADER. */
1457 if (!empty_block_p (pre_header))
1458 gsi = gsi_last_bb (pre_header);
1459 else
1460 gsi = gsi_start_bb (pre_header);
1461 /* Create copy of COND_STMT. */
1462 new_cond_stmt = gimple_build_cond (gimple_cond_code (cond_stmt),
1463 gimple_cond_lhs (cond_stmt),
1464 gimple_cond_rhs (cond_stmt),
1465 NULL_TREE(tree) nullptr, NULL_TREE(tree) nullptr);
1466 gsi_insert_after (&gsi, new_cond_stmt, GSI_NEW_STMT);
1467 /* Convert COND_STMT to true/false conditional. */
1468 if (guard == te)
1469 gimple_cond_make_false (cond_stmt);
1470 else
1471 gimple_cond_make_true (cond_stmt);
1472 update_stmt (cond_stmt);
1473 /* Create new loop pre-header. */
1474 e = split_block (pre_header, last_stmt (pre_header));
1475
1476 dump_user_location_t loc = find_loop_location (loop);
1477
1478 if (dump_enabled_p ())
1479 {
1480 char buffer[64];
1481 guard->probability.dump (buffer);
1482
1483 dump_printf_loc (MSG_NOTE, loc,
1484 "Moving guard %i->%i (prob %s) to bb %i, "
1485 "new preheader is %i\n",
1486 guard->src->index, guard->dest->index,
1487 buffer, e->src->index, e->dest->index);
1488 }
1489
1490 gcc_assert (loop_preheader_edge (loop)->src == e->dest)((void)(!(loop_preheader_edge (loop)->src == e->dest) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1490, __FUNCTION__), 0 : 0))
;
1491
1492 if (guard == fe)
1493 {
1494 e->flags = EDGE_TRUE_VALUE;
1495 flags |= EDGE_FALSE_VALUE;
1496 not_guard = te;
1497 }
1498 else
1499 {
1500 e->flags = EDGE_FALSE_VALUE;
1501 flags |= EDGE_TRUE_VALUE;
1502 not_guard = fe;
1503 }
1504 new_edge = make_edge (pre_header, exit->dest, flags);
1505
1506 /* Determine the probability that we skip the loop. Assume that loop has
1507 same average number of iterations regardless outcome of guard. */
1508 new_edge->probability = guard->probability;
1509 profile_count skip_count = guard->src->count.nonzero_p ()
1510 ? guard->count ().apply_scale (pre_header->count,
1511 guard->src->count)
1512 : guard->count ().apply_probability (new_edge->probability);
1513
1514 if (skip_count > e->count ())
1515 {
1516 fprintf (dump_file, " Capping count; expect profile inconsistency\n");
1517 skip_count = e->count ();
1518 }
1519 if (dump_enabled_p ())
1520 {
1521 char buffer[64];
1522 new_edge->probability.dump (buffer);
1523
1524 dump_printf_loc (MSG_NOTE, loc,
1525 "Estimated probability of skipping loop is %s\n",
1526 buffer);
1527 }
1528
1529 /* Update profile after the transform:
1530
1531 First decrease count of path from newly hoisted loop guard
1532 to loop header... */
1533 e->probability = new_edge->probability.invert ();
1534 e->dest->count = e->count ();
1535
1536 /* ... now update profile to represent that original guard will be optimized
1537 away ... */
1538 guard->probability = profile_probability::never ();
1539 not_guard->probability = profile_probability::always ();
1540
1541 /* ... finally scale everything in the loop except for guarded basic blocks
1542 where profile does not change. */
1543 basic_block *body = get_loop_body (loop);
1544
1545 for (unsigned int i = 0; i < loop->num_nodes; i++)
1546 {
1547 basic_block bb = body[i];
1548 if (!dominated_by_p (CDI_DOMINATORS, bb, not_guard->dest))
1549 {
1550 if (dump_enabled_p ())
1551 dump_printf_loc (MSG_NOTE, loc,
1552 "Scaling nonguarded BBs in loop: %i\n",
1553 bb->index);
1554 if (e->probability.initialized_p ())
1555 scale_bbs_frequencies (&bb, 1, e->probability);
1556 }
1557 }
1558
1559 if (fix_dom_of_exit)
1560 set_immediate_dominator (CDI_DOMINATORS, exit->dest, pre_header);
1561 /* Add NEW_ADGE argument for all phi in post-header block. */
1562 bb = exit->dest;
1563 for (gphi_iterator gsi = gsi_start_phis (bb);
1564 !gsi_end_p (gsi); gsi_next (&gsi))
1565 {
1566 gphi *phi = gsi.phi ();
1567 tree arg;
1568 if (virtual_operand_p (gimple_phi_result (phi)))
1569 {
1570 arg = get_vop_from_header (loop);
1571 if (arg == NULL_TREE(tree) nullptr)
1572 /* Use exit edge argument. */
1573 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit)gimple_phi_arg_def (((phi)), ((exit)->dest_idx));
1574 add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION((location_t) 0));
1575 }
1576 else
1577 {
1578 /* Use exit edge argument. */
1579 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit)gimple_phi_arg_def (((phi)), ((exit)->dest_idx));
1580 add_phi_arg (phi, arg, new_edge, UNKNOWN_LOCATION((location_t) 0));
1581 }
1582 }
1583
1584 if (dump_enabled_p ())
1585 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc,
1586 "Guard hoisted\n");
1587
1588 free (body);
1589}
1590
1591/* Return true if phi argument for exit edge can be used
1592 for edge around loop. */
1593
1594static bool
1595check_exit_phi (class loop *loop)
1596{
1597 edge exit = single_exit (loop);
1598 basic_block pre_header = loop_preheader_edge (loop)->src;
1599
1600 for (gphi_iterator gsi = gsi_start_phis (exit->dest);
1601 !gsi_end_p (gsi); gsi_next (&gsi))
1602 {
1603 gphi *phi = gsi.phi ();
1604 tree arg;
1605 gimple *def;
1606 basic_block def_bb;
1607 if (virtual_operand_p (gimple_phi_result (phi)))
1608 continue;
1609 arg = PHI_ARG_DEF_FROM_EDGE (phi, exit)gimple_phi_arg_def (((phi)), ((exit)->dest_idx));
1610 if (TREE_CODE (arg)((enum tree_code) (arg)->base.code) != SSA_NAME)
1611 continue;
1612 def = SSA_NAME_DEF_STMT (arg)(tree_check ((arg), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1612, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1613 if (!def)
1614 continue;
1615 def_bb = gimple_bb (def);
1616 if (!def_bb)
1617 continue;
1618 if (!dominated_by_p (CDI_DOMINATORS, pre_header, def_bb))
1619 /* Definition inside loop! */
1620 return false;
1621 /* Check loop closed phi invariant. */
1622 if (!flow_bb_inside_loop_p (def_bb->loop_father, pre_header))
1623 return false;
1624 }
1625 return true;
1626}
1627
1628/* Remove all dead cases from switches that are unswitched. */
1629
1630static void
1631clean_up_after_unswitching (int ignored_edge_flag)
1632{
1633 basic_block bb;
1634 edge e;
1635 edge_iterator ei;
1636 bool removed_edge = false;
1637
1638 FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb
; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb->
next_bb)
1639 {
1640 gswitch *stmt= safe_dyn_cast <gswitch *> (last_stmt (bb));
1641 if (stmt && !CONSTANT_CLASS_P (gimple_switch_index (stmt))(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code
) (gimple_switch_index (stmt))->base.code))] == tcc_constant
)
)
1642 {
1643 unsigned nlabels = gimple_switch_num_labels (stmt);
1644 unsigned index = 1;
1645 tree lab = gimple_switch_default_label (stmt);
1646 edge default_e = find_edge (gimple_bb (stmt),
1647 label_to_block (cfun(cfun + 0), CASE_LABEL (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1647, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1647, __FUNCTION__)))))
));
1648 for (unsigned i = 1; i < nlabels; ++i)
1649 {
1650 tree lab = gimple_switch_label (stmt, i);
1651 basic_block dest = label_to_block (cfun(cfun + 0), CASE_LABEL (lab)(*((const_cast<tree*> (tree_operand_check (((tree_check
((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1651, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-ssa-loop-unswitch.cc"
, 1651, __FUNCTION__)))))
);
1652 edge e = find_edge (gimple_bb (stmt), dest);
1653 if (e == NULLnullptr)
1654 ; /* The edge is already removed. */
1655 else if (e->flags & ignored_edge_flag)
1656 {
1657 /* We may not remove the default label so we also have
1658 to preserve its edge. But we can remove the
1659 non-default CASE sharing the edge. */
1660 if (e != default_e)
1661 {
1662 remove_edge (e);
1663 removed_edge = true;
1664 }
1665 }
1666 else
1667 {
1668 gimple_switch_set_label (stmt, index, lab);
1669 ++index;
1670 }
1671 }
1672
1673 if (index != nlabels)
1674 gimple_switch_set_num_labels (stmt, index);
1675 }
1676
1677 /* Clean up the ignored_edge_flag from edges. */
1678 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
1679 e->flags &= ~ignored_edge_flag;
1680 }
1681
1682 /* If we removed an edge we possibly have to recompute dominators. */
1683 if (removed_edge)
1684 free_dominance_info (CDI_DOMINATORS);
1685}
1686
1687/* Loop unswitching pass. */
1688
1689namespace {
1690
1691const pass_data pass_data_tree_unswitch =
1692{
1693 GIMPLE_PASS, /* type */
1694 "unswitch", /* name */
1695 OPTGROUP_LOOP, /* optinfo_flags */
1696 TV_TREE_LOOP_UNSWITCH, /* tv_id */
1697 PROP_cfg(1 << 3), /* properties_required */
1698 0, /* properties_provided */
1699 0, /* properties_destroyed */
1700 0, /* todo_flags_start */
1701 0, /* todo_flags_finish */
1702};
1703
1704class pass_tree_unswitch : public gimple_opt_pass
1705{
1706public:
1707 pass_tree_unswitch (gcc::context *ctxt)
1708 : gimple_opt_pass (pass_data_tree_unswitch, ctxt)
1709 {}
1710
1711 /* opt_pass methods: */
1712 bool gate (function *) final override { return flag_unswitch_loopsglobal_options.x_flag_unswitch_loops != 0; }
1713 unsigned int execute (function *) final override;
1714
1715}; // class pass_tree_unswitch
1716
1717unsigned int
1718pass_tree_unswitch::execute (function *fun)
1719{
1720 if (number_of_loops (fun) <= 1)
1721 return 0;
1722
1723 return tree_ssa_unswitch_loops (fun);
1724}
1725
1726} // anon namespace
1727
1728gimple_opt_pass *
1729make_pass_tree_unswitch (gcc::context *ctxt)
1730{
1731 return new pass_tree_unswitch (ctxt);
1732}
1733
1734