Bug Summary

File:build/gcc/tree-if-conv.cc
Warning:line 2004, column 10
8th function call argument is an uninitialized value

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-if-conv.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-zinhZT.plist -x c++ /buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc
1/* If-conversion for vectorizer.
2 Copyright (C) 2004-2023 Free Software Foundation, Inc.
3 Contributed by Devang Patel <dpatel@apple.com>
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21/* This pass implements a tree level if-conversion of loops. Its
22 initial goal is to help the vectorizer to vectorize loops with
23 conditions.
24
25 A short description of if-conversion:
26
27 o Decide if a loop is if-convertible or not.
28 o Walk all loop basic blocks in breadth first order (BFS order).
29 o Remove conditional statements (at the end of basic block)
30 and propagate condition into destination basic blocks'
31 predicate list.
32 o Replace modify expression with conditional modify expression
33 using current basic block's condition.
34 o Merge all basic blocks
35 o Replace phi nodes with conditional modify expr
36 o Merge all basic blocks into header
37
38 Sample transformation:
39
40 INPUT
41 -----
42
43 # i_23 = PHI <0(0), i_18(10)>;
44 <L0>:;
45 j_15 = A[i_23];
46 if (j_15 > 41) goto <L1>; else goto <L17>;
47
48 <L17>:;
49 goto <bb 3> (<L3>);
50
51 <L1>:;
52
53 # iftmp.2_4 = PHI <0(8), 42(2)>;
54 <L3>:;
55 A[i_23] = iftmp.2_4;
56 i_18 = i_23 + 1;
57 if (i_18 <= 15) goto <L19>; else goto <L18>;
58
59 <L19>:;
60 goto <bb 1> (<L0>);
61
62 <L18>:;
63
64 OUTPUT
65 ------
66
67 # i_23 = PHI <0(0), i_18(10)>;
68 <L0>:;
69 j_15 = A[i_23];
70
71 <L3>:;
72 iftmp.2_4 = j_15 > 41 ? 42 : 0;
73 A[i_23] = iftmp.2_4;
74 i_18 = i_23 + 1;
75 if (i_18 <= 15) goto <L19>; else goto <L18>;
76
77 <L19>:;
78 goto <bb 1> (<L0>);
79
80 <L18>:;
81*/
82
83#include "config.h"
84#include "system.h"
85#include "coretypes.h"
86#include "backend.h"
87#include "rtl.h"
88#include "tree.h"
89#include "gimple.h"
90#include "cfghooks.h"
91#include "tree-pass.h"
92#include "ssa.h"
93#include "expmed.h"
94#include "expr.h"
95#include "optabs-query.h"
96#include "gimple-pretty-print.h"
97#include "alias.h"
98#include "fold-const.h"
99#include "stor-layout.h"
100#include "gimple-iterator.h"
101#include "gimple-fold.h"
102#include "gimplify.h"
103#include "gimplify-me.h"
104#include "tree-cfg.h"
105#include "tree-into-ssa.h"
106#include "tree-ssa.h"
107#include "cfgloop.h"
108#include "tree-data-ref.h"
109#include "tree-scalar-evolution.h"
110#include "tree-ssa-loop.h"
111#include "tree-ssa-loop-niter.h"
112#include "tree-ssa-loop-ivopts.h"
113#include "tree-ssa-address.h"
114#include "dbgcnt.h"
115#include "tree-hash-traits.h"
116#include "varasm.h"
117#include "builtins.h"
118#include "cfganal.h"
119#include "internal-fn.h"
120#include "fold-const.h"
121#include "tree-ssa-sccvn.h"
122#include "tree-cfgcleanup.h"
123#include "tree-ssa-dse.h"
124#include "tree-vectorizer.h"
125#include "tree-eh.h"
126#include "cgraph.h"
127
128/* For lang_hooks.types.type_for_mode. */
129#include "langhooks.h"
130
131/* Only handle PHIs with no more arguments unless we are asked to by
132 simd pragma. */
133#define MAX_PHI_ARG_NUM((unsigned) global_options.x_param_max_tree_if_conversion_phi_args
)
\
134 ((unsigned) param_max_tree_if_conversion_phi_argsglobal_options.x_param_max_tree_if_conversion_phi_args)
135
136/* True if we've converted a statement that was only executed when some
137 condition C was true, and if for correctness we need to predicate the
138 statement to ensure that it is a no-op when C is false. See
139 predicate_statements for the kinds of predication we support. */
140static bool need_to_predicate;
141
142/* True if we have to rewrite stmts that may invoke undefined behavior
143 when a condition C was false so it doesn't if it is always executed.
144 See predicate_statements for the kinds of predication we support. */
145static bool need_to_rewrite_undefined;
146
147/* Indicate if there are any complicated PHIs that need to be handled in
148 if-conversion. Complicated PHI has more than two arguments and can't
149 be degenerated to two arguments PHI. See more information in comment
150 before phi_convertible_by_degenerating_args. */
151static bool any_complicated_phi;
152
153/* True if we have bitfield accesses we can lower. */
154static bool need_to_lower_bitfields;
155
156/* True if there is any ifcvting to be done. */
157static bool need_to_ifcvt;
158
159/* Hash for struct innermost_loop_behavior. It depends on the user to
160 free the memory. */
161
162struct innermost_loop_behavior_hash : nofree_ptr_hash <innermost_loop_behavior>
163{
164 static inline hashval_t hash (const value_type &);
165 static inline bool equal (const value_type &,
166 const compare_type &);
167};
168
169inline hashval_t
170innermost_loop_behavior_hash::hash (const value_type &e)
171{
172 hashval_t hash;
173
174 hash = iterative_hash_expr (e->base_address, 0);
175 hash = iterative_hash_expr (e->offset, hash);
176 hash = iterative_hash_expr (e->init, hash);
177 return iterative_hash_expr (e->step, hash);
178}
179
180inline bool
181innermost_loop_behavior_hash::equal (const value_type &e1,
182 const compare_type &e2)
183{
184 if ((e1->base_address && !e2->base_address)
185 || (!e1->base_address && e2->base_address)
186 || (!e1->offset && e2->offset)
187 || (e1->offset && !e2->offset)
188 || (!e1->init && e2->init)
189 || (e1->init && !e2->init)
190 || (!e1->step && e2->step)
191 || (e1->step && !e2->step))
192 return false;
193
194 if (e1->base_address && e2->base_address
195 && !operand_equal_p (e1->base_address, e2->base_address, 0))
196 return false;
197 if (e1->offset && e2->offset
198 && !operand_equal_p (e1->offset, e2->offset, 0))
199 return false;
200 if (e1->init && e2->init
201 && !operand_equal_p (e1->init, e2->init, 0))
202 return false;
203 if (e1->step && e2->step
204 && !operand_equal_p (e1->step, e2->step, 0))
205 return false;
206
207 return true;
208}
209
210/* List of basic blocks in if-conversion-suitable order. */
211static basic_block *ifc_bbs;
212
213/* Hash table to store <DR's innermost loop behavior, DR> pairs. */
214static hash_map<innermost_loop_behavior_hash,
215 data_reference_p> *innermost_DR_map;
216
217/* Hash table to store <base reference, DR> pairs. */
218static hash_map<tree_operand_hash, data_reference_p> *baseref_DR_map;
219
220/* List of redundant SSA names: the first should be replaced by the second. */
221static vec< std::pair<tree, tree> > redundant_ssa_names;
222
223/* Structure used to predicate basic blocks. This is attached to the
224 ->aux field of the BBs in the loop to be if-converted. */
225struct bb_predicate {
226
227 /* The condition under which this basic block is executed. */
228 tree predicate;
229
230 /* PREDICATE is gimplified, and the sequence of statements is
231 recorded here, in order to avoid the duplication of computations
232 that occur in previous conditions. See PR44483. */
233 gimple_seq predicate_gimplified_stmts;
234};
235
236/* Returns true when the basic block BB has a predicate. */
237
238static inline bool
239bb_has_predicate (basic_block bb)
240{
241 return bb->aux != NULLnullptr;
242}
243
244/* Returns the gimplified predicate for basic block BB. */
245
246static inline tree
247bb_predicate (basic_block bb)
248{
249 return ((struct bb_predicate *) bb->aux)->predicate;
250}
251
252/* Sets the gimplified predicate COND for basic block BB. */
253
254static inline void
255set_bb_predicate (basic_block bb, tree cond)
256{
257 gcc_assert ((TREE_CODE (cond) == TRUTH_NOT_EXPR((void)(!((((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR
&& is_gimple_val ((*((const_cast<tree*> (tree_operand_check
((cond), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 258, __FUNCTION__))))))) || is_gimple_val (cond)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 259, __FUNCTION__), 0 : 0))
258 && is_gimple_val (TREE_OPERAND (cond, 0)))((void)(!((((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR
&& is_gimple_val ((*((const_cast<tree*> (tree_operand_check
((cond), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 258, __FUNCTION__))))))) || is_gimple_val (cond)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 259, __FUNCTION__), 0 : 0))
259 || is_gimple_val (cond))((void)(!((((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR
&& is_gimple_val ((*((const_cast<tree*> (tree_operand_check
((cond), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 258, __FUNCTION__))))))) || is_gimple_val (cond)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 259, __FUNCTION__), 0 : 0))
;
260 ((struct bb_predicate *) bb->aux)->predicate = cond;
261}
262
263/* Returns the sequence of statements of the gimplification of the
264 predicate for basic block BB. */
265
266static inline gimple_seq
267bb_predicate_gimplified_stmts (basic_block bb)
268{
269 return ((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts;
270}
271
272/* Sets the sequence of statements STMTS of the gimplification of the
273 predicate for basic block BB. */
274
275static inline void
276set_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts)
277{
278 ((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts = stmts;
279}
280
281/* Adds the sequence of statements STMTS to the sequence of statements
282 of the predicate for basic block BB. */
283
284static inline void
285add_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts)
286{
287 /* We might have updated some stmts in STMTS via force_gimple_operand
288 calling fold_stmt and that producing multiple stmts. Delink immediate
289 uses so update_ssa after loop versioning doesn't get confused for
290 the not yet inserted predicates.
291 ??? This should go away once we reliably avoid updating stmts
292 not in any BB. */
293 for (gimple_stmt_iterator gsi = gsi_start (stmts);
294 !gsi_end_p (gsi); gsi_next (&gsi))
295 {
296 gimple *stmt = gsi_stmt (gsi);
297 delink_stmt_imm_use (stmt);
298 gimple_set_modified (stmt, true);
299 }
300 gimple_seq_add_seq_without_update
301 (&(((struct bb_predicate *) bb->aux)->predicate_gimplified_stmts), stmts);
302}
303
304/* Initializes to TRUE the predicate of basic block BB. */
305
306static inline void
307init_bb_predicate (basic_block bb)
308{
309 bb->aux = XNEW (struct bb_predicate)((struct bb_predicate *) xmalloc (sizeof (struct bb_predicate
)))
;
310 set_bb_predicate_gimplified_stmts (bb, NULLnullptr);
311 set_bb_predicate (bb, boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]);
312}
313
314/* Release the SSA_NAMEs associated with the predicate of basic block BB. */
315
316static inline void
317release_bb_predicate (basic_block bb)
318{
319 gimple_seq stmts = bb_predicate_gimplified_stmts (bb);
320 if (stmts)
321 {
322 /* Ensure that these stmts haven't yet been added to a bb. */
323 if (flag_checkingglobal_options.x_flag_checking)
324 for (gimple_stmt_iterator i = gsi_start (stmts);
325 !gsi_end_p (i); gsi_next (&i))
326 gcc_assert (! gimple_bb (gsi_stmt (i)))((void)(!(! gimple_bb (gsi_stmt (i))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 326, __FUNCTION__), 0 : 0))
;
327
328 /* Discard them. */
329 gimple_seq_discard (stmts);
330 set_bb_predicate_gimplified_stmts (bb, NULLnullptr);
331 }
332}
333
334/* Free the predicate of basic block BB. */
335
336static inline void
337free_bb_predicate (basic_block bb)
338{
339 if (!bb_has_predicate (bb))
340 return;
341
342 release_bb_predicate (bb);
343 free (bb->aux);
344 bb->aux = NULLnullptr;
345}
346
347/* Reinitialize predicate of BB with the true predicate. */
348
349static inline void
350reset_bb_predicate (basic_block bb)
351{
352 if (!bb_has_predicate (bb))
353 init_bb_predicate (bb);
354 else
355 {
356 release_bb_predicate (bb);
357 set_bb_predicate (bb, boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]);
358 }
359}
360
361/* Returns a new SSA_NAME of type TYPE that is assigned the value of
362 the expression EXPR. Inserts the statement created for this
363 computation before GSI and leaves the iterator GSI at the same
364 statement. */
365
366static tree
367ifc_temp_var (tree type, tree expr, gimple_stmt_iterator *gsi)
368{
369 tree new_name = make_temp_ssa_name (type, NULLnullptr, "_ifc_");
370 gimple *stmt = gimple_build_assign (new_name, expr);
371 gimple_set_vuse (stmt, gimple_vuse (gsi_stmt (*gsi)));
372 gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
373 return new_name;
374}
375
376/* Return true when COND is a false predicate. */
377
378static inline bool
379is_false_predicate (tree cond)
380{
381 return (cond != NULL_TREE(tree) nullptr
382 && (cond == boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]
383 || integer_zerop (cond)));
384}
385
386/* Return true when COND is a true predicate. */
387
388static inline bool
389is_true_predicate (tree cond)
390{
391 return (cond == NULL_TREE(tree) nullptr
392 || cond == boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE]
393 || integer_onep (cond));
394}
395
396/* Returns true when BB has a predicate that is not trivial: true or
397 NULL_TREE. */
398
399static inline bool
400is_predicated (basic_block bb)
401{
402 return !is_true_predicate (bb_predicate (bb));
403}
404
405/* Parses the predicate COND and returns its comparison code and
406 operands OP0 and OP1. */
407
408static enum tree_code
409parse_predicate (tree cond, tree *op0, tree *op1)
410{
411 gimple *s;
412
413 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == SSA_NAME
414 && is_gimple_assign (s = SSA_NAME_DEF_STMT (cond)(tree_check ((cond), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 414, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
))
415 {
416 if (TREE_CODE_CLASS (gimple_assign_rhs_code (s))tree_code_type_tmpl <0>::tree_code_type[(int) (gimple_assign_rhs_code
(s))]
== tcc_comparison)
417 {
418 *op0 = gimple_assign_rhs1 (s);
419 *op1 = gimple_assign_rhs2 (s);
420 return gimple_assign_rhs_code (s);
421 }
422
423 else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR)
424 {
425 tree op = gimple_assign_rhs1 (s);
426 tree type = TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 426, __FUNCTION__))->typed.type)
;
427 enum tree_code code = parse_predicate (op, op0, op1);
428
429 return code == ERROR_MARK ? ERROR_MARK
430 : invert_tree_comparison (code, HONOR_NANS (type));
431 }
432
433 return ERROR_MARK;
434 }
435
436 if (COMPARISON_CLASS_P (cond)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code
) (cond)->base.code))] == tcc_comparison)
)
437 {
438 *op0 = TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 438, __FUNCTION__)))))
;
439 *op1 = TREE_OPERAND (cond, 1)(*((const_cast<tree*> (tree_operand_check ((cond), (1),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 439, __FUNCTION__)))))
;
440 return TREE_CODE (cond)((enum tree_code) (cond)->base.code);
441 }
442
443 return ERROR_MARK;
444}
445
446/* Returns the fold of predicate C1 OR C2 at location LOC. */
447
448static tree
449fold_or_predicates (location_t loc, tree c1, tree c2)
450{
451 tree op1a, op1b, op2a, op2b;
452 enum tree_code code1 = parse_predicate (c1, &op1a, &op1b);
453 enum tree_code code2 = parse_predicate (c2, &op2a, &op2b);
454
455 if (code1 != ERROR_MARK && code2 != ERROR_MARK)
456 {
457 tree t = maybe_fold_or_comparisons (boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], code1, op1a, op1b,
458 code2, op2a, op2b);
459 if (t)
460 return t;
461 }
462
463 return fold_build2_loc (loc, TRUTH_OR_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], c1, c2);
464}
465
466/* Returns either a COND_EXPR or the folded expression if the folded
467 expression is a MIN_EXPR, a MAX_EXPR, an ABS_EXPR,
468 a constant or a SSA_NAME. */
469
470static tree
471fold_build_cond_expr (tree type, tree cond, tree rhs, tree lhs)
472{
473 /* If COND is comparison r != 0 and r has boolean type, convert COND
474 to SSA_NAME to accept by vect bool pattern. */
475 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == NE_EXPR)
476 {
477 tree op0 = TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 477, __FUNCTION__)))))
;
478 tree op1 = TREE_OPERAND (cond, 1)(*((const_cast<tree*> (tree_operand_check ((cond), (1),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 478, __FUNCTION__)))))
;
479 if (TREE_CODE (op0)((enum tree_code) (op0)->base.code) == SSA_NAME
480 && TREE_CODE (TREE_TYPE (op0))((enum tree_code) (((contains_struct_check ((op0), (TS_TYPED)
, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 480, __FUNCTION__))->typed.type))->base.code)
== BOOLEAN_TYPE
481 && (integer_zerop (op1)))
482 cond = op0;
483 }
484
485 gimple_match_op cexpr (gimple_match_cond::UNCOND, COND_EXPR,
486 type, cond, rhs, lhs);
487 if (cexpr.resimplify (NULLnullptr, follow_all_ssa_edges))
488 {
489 if (gimple_simplified_result_is_gimple_val (&cexpr))
490 return cexpr.ops[0];
491 else if (cexpr.code == ABS_EXPR)
492 return build1 (ABS_EXPR, type, cexpr.ops[0]);
493 else if (cexpr.code == MIN_EXPR
494 || cexpr.code == MAX_EXPR)
495 return build2 ((tree_code)cexpr.code, type, cexpr.ops[0], cexpr.ops[1]);
496 }
497
498 return build3 (COND_EXPR, type, cond, rhs, lhs);
499}
500
501/* Add condition NC to the predicate list of basic block BB. LOOP is
502 the loop to be if-converted. Use predicate of cd-equivalent block
503 for join bb if it exists: we call basic blocks bb1 and bb2
504 cd-equivalent if they are executed under the same condition. */
505
506static inline void
507add_to_predicate_list (class loop *loop, basic_block bb, tree nc)
508{
509 tree bc, *tp;
510 basic_block dom_bb;
511
512 if (is_true_predicate (nc))
513 return;
514
515 /* If dominance tells us this basic block is always executed,
516 don't record any predicates for it. */
517 if (dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
518 return;
519
520 dom_bb = get_immediate_dominator (CDI_DOMINATORS, bb);
521 /* We use notion of cd equivalence to get simpler predicate for
522 join block, e.g. if join block has 2 predecessors with predicates
523 p1 & p2 and p1 & !p2, we'd like to get p1 for it instead of
524 p1 & p2 | p1 & !p2. */
525 if (dom_bb != loop->header
526 && get_immediate_dominator (CDI_POST_DOMINATORS, dom_bb) == bb)
527 {
528 gcc_assert (flow_bb_inside_loop_p (loop, dom_bb))((void)(!(flow_bb_inside_loop_p (loop, dom_bb)) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 528, __FUNCTION__), 0 : 0))
;
529 bc = bb_predicate (dom_bb);
530 if (!is_true_predicate (bc))
531 set_bb_predicate (bb, bc);
532 else
533 gcc_assert (is_true_predicate (bb_predicate (bb)))((void)(!(is_true_predicate (bb_predicate (bb))) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 533, __FUNCTION__), 0 : 0))
;
534 if (dump_file && (dump_flags & TDF_DETAILS))
535 fprintf (dump_file, "Use predicate of bb#%d for bb#%d\n",
536 dom_bb->index, bb->index);
537 return;
538 }
539
540 if (!is_predicated (bb))
541 bc = nc;
542 else
543 {
544 bc = bb_predicate (bb);
545 bc = fold_or_predicates (EXPR_LOCATION (bc)((((bc)) && ((tree_code_type_tmpl <0>::tree_code_type
[(int) (((enum tree_code) ((bc))->base.code))]) >= tcc_reference
&& (tree_code_type_tmpl <0>::tree_code_type[(int
) (((enum tree_code) ((bc))->base.code))]) <= tcc_expression
)) ? (bc)->exp.locus : ((location_t) 0))
, nc, bc);
546 if (is_true_predicate (bc))
547 {
548 reset_bb_predicate (bb);
549 return;
550 }
551 }
552
553 /* Allow a TRUTH_NOT_EXPR around the main predicate. */
554 if (TREE_CODE (bc)((enum tree_code) (bc)->base.code) == TRUTH_NOT_EXPR)
555 tp = &TREE_OPERAND (bc, 0)(*((const_cast<tree*> (tree_operand_check ((bc), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 555, __FUNCTION__)))))
;
556 else
557 tp = &bc;
558 if (!is_gimple_val (*tp))
559 {
560 gimple_seq stmts;
561 *tp = force_gimple_operand (*tp, &stmts, true, NULL_TREE(tree) nullptr);
562 add_bb_predicate_gimplified_stmts (bb, stmts);
563 }
564 set_bb_predicate (bb, bc);
565}
566
567/* Add the condition COND to the previous condition PREV_COND, and add
568 this to the predicate list of the destination of edge E. LOOP is
569 the loop to be if-converted. */
570
571static void
572add_to_dst_predicate_list (class loop *loop, edge e,
573 tree prev_cond, tree cond)
574{
575 if (!flow_bb_inside_loop_p (loop, e->dest))
576 return;
577
578 if (!is_true_predicate (prev_cond))
579 cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,fold_build2_loc (((location_t) 0), TRUTH_AND_EXPR, global_trees
[TI_BOOLEAN_TYPE], prev_cond, cond )
580 prev_cond, cond)fold_build2_loc (((location_t) 0), TRUTH_AND_EXPR, global_trees
[TI_BOOLEAN_TYPE], prev_cond, cond )
;
581
582 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, e->dest))
583 add_to_predicate_list (loop, e->dest, cond);
584}
585
586/* Return true if one of the successor edges of BB exits LOOP. */
587
588static bool
589bb_with_exit_edge_p (class loop *loop, basic_block bb)
590{
591 edge e;
592 edge_iterator ei;
593
594 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
595 if (loop_exit_edge_p (loop, e))
596 return true;
597
598 return false;
599}
600
601/* Given PHI which has more than two arguments, this function checks if
602 it's if-convertible by degenerating its arguments. Specifically, if
603 below two conditions are satisfied:
604
605 1) Number of PHI arguments with different values equals to 2 and one
606 argument has the only occurrence.
607 2) The edge corresponding to the unique argument isn't critical edge.
608
609 Such PHI can be handled as PHIs have only two arguments. For example,
610 below PHI:
611
612 res = PHI <A_1(e1), A_1(e2), A_2(e3)>;
613
614 can be transformed into:
615
616 res = (predicate of e3) ? A_2 : A_1;
617
618 Return TRUE if it is the case, FALSE otherwise. */
619
620static bool
621phi_convertible_by_degenerating_args (gphi *phi)
622{
623 edge e;
624 tree arg, t1 = NULLnullptr, t2 = NULLnullptr;
625 unsigned int i, i1 = 0, i2 = 0, n1 = 0, n2 = 0;
626 unsigned int num_args = gimple_phi_num_args (phi);
627
628 gcc_assert (num_args > 2)((void)(!(num_args > 2) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 628, __FUNCTION__), 0 : 0))
;
629
630 for (i = 0; i < num_args; i++)
631 {
632 arg = gimple_phi_arg_def (phi, i);
633 if (t1 == NULLnullptr || operand_equal_p (t1, arg, 0))
634 {
635 n1++;
636 i1 = i;
637 t1 = arg;
638 }
639 else if (t2 == NULLnullptr || operand_equal_p (t2, arg, 0))
640 {
641 n2++;
642 i2 = i;
643 t2 = arg;
644 }
645 else
646 return false;
647 }
648
649 if (n1 != 1 && n2 != 1)
650 return false;
651
652 /* Check if the edge corresponding to the unique arg is critical. */
653 e = gimple_phi_arg_edge (phi, (n1 == 1) ? i1 : i2);
654 if (EDGE_COUNT (e->src->succs)vec_safe_length (e->src->succs) > 1)
655 return false;
656
657 return true;
658}
659
660/* Return true when PHI is if-convertible. PHI is part of loop LOOP
661 and it belongs to basic block BB. Note at this point, it is sure
662 that PHI is if-convertible. This function updates global variable
663 ANY_COMPLICATED_PHI if PHI is complicated. */
664
665static bool
666if_convertible_phi_p (class loop *loop, basic_block bb, gphi *phi)
667{
668 if (dump_file && (dump_flags & TDF_DETAILS))
669 {
670 fprintf (dump_file, "-------------------------\n");
671 print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
672 }
673
674 if (bb != loop->header
675 && gimple_phi_num_args (phi) > 2
676 && !phi_convertible_by_degenerating_args (phi))
677 any_complicated_phi = true;
678
679 return true;
680}
681
682/* Records the status of a data reference. This struct is attached to
683 each DR->aux field. */
684
685struct ifc_dr {
686 bool rw_unconditionally;
687 bool w_unconditionally;
688 bool written_at_least_once;
689
690 tree rw_predicate;
691 tree w_predicate;
692 tree base_w_predicate;
693};
694
695#define IFC_DR(DR)((struct ifc_dr *) (DR)->aux) ((struct ifc_dr *) (DR)->aux)
696#define DR_BASE_W_UNCONDITIONALLY(DR)(((struct ifc_dr *) (DR)->aux)->written_at_least_once) (IFC_DR (DR)((struct ifc_dr *) (DR)->aux)->written_at_least_once)
697#define DR_RW_UNCONDITIONALLY(DR)(((struct ifc_dr *) (DR)->aux)->rw_unconditionally) (IFC_DR (DR)((struct ifc_dr *) (DR)->aux)->rw_unconditionally)
698#define DR_W_UNCONDITIONALLY(DR)(((struct ifc_dr *) (DR)->aux)->w_unconditionally) (IFC_DR (DR)((struct ifc_dr *) (DR)->aux)->w_unconditionally)
699
700/* Iterates over DR's and stores refs, DR and base refs, DR pairs in
701 HASH tables. While storing them in HASH table, it checks if the
702 reference is unconditionally read or written and stores that as a flag
703 information. For base reference it checks if it is written atlest once
704 unconditionally and stores it as flag information along with DR.
705 In other words for every data reference A in STMT there exist other
706 accesses to a data reference with the same base with predicates that
707 add up (OR-up) to the true predicate: this ensures that the data
708 reference A is touched (read or written) on every iteration of the
709 if-converted loop. */
710static void
711hash_memrefs_baserefs_and_store_DRs_read_written_info (data_reference_p a)
712{
713
714 data_reference_p *master_dr, *base_master_dr;
715 tree base_ref = DR_BASE_OBJECT (a)(a)->indices.base_object;
716 innermost_loop_behavior *innermost = &DR_INNERMOST (a)(a)->innermost;
717 tree ca = bb_predicate (gimple_bb (DR_STMT (a)(a)->stmt));
718 bool exist1, exist2;
719
720 master_dr = &innermost_DR_map->get_or_insert (innermost, &exist1);
721 if (!exist1)
722 *master_dr = a;
723
724 if (DR_IS_WRITE (a)(!(a)->is_read))
725 {
726 IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->w_predicate
727 = fold_or_predicates (UNKNOWN_LOCATION((location_t) 0), ca,
728 IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->w_predicate);
729 if (is_true_predicate (IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->w_predicate))
730 DR_W_UNCONDITIONALLY (*master_dr)(((struct ifc_dr *) (*master_dr)->aux)->w_unconditionally
)
= true;
731 }
732 IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->rw_predicate
733 = fold_or_predicates (UNKNOWN_LOCATION((location_t) 0), ca,
734 IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->rw_predicate);
735 if (is_true_predicate (IFC_DR (*master_dr)((struct ifc_dr *) (*master_dr)->aux)->rw_predicate))
736 DR_RW_UNCONDITIONALLY (*master_dr)(((struct ifc_dr *) (*master_dr)->aux)->rw_unconditionally
)
= true;
737
738 if (DR_IS_WRITE (a)(!(a)->is_read))
739 {
740 base_master_dr = &baseref_DR_map->get_or_insert (base_ref, &exist2);
741 if (!exist2)
742 *base_master_dr = a;
743 IFC_DR (*base_master_dr)((struct ifc_dr *) (*base_master_dr)->aux)->base_w_predicate
744 = fold_or_predicates (UNKNOWN_LOCATION((location_t) 0), ca,
745 IFC_DR (*base_master_dr)((struct ifc_dr *) (*base_master_dr)->aux)->base_w_predicate);
746 if (is_true_predicate (IFC_DR (*base_master_dr)((struct ifc_dr *) (*base_master_dr)->aux)->base_w_predicate))
747 DR_BASE_W_UNCONDITIONALLY (*base_master_dr)(((struct ifc_dr *) (*base_master_dr)->aux)->written_at_least_once
)
= true;
748 }
749}
750
751/* Return TRUE if can prove the index IDX of an array reference REF is
752 within array bound. Return false otherwise. */
753
754static bool
755idx_within_array_bound (tree ref, tree *idx, void *dta)
756{
757 wi::overflow_type overflow;
758 widest_int niter, valid_niter, delta, wi_step;
759 tree ev, init, step;
760 tree low, high;
761 class loop *loop = (class loop*) dta;
762
763 /* Only support within-bound access for array references. */
764 if (TREE_CODE (ref)((enum tree_code) (ref)->base.code) != ARRAY_REF)
765 return false;
766
767 /* For arrays that might have flexible sizes, it is not guaranteed that they
768 do not extend over their declared size. */
769 if (array_ref_flexible_size_p (ref))
770 return false;
771
772 ev = analyze_scalar_evolution (loop, *idx);
773 ev = instantiate_parameters (loop, ev);
774 init = initial_condition (ev);
775 step = evolution_part_in_loop_num (ev, loop->num);
776
777 if (!init || TREE_CODE (init)((enum tree_code) (init)->base.code) != INTEGER_CST
778 || (step && TREE_CODE (step)((enum tree_code) (step)->base.code) != INTEGER_CST))
779 return false;
780
781 low = array_ref_low_bound (ref);
782 high = array_ref_up_bound (ref);
783
784 /* The case of nonconstant bounds could be handled, but it would be
785 complicated. */
786 if (TREE_CODE (low)((enum tree_code) (low)->base.code) != INTEGER_CST
787 || !high || TREE_CODE (high)((enum tree_code) (high)->base.code) != INTEGER_CST)
788 return false;
789
790 /* Check if the intial idx is within bound. */
791 if (wi::to_widest (init) < wi::to_widest (low)
792 || wi::to_widest (init) > wi::to_widest (high))
793 return false;
794
795 /* The idx is always within bound. */
796 if (!step || integer_zerop (step))
797 return true;
798
799 if (!max_loop_iterations (loop, &niter))
800 return false;
801
802 if (wi::to_widest (step) < 0)
803 {
804 delta = wi::to_widest (init) - wi::to_widest (low);
805 wi_step = -wi::to_widest (step);
806 }
807 else
808 {
809 delta = wi::to_widest (high) - wi::to_widest (init);
810 wi_step = wi::to_widest (step);
811 }
812
813 valid_niter = wi::div_floor (delta, wi_step, SIGNED, &overflow);
814 /* The iteration space of idx is within array bound. */
815 if (!overflow && niter <= valid_niter)
816 return true;
817
818 return false;
819}
820
821/* Return TRUE if ref is a within bound array reference. */
822
823static bool
824ref_within_array_bound (gimple *stmt, tree ref)
825{
826 class loop *loop = loop_containing_stmt (stmt);
827
828 gcc_assert (loop != NULL)((void)(!(loop != nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 828, __FUNCTION__), 0 : 0))
;
829 return for_each_index (&ref, idx_within_array_bound, loop);
830}
831
832
833/* Given a memory reference expression T, return TRUE if base object
834 it refers to is writable. The base object of a memory reference
835 is the main object being referenced, which is returned by function
836 get_base_address. */
837
838static bool
839base_object_writable (tree ref)
840{
841 tree base_tree = get_base_address (ref);
842
843 return (base_tree
844 && DECL_P (base_tree)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code
) (base_tree)->base.code))] == tcc_declaration)
845 && decl_binds_to_current_def_p (base_tree)
846 && !TREE_READONLY (base_tree)((non_type_check ((base_tree), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 846, __FUNCTION__))->base.readonly_flag)
);
847}
848
849/* Return true when the memory references of STMT won't trap in the
850 if-converted code. There are two things that we have to check for:
851
852 - writes to memory occur to writable memory: if-conversion of
853 memory writes transforms the conditional memory writes into
854 unconditional writes, i.e. "if (cond) A[i] = foo" is transformed
855 into "A[i] = cond ? foo : A[i]", and as the write to memory may not
856 be executed at all in the original code, it may be a readonly
857 memory. To check that A is not const-qualified, we check that
858 there exists at least an unconditional write to A in the current
859 function.
860
861 - reads or writes to memory are valid memory accesses for every
862 iteration. To check that the memory accesses are correctly formed
863 and that we are allowed to read and write in these locations, we
864 check that the memory accesses to be if-converted occur at every
865 iteration unconditionally.
866
867 Returns true for the memory reference in STMT, same memory reference
868 is read or written unconditionally atleast once and the base memory
869 reference is written unconditionally once. This is to check reference
870 will not write fault. Also retuns true if the memory reference is
871 unconditionally read once then we are conditionally writing to memory
872 which is defined as read and write and is bound to the definition
873 we are seeing. */
874static bool
875ifcvt_memrefs_wont_trap (gimple *stmt, vec<data_reference_p> drs)
876{
877 /* If DR didn't see a reference here we can't use it to tell
878 whether the ref traps or not. */
879 if (gimple_uid (stmt) == 0)
880 return false;
881
882 data_reference_p *master_dr, *base_master_dr;
883 data_reference_p a = drs[gimple_uid (stmt) - 1];
884
885 tree base = DR_BASE_OBJECT (a)(a)->indices.base_object;
886 innermost_loop_behavior *innermost = &DR_INNERMOST (a)(a)->innermost;
887
888 gcc_assert (DR_STMT (a) == stmt)((void)(!((a)->stmt == stmt) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 888, __FUNCTION__), 0 : 0))
;
889 gcc_assert (DR_BASE_ADDRESS (a) || DR_OFFSET (a)((void)(!((a)->innermost.base_address || (a)->innermost
.offset || (a)->innermost.init || (a)->innermost.step) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 890, __FUNCTION__), 0 : 0))
890 || DR_INIT (a) || DR_STEP (a))((void)(!((a)->innermost.base_address || (a)->innermost
.offset || (a)->innermost.init || (a)->innermost.step) ?
fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 890, __FUNCTION__), 0 : 0))
;
891
892 master_dr = innermost_DR_map->get (innermost);
893 gcc_assert (master_dr != NULL)((void)(!(master_dr != nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 893, __FUNCTION__), 0 : 0))
;
894
895 base_master_dr = baseref_DR_map->get (base);
896
897 /* If a is unconditionally written to it doesn't trap. */
898 if (DR_W_UNCONDITIONALLY (*master_dr)(((struct ifc_dr *) (*master_dr)->aux)->w_unconditionally
)
)
899 return true;
900
901 /* If a is unconditionally accessed then ...
902
903 Even a is conditional access, we can treat it as an unconditional
904 one if it's an array reference and all its index are within array
905 bound. */
906 if (DR_RW_UNCONDITIONALLY (*master_dr)(((struct ifc_dr *) (*master_dr)->aux)->rw_unconditionally
)
907 || ref_within_array_bound (stmt, DR_REF (a)(a)->ref))
908 {
909 /* an unconditional read won't trap. */
910 if (DR_IS_READ (a)(a)->is_read)
911 return true;
912
913 /* an unconditionaly write won't trap if the base is written
914 to unconditionally. */
915 if (base_master_dr
916 && DR_BASE_W_UNCONDITIONALLY (*base_master_dr)(((struct ifc_dr *) (*base_master_dr)->aux)->written_at_least_once
)
)
917 return flag_store_data_racesglobal_options.x_flag_store_data_races;
918 /* or the base is known to be not readonly. */
919 else if (base_object_writable (DR_REF (a)(a)->ref))
920 return flag_store_data_racesglobal_options.x_flag_store_data_races;
921 }
922
923 return false;
924}
925
926/* Return true if STMT could be converted into a masked load or store
927 (conditional load or store based on a mask computed from bb predicate). */
928
929static bool
930ifcvt_can_use_mask_load_store (gimple *stmt)
931{
932 /* Check whether this is a load or store. */
933 tree lhs = gimple_assign_lhs (stmt);
934 bool is_load;
935 tree ref;
936 if (gimple_store_p (stmt))
937 {
938 if (!is_gimple_val (gimple_assign_rhs1 (stmt)))
939 return false;
940 is_load = false;
941 ref = lhs;
942 }
943 else if (gimple_assign_load_p (stmt))
944 {
945 is_load = true;
946 ref = gimple_assign_rhs1 (stmt);
947 }
948 else
949 return false;
950
951 if (may_be_nonaddressable_p (ref))
952 return false;
953
954 /* Mask should be integer mode of the same size as the load/store
955 mode. */
956 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs))((((enum tree_code) ((tree_class_check ((((contains_struct_check
((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 956, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 956, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 956, __FUNCTION__))->typed.type)) : (((contains_struct_check
((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 956, __FUNCTION__))->typed.type))->type_common.mode)
;
957 if (!int_mode_for_mode (mode).exists () || VECTOR_MODE_P (mode)(((enum mode_class) mode_class[mode]) == MODE_VECTOR_BOOL || (
(enum mode_class) mode_class[mode]) == MODE_VECTOR_INT || ((enum
mode_class) mode_class[mode]) == MODE_VECTOR_FLOAT || ((enum
mode_class) mode_class[mode]) == MODE_VECTOR_FRACT || ((enum
mode_class) mode_class[mode]) == MODE_VECTOR_UFRACT || ((enum
mode_class) mode_class[mode]) == MODE_VECTOR_ACCUM || ((enum
mode_class) mode_class[mode]) == MODE_VECTOR_UACCUM)
)
958 return false;
959
960 if (can_vec_mask_load_store_p (mode, VOIDmode((void) 0, E_VOIDmode), is_load))
961 return true;
962
963 return false;
964}
965
966/* Return true if STMT could be converted from an operation that is
967 unconditional to one that is conditional on a bb predicate mask. */
968
969static bool
970ifcvt_can_predicate (gimple *stmt)
971{
972 basic_block bb = gimple_bb (stmt);
973
974 if (!(flag_tree_loop_vectorizeglobal_options.x_flag_tree_loop_vectorize || bb->loop_father->force_vectorize)
975 || bb->loop_father->dont_vectorize
976 || gimple_has_volatile_ops (stmt))
977 return false;
978
979 if (gimple_assign_single_p (stmt))
980 return ifcvt_can_use_mask_load_store (stmt);
981
982 tree_code code = gimple_assign_rhs_code (stmt);
983 tree lhs_type = TREE_TYPE (gimple_assign_lhs (stmt))((contains_struct_check ((gimple_assign_lhs (stmt)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 983, __FUNCTION__))->typed.type)
;
984 tree rhs_type = TREE_TYPE (gimple_assign_rhs1 (stmt))((contains_struct_check ((gimple_assign_rhs1 (stmt)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 984, __FUNCTION__))->typed.type)
;
985 if (!types_compatible_p (lhs_type, rhs_type))
986 return false;
987 internal_fn cond_fn = get_conditional_internal_fn (code);
988 return (cond_fn != IFN_LAST
989 && vectorized_internal_fn_supported_p (cond_fn, lhs_type));
990}
991
992/* Return true when STMT is if-convertible.
993
994 GIMPLE_ASSIGN statement is not if-convertible if,
995 - it is not movable,
996 - it could trap,
997 - LHS is not var decl. */
998
999static bool
1000if_convertible_gimple_assign_stmt_p (gimple *stmt,
1001 vec<data_reference_p> refs)
1002{
1003 tree lhs = gimple_assign_lhs (stmt);
1004
1005 if (dump_file && (dump_flags & TDF_DETAILS))
1006 {
1007 fprintf (dump_file, "-------------------------\n");
1008 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1009 }
1010
1011 if (!is_gimple_reg_type (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1011, __FUNCTION__))->typed.type)
))
1012 return false;
1013
1014 /* Some of these constrains might be too conservative. */
1015 if (stmt_ends_bb_p (stmt)
1016 || gimple_has_volatile_ops (stmt)
1017 || (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == SSA_NAME
1018 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)(tree_check ((lhs), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1018, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
)
1019 || gimple_has_side_effects (stmt))
1020 {
1021 if (dump_file && (dump_flags & TDF_DETAILS))
1022 fprintf (dump_file, "stmt not suitable for ifcvt\n");
1023 return false;
1024 }
1025
1026 /* tree-into-ssa.cc uses GF_PLF_1, so avoid it, because
1027 in between if_convertible_loop_p and combine_blocks
1028 we can perform loop versioning. */
1029 gimple_set_plf (stmt, GF_PLF_2, false);
1030
1031 if ((! gimple_vuse (stmt)
1032 || gimple_could_trap_p_1 (stmt, false, false)
1033 || ! ifcvt_memrefs_wont_trap (stmt, refs))
1034 && gimple_could_trap_p (stmt))
1035 {
1036 if (ifcvt_can_predicate (stmt))
1037 {
1038 gimple_set_plf (stmt, GF_PLF_2, true);
1039 need_to_predicate = true;
1040 return true;
1041 }
1042 if (dump_file && (dump_flags & TDF_DETAILS))
1043 fprintf (dump_file, "tree could trap...\n");
1044 return false;
1045 }
1046 else if ((INTEGRAL_TYPE_P (TREE_TYPE (lhs))(((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1046, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1046, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1046, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE
)
1047 || POINTER_TYPE_P (TREE_TYPE (lhs))(((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1047, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1047, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
)
1048 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))((((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1048, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1048, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
) ? !global_options.x_flag_wrapv_pointer : (!(any_integral_type_check
((((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1048, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1048, __FUNCTION__))->base.u.bits.unsigned_flag &&
!global_options.x_flag_wrapv && !global_options.x_flag_trapv
))
1049 && arith_code_with_undefined_signed_overflow
1050 (gimple_assign_rhs_code (stmt)))
1051 /* We have to rewrite stmts with undefined overflow. */
1052 need_to_rewrite_undefined = true;
1053
1054 /* When if-converting stores force versioning, likewise if we
1055 ended up generating store data races. */
1056 if (gimple_vdef (stmt))
1057 need_to_predicate = true;
1058
1059 return true;
1060}
1061
1062/* Return true when STMT is if-convertible.
1063
1064 A statement is if-convertible if:
1065 - it is an if-convertible GIMPLE_ASSIGN,
1066 - it is a GIMPLE_LABEL or a GIMPLE_COND,
1067 - it is builtins call,
1068 - it is a call to a function with a SIMD clone. */
1069
1070static bool
1071if_convertible_stmt_p (gimple *stmt, vec<data_reference_p> refs)
1072{
1073 switch (gimple_code (stmt))
1074 {
1075 case GIMPLE_LABEL:
1076 case GIMPLE_DEBUG:
1077 case GIMPLE_COND:
1078 return true;
1079
1080 case GIMPLE_ASSIGN:
1081 return if_convertible_gimple_assign_stmt_p (stmt, refs);
1082
1083 case GIMPLE_CALL:
1084 {
1085 tree fndecl = gimple_call_fndecl (stmt);
1086 if (fndecl)
1087 {
1088 /* We can vectorize some builtins and functions with SIMD
1089 "inbranch" clones. */
1090 int flags = gimple_call_flags (stmt);
1091 struct cgraph_node *node = cgraph_node::get (fndecl);
1092 if ((flags & ECF_CONST(1 << 0))
1093 && !(flags & ECF_LOOPING_CONST_OR_PURE(1 << 2))
1094 && fndecl_built_in_p (fndecl))
1095 return true;
1096 if (node && node->simd_clones != NULLnullptr)
1097 /* Ensure that at least one clone can be "inbranch". */
1098 for (struct cgraph_node *n = node->simd_clones; n != NULLnullptr;
1099 n = n->simdclone->next_clone)
1100 if (n->simdclone->inbranch)
1101 {
1102 gimple_set_plf (stmt, GF_PLF_2, true);
1103 need_to_predicate = true;
1104 return true;
1105 }
1106 }
1107 return false;
1108 }
1109
1110 default:
1111 /* Don't know what to do with 'em so don't do anything. */
1112 if (dump_file && (dump_flags & TDF_DETAILS))
1113 {
1114 fprintf (dump_file, "don't know what to do\n");
1115 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
1116 }
1117 return false;
1118 }
1119}
1120
1121/* Assumes that BB has more than 1 predecessors.
1122 Returns false if at least one successor is not on critical edge
1123 and true otherwise. */
1124
1125static inline bool
1126all_preds_critical_p (basic_block bb)
1127{
1128 edge e;
1129 edge_iterator ei;
1130
1131 FOR_EACH_EDGE (e, ei, bb->preds)for ((ei) = ei_start_1 (&((bb->preds))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
1132 if (EDGE_COUNT (e->src->succs)vec_safe_length (e->src->succs) == 1)
1133 return false;
1134 return true;
1135}
1136
1137/* Return true when BB is if-convertible. This routine does not check
1138 basic block's statements and phis.
1139
1140 A basic block is not if-convertible if:
1141 - it is non-empty and it is after the exit block (in BFS order),
1142 - it is after the exit block but before the latch,
1143 - its edges are not normal.
1144
1145 EXIT_BB is the basic block containing the exit of the LOOP. BB is
1146 inside LOOP. */
1147
1148static bool
1149if_convertible_bb_p (class loop *loop, basic_block bb, basic_block exit_bb)
1150{
1151 edge e;
1152 edge_iterator ei;
1153
1154 if (dump_file && (dump_flags & TDF_DETAILS))
1155 fprintf (dump_file, "----------[%d]-------------\n", bb->index);
1156
1157 if (EDGE_COUNT (bb->succs)vec_safe_length (bb->succs) > 2)
1158 return false;
1159
1160 gimple *last = last_stmt (bb);
1161 if (gcall *call = safe_dyn_cast <gcall *> (last))
1162 if (gimple_call_ctrl_altering_p (call))
1163 return false;
1164
1165 if (exit_bb)
1166 {
1167 if (bb != loop->latch)
1168 {
1169 if (dump_file && (dump_flags & TDF_DETAILS))
1170 fprintf (dump_file, "basic block after exit bb but before latch\n");
1171 return false;
1172 }
1173 else if (!empty_block_p (bb))
1174 {
1175 if (dump_file && (dump_flags & TDF_DETAILS))
1176 fprintf (dump_file, "non empty basic block after exit bb\n");
1177 return false;
1178 }
1179 else if (bb == loop->latch
1180 && bb != exit_bb
1181 && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
1182 {
1183 if (dump_file && (dump_flags & TDF_DETAILS))
1184 fprintf (dump_file, "latch is not dominated by exit_block\n");
1185 return false;
1186 }
1187 }
1188
1189 /* Be less adventurous and handle only normal edges. */
1190 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
1191 if (e->flags & (EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
1192 {
1193 if (dump_file && (dump_flags & TDF_DETAILS))
1194 fprintf (dump_file, "Difficult to handle edges\n");
1195 return false;
1196 }
1197
1198 return true;
1199}
1200
1201/* Return true when all predecessor blocks of BB are visited. The
1202 VISITED bitmap keeps track of the visited blocks. */
1203
1204static bool
1205pred_blocks_visited_p (basic_block bb, bitmap *visited)
1206{
1207 edge e;
1208 edge_iterator ei;
1209 FOR_EACH_EDGE (e, ei, bb->preds)for ((ei) = ei_start_1 (&((bb->preds))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
1210 if (!bitmap_bit_p (*visited, e->src->index))
1211 return false;
1212
1213 return true;
1214}
1215
1216/* Get body of a LOOP in suitable order for if-conversion. It is
1217 caller's responsibility to deallocate basic block list.
1218 If-conversion suitable order is, breadth first sort (BFS) order
1219 with an additional constraint: select a block only if all its
1220 predecessors are already selected. */
1221
1222static basic_block *
1223get_loop_body_in_if_conv_order (const class loop *loop)
1224{
1225 basic_block *blocks, *blocks_in_bfs_order;
1226 basic_block bb;
1227 bitmap visited;
1228 unsigned int index = 0;
1229 unsigned int visited_count = 0;
1230
1231 gcc_assert (loop->num_nodes)((void)(!(loop->num_nodes) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1231, __FUNCTION__), 0 : 0))
;
1232 gcc_assert (loop->latch != EXIT_BLOCK_PTR_FOR_FN (cfun))((void)(!(loop->latch != (((cfun + 0))->cfg->x_exit_block_ptr
)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1232, __FUNCTION__), 0 : 0))
;
1233
1234 blocks = XCNEWVEC (basic_block, loop->num_nodes)((basic_block *) xcalloc ((loop->num_nodes), sizeof (basic_block
)))
;
1235 visited = BITMAP_ALLOCbitmap_alloc (NULLnullptr);
1236
1237 blocks_in_bfs_order = get_loop_body_in_bfs_order (loop);
1238
1239 index = 0;
1240 while (index < loop->num_nodes)
1241 {
1242 bb = blocks_in_bfs_order [index];
1243
1244 if (bb->flags & BB_IRREDUCIBLE_LOOP)
1245 {
1246 free (blocks_in_bfs_order);
1247 BITMAP_FREE (visited)((void) (bitmap_obstack_free ((bitmap) visited), (visited) = (
bitmap) nullptr))
;
1248 free (blocks);
1249 return NULLnullptr;
1250 }
1251
1252 if (!bitmap_bit_p (visited, bb->index))
1253 {
1254 if (pred_blocks_visited_p (bb, &visited)
1255 || bb == loop->header)
1256 {
1257 /* This block is now visited. */
1258 bitmap_set_bit (visited, bb->index);
1259 blocks[visited_count++] = bb;
1260 }
1261 }
1262
1263 index++;
1264
1265 if (index == loop->num_nodes
1266 && visited_count != loop->num_nodes)
1267 /* Not done yet. */
1268 index = 0;
1269 }
1270 free (blocks_in_bfs_order);
1271 BITMAP_FREE (visited)((void) (bitmap_obstack_free ((bitmap) visited), (visited) = (
bitmap) nullptr))
;
1272 return blocks;
1273}
1274
1275/* Returns true when the analysis of the predicates for all the basic
1276 blocks in LOOP succeeded.
1277
1278 predicate_bbs first allocates the predicates of the basic blocks.
1279 These fields are then initialized with the tree expressions
1280 representing the predicates under which a basic block is executed
1281 in the LOOP. As the loop->header is executed at each iteration, it
1282 has the "true" predicate. Other statements executed under a
1283 condition are predicated with that condition, for example
1284
1285 | if (x)
1286 | S1;
1287 | else
1288 | S2;
1289
1290 S1 will be predicated with "x", and
1291 S2 will be predicated with "!x". */
1292
1293static void
1294predicate_bbs (loop_p loop)
1295{
1296 unsigned int i;
1297
1298 for (i = 0; i < loop->num_nodes; i++)
1299 init_bb_predicate (ifc_bbs[i]);
1300
1301 for (i = 0; i < loop->num_nodes; i++)
1302 {
1303 basic_block bb = ifc_bbs[i];
1304 tree cond;
1305 gimple *stmt;
1306
1307 /* The loop latch and loop exit block are always executed and
1308 have no extra conditions to be processed: skip them. */
1309 if (bb == loop->latch
1310 || bb_with_exit_edge_p (loop, bb))
1311 {
1312 reset_bb_predicate (bb);
1313 continue;
1314 }
1315
1316 cond = bb_predicate (bb);
1317 stmt = last_stmt (bb);
1318 if (stmt && gimple_code (stmt) == GIMPLE_COND)
1319 {
1320 tree c2;
1321 edge true_edge, false_edge;
1322 location_t loc = gimple_location (stmt);
1323 tree c;
1324 /* gcc.dg/fold-bopcond-1.c shows that despite all forwprop passes
1325 conditions can remain unfolded because of multiple uses so
1326 try to re-fold here, especially to get precision changing
1327 conversions sorted out. Do not simply fold the stmt since
1328 this is analysis only. When conditions were embedded in
1329 COND_EXPRs those were folded separately before folding the
1330 COND_EXPR but as they are now outside we have to make sure
1331 to fold them. Do it here - another opportunity would be to
1332 fold predicates as they are inserted. */
1333 gimple_match_op cexpr (gimple_match_cond::UNCOND,
1334 gimple_cond_code (stmt),
1335 boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
1336 gimple_cond_lhs (stmt),
1337 gimple_cond_rhs (stmt));
1338 if (cexpr.resimplify (NULLnullptr, follow_all_ssa_edges)
1339 && cexpr.code.is_tree_code ()
1340 && TREE_CODE_CLASS ((tree_code)cexpr.code)tree_code_type_tmpl <0>::tree_code_type[(int) ((tree_code
)cexpr.code)]
== tcc_comparison)
1341 c = build2_loc (loc, (tree_code)cexpr.code, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
1342 cexpr.ops[0], cexpr.ops[1]);
1343 else
1344 c = build2_loc (loc, gimple_cond_code (stmt),
1345 boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
1346 gimple_cond_lhs (stmt),
1347 gimple_cond_rhs (stmt));
1348
1349 /* Add new condition into destination's predicate list. */
1350 extract_true_false_edges_from_block (gimple_bb (stmt),
1351 &true_edge, &false_edge);
1352
1353 /* If C is true, then TRUE_EDGE is taken. */
1354 add_to_dst_predicate_list (loop, true_edge, unshare_expr (cond),
1355 unshare_expr (c));
1356
1357 /* If C is false, then FALSE_EDGE is taken. */
1358 c2 = build1_loc (loc, TRUTH_NOT_EXPR, boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
1359 unshare_expr (c));
1360 add_to_dst_predicate_list (loop, false_edge,
1361 unshare_expr (cond), c2);
1362
1363 cond = NULL_TREE(tree) nullptr;
1364 }
1365
1366 /* If current bb has only one successor, then consider it as an
1367 unconditional goto. */
1368 if (single_succ_p (bb))
1369 {
1370 basic_block bb_n = single_succ (bb);
1371
1372 /* The successor bb inherits the predicate of its
1373 predecessor. If there is no predicate in the predecessor
1374 bb, then consider the successor bb as always executed. */
1375 if (cond == NULL_TREE(tree) nullptr)
1376 cond = boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE];
1377
1378 add_to_predicate_list (loop, bb_n, cond);
1379 }
1380 }
1381
1382 /* The loop header is always executed. */
1383 reset_bb_predicate (loop->header);
1384 gcc_assert (bb_predicate_gimplified_stmts (loop->header) == NULL((void)(!(bb_predicate_gimplified_stmts (loop->header) == nullptr
&& bb_predicate_gimplified_stmts (loop->latch) ==
nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1385, __FUNCTION__), 0 : 0))
1385 && bb_predicate_gimplified_stmts (loop->latch) == NULL)((void)(!(bb_predicate_gimplified_stmts (loop->header) == nullptr
&& bb_predicate_gimplified_stmts (loop->latch) ==
nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1385, __FUNCTION__), 0 : 0))
;
1386}
1387
1388/* Build region by adding loop pre-header and post-header blocks. */
1389
1390static vec<basic_block>
1391build_region (class loop *loop)
1392{
1393 vec<basic_block> region = vNULL;
1394 basic_block exit_bb = NULLnullptr;
1395
1396 gcc_assert (ifc_bbs)((void)(!(ifc_bbs) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1396, __FUNCTION__), 0 : 0))
;
1397 /* The first element is loop pre-header. */
1398 region.safe_push (loop_preheader_edge (loop)->src);
1399
1400 for (unsigned int i = 0; i < loop->num_nodes; i++)
1401 {
1402 basic_block bb = ifc_bbs[i];
1403 region.safe_push (bb);
1404 /* Find loop postheader. */
1405 edge e;
1406 edge_iterator ei;
1407 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
1408 if (loop_exit_edge_p (loop, e))
1409 {
1410 exit_bb = e->dest;
1411 break;
1412 }
1413 }
1414 /* The last element is loop post-header. */
1415 gcc_assert (exit_bb)((void)(!(exit_bb) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1415, __FUNCTION__), 0 : 0))
;
1416 region.safe_push (exit_bb);
1417 return region;
1418}
1419
1420/* Return true when LOOP is if-convertible. This is a helper function
1421 for if_convertible_loop_p. REFS and DDRS are initialized and freed
1422 in if_convertible_loop_p. */
1423
1424static bool
1425if_convertible_loop_p_1 (class loop *loop, vec<data_reference_p> *refs)
1426{
1427 unsigned int i;
1428 basic_block exit_bb = NULLnullptr;
1429 vec<basic_block> region;
1430
1431 calculate_dominance_info (CDI_DOMINATORS);
1432
1433 for (i = 0; i < loop->num_nodes; i++)
1434 {
1435 basic_block bb = ifc_bbs[i];
1436
1437 if (!if_convertible_bb_p (loop, bb, exit_bb))
1438 return false;
1439
1440 if (bb_with_exit_edge_p (loop, bb))
1441 exit_bb = bb;
1442 }
1443
1444 for (i = 0; i < loop->num_nodes; i++)
1445 {
1446 basic_block bb = ifc_bbs[i];
1447 gimple_stmt_iterator gsi;
1448
1449 bool may_have_nonlocal_labels
1450 = bb_with_exit_edge_p (loop, bb) || bb == loop->latch;
1451 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
1452 switch (gimple_code (gsi_stmt (gsi)))
1453 {
1454 case GIMPLE_LABEL:
1455 if (!may_have_nonlocal_labels)
1456 {
1457 tree label
1458 = gimple_label_label (as_a <glabel *> (gsi_stmt (gsi)));
1459 if (DECL_NONLOCAL (label)((contains_struct_check ((label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1459, __FUNCTION__))->decl_common.nonlocal_flag)
|| FORCED_LABEL (label)((tree_check ((label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1459, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag
)
)
1460 return false;
1461 }
1462 /* Fallthru. */
1463 case GIMPLE_ASSIGN:
1464 case GIMPLE_CALL:
1465 case GIMPLE_DEBUG:
1466 case GIMPLE_COND:
1467 gimple_set_uid (gsi_stmt (gsi), 0);
1468 break;
1469 default:
1470 return false;
1471 }
1472 }
1473
1474 data_reference_p dr;
1475
1476 innermost_DR_map
1477 = new hash_map<innermost_loop_behavior_hash, data_reference_p>;
1478 baseref_DR_map = new hash_map<tree_operand_hash, data_reference_p>;
1479
1480 /* Compute post-dominator tree locally. */
1481 region = build_region (loop);
1482 calculate_dominance_info_for_region (CDI_POST_DOMINATORS, region);
1483
1484 predicate_bbs (loop);
1485
1486 /* Free post-dominator tree since it is not used after predication. */
1487 free_dominance_info_for_region (cfun(cfun + 0), CDI_POST_DOMINATORS, region);
1488 region.release ();
1489
1490 for (i = 0; refs->iterate (i, &dr); i++)
1491 {
1492 tree ref = DR_REF (dr)(dr)->ref;
1493
1494 dr->aux = XNEW (struct ifc_dr)((struct ifc_dr *) xmalloc (sizeof (struct ifc_dr)));
1495 DR_BASE_W_UNCONDITIONALLY (dr)(((struct ifc_dr *) (dr)->aux)->written_at_least_once) = false;
1496 DR_RW_UNCONDITIONALLY (dr)(((struct ifc_dr *) (dr)->aux)->rw_unconditionally) = false;
1497 DR_W_UNCONDITIONALLY (dr)(((struct ifc_dr *) (dr)->aux)->w_unconditionally) = false;
1498 IFC_DR (dr)((struct ifc_dr *) (dr)->aux)->rw_predicate = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1499 IFC_DR (dr)((struct ifc_dr *) (dr)->aux)->w_predicate = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1500 IFC_DR (dr)((struct ifc_dr *) (dr)->aux)->base_w_predicate = boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE];
1501 if (gimple_uid (DR_STMT (dr)(dr)->stmt) == 0)
1502 gimple_set_uid (DR_STMT (dr)(dr)->stmt, i + 1);
1503
1504 /* If DR doesn't have innermost loop behavior or it's a compound
1505 memory reference, we synthesize its innermost loop behavior
1506 for hashing. */
1507 if (TREE_CODE (ref)((enum tree_code) (ref)->base.code) == COMPONENT_REF
1508 || TREE_CODE (ref)((enum tree_code) (ref)->base.code) == IMAGPART_EXPR
1509 || TREE_CODE (ref)((enum tree_code) (ref)->base.code) == REALPART_EXPR
1510 || !(DR_BASE_ADDRESS (dr)(dr)->innermost.base_address || DR_OFFSET (dr)(dr)->innermost.offset
1511 || DR_INIT (dr)(dr)->innermost.init || DR_STEP (dr)(dr)->innermost.step))
1512 {
1513 while (TREE_CODE (ref)((enum tree_code) (ref)->base.code) == COMPONENT_REF
1514 || TREE_CODE (ref)((enum tree_code) (ref)->base.code) == IMAGPART_EXPR
1515 || TREE_CODE (ref)((enum tree_code) (ref)->base.code) == REALPART_EXPR)
1516 ref = TREE_OPERAND (ref, 0)(*((const_cast<tree*> (tree_operand_check ((ref), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1516, __FUNCTION__)))))
;
1517
1518 memset (&DR_INNERMOST (dr)(dr)->innermost, 0, sizeof (DR_INNERMOST (dr)(dr)->innermost));
1519 DR_BASE_ADDRESS (dr)(dr)->innermost.base_address = ref;
1520 }
1521 hash_memrefs_baserefs_and_store_DRs_read_written_info (dr);
1522 }
1523
1524 for (i = 0; i < loop->num_nodes; i++)
1525 {
1526 basic_block bb = ifc_bbs[i];
1527 gimple_stmt_iterator itr;
1528
1529 /* Check the if-convertibility of statements in predicated BBs. */
1530 if (!dominated_by_p (CDI_DOMINATORS, loop->latch, bb))
1531 for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr))
1532 if (!if_convertible_stmt_p (gsi_stmt (itr), *refs))
1533 return false;
1534 }
1535
1536 /* Checking PHIs needs to be done after stmts, as the fact whether there
1537 are any masked loads or stores affects the tests. */
1538 for (i = 0; i < loop->num_nodes; i++)
1539 {
1540 basic_block bb = ifc_bbs[i];
1541 gphi_iterator itr;
1542
1543 for (itr = gsi_start_phis (bb); !gsi_end_p (itr); gsi_next (&itr))
1544 if (!if_convertible_phi_p (loop, bb, itr.phi ()))
1545 return false;
1546 }
1547
1548 if (dump_file)
1549 fprintf (dump_file, "Applying if-conversion\n");
1550
1551 return true;
1552}
1553
1554/* Return true when LOOP is if-convertible.
1555 LOOP is if-convertible if:
1556 - it is innermost,
1557 - it has two or more basic blocks,
1558 - it has only one exit,
1559 - loop header is not the exit edge,
1560 - if its basic blocks and phi nodes are if convertible. */
1561
1562static bool
1563if_convertible_loop_p (class loop *loop, vec<data_reference_p> *refs)
1564{
1565 edge e;
1566 edge_iterator ei;
1567 bool res = false;
1568
1569 /* Handle only innermost loop. */
1570 if (!loop || loop->inner)
1571 {
1572 if (dump_file && (dump_flags & TDF_DETAILS))
1573 fprintf (dump_file, "not innermost loop\n");
1574 return false;
1575 }
1576
1577 /* If only one block, no need for if-conversion. */
1578 if (loop->num_nodes <= 2)
1579 {
1580 if (dump_file && (dump_flags & TDF_DETAILS))
1581 fprintf (dump_file, "less than 2 basic blocks\n");
1582 return false;
1583 }
1584
1585 /* More than one loop exit is too much to handle. */
1586 if (!single_exit (loop))
1587 {
1588 if (dump_file && (dump_flags & TDF_DETAILS))
1589 fprintf (dump_file, "multiple exits\n");
1590 return false;
1591 }
1592
1593 /* If one of the loop header's edge is an exit edge then do not
1594 apply if-conversion. */
1595 FOR_EACH_EDGE (e, ei, loop->header->succs)for ((ei) = ei_start_1 (&((loop->header->succs))); ei_cond
((ei), &(e)); ei_next (&(ei)))
1596 if (loop_exit_edge_p (loop, e))
1597 return false;
1598
1599 res = if_convertible_loop_p_1 (loop, refs);
1600
1601 delete innermost_DR_map;
1602 innermost_DR_map = NULLnullptr;
1603
1604 delete baseref_DR_map;
1605 baseref_DR_map = NULLnullptr;
1606
1607 return res;
1608}
1609
1610/* Return reduc_1 if has_nop.
1611
1612 if (...)
1613 tmp1 = (unsigned type) reduc_1;
1614 tmp2 = tmp1 + rhs2;
1615 reduc_3 = (signed type) tmp2. */
1616static tree
1617strip_nop_cond_scalar_reduction (bool has_nop, tree op)
1618{
1619 if (!has_nop)
1620 return op;
1621
1622 if (TREE_CODE (op)((enum tree_code) (op)->base.code) != SSA_NAME)
1623 return NULL_TREE(tree) nullptr;
1624
1625 gassign *stmt = safe_dyn_cast <gassign *> (SSA_NAME_DEF_STMT (op)(tree_check ((op), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1625, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
);
1626 if (!stmt
1627 || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (stmt))((gimple_assign_rhs_code (stmt)) == NOP_EXPR || (gimple_assign_rhs_code
(stmt)) == CONVERT_EXPR)
1628 || !tree_nop_conversion_p (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1628, __FUNCTION__))->typed.type)
, TREE_TYPE((contains_struct_check ((gimple_assign_rhs1 (stmt)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1629, __FUNCTION__))->typed.type)
1629 (gimple_assign_rhs1 (stmt))((contains_struct_check ((gimple_assign_rhs1 (stmt)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1629, __FUNCTION__))->typed.type)
))
1630 return NULL_TREE(tree) nullptr;
1631
1632 return gimple_assign_rhs1 (stmt);
1633}
1634
1635/* Returns true if def-stmt for phi argument ARG is simple increment/decrement
1636 which is in predicated basic block.
1637 In fact, the following PHI pattern is searching:
1638 loop-header:
1639 reduc_1 = PHI <..., reduc_2>
1640 ...
1641 if (...)
1642 reduc_3 = ...
1643 reduc_2 = PHI <reduc_1, reduc_3>
1644
1645 ARG_0 and ARG_1 are correspondent PHI arguments.
1646 REDUC, OP0 and OP1 contain reduction stmt and its operands.
1647 EXTENDED is true if PHI has > 2 arguments. */
1648
1649static bool
1650is_cond_scalar_reduction (gimple *phi, gimple **reduc, tree arg_0, tree arg_1,
1651 tree *op0, tree *op1, bool extended, bool* has_nop,
1652 gimple **nop_reduc)
1653{
1654 tree lhs, r_op1, r_op2, r_nop1, r_nop2;
1655 gimple *stmt;
1656 gimple *header_phi = NULLnullptr;
1657 enum tree_code reduction_op;
1658 basic_block bb = gimple_bb (phi);
1659 class loop *loop = bb->loop_father;
1660 edge latch_e = loop_latch_edge (loop);
1661 imm_use_iterator imm_iter;
1662 use_operand_p use_p;
1663 edge e;
1664 edge_iterator ei;
1665 bool result = *has_nop = false;
1666 if (TREE_CODE (arg_0)((enum tree_code) (arg_0)->base.code) != SSA_NAME || TREE_CODE (arg_1)((enum tree_code) (arg_1)->base.code) != SSA_NAME)
12
Assuming field 'code' is equal to SSA_NAME
13
Assuming field 'code' is equal to SSA_NAME
1667 return false;
1668
1669 if (!extended
13.1
'extended' is false
&& gimple_code (SSA_NAME_DEF_STMT (arg_0)(tree_check ((arg_0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1669, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
) == GIMPLE_PHI
)
14
Assuming the condition is false
15
Taking false branch
1670 {
1671 lhs = arg_1;
1672 header_phi = SSA_NAME_DEF_STMT (arg_0)(tree_check ((arg_0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1672, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1673 stmt = SSA_NAME_DEF_STMT (arg_1)(tree_check ((arg_1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1673, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1674 }
1675 else if (gimple_code (SSA_NAME_DEF_STMT (arg_1)(tree_check ((arg_1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1675, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
) == GIMPLE_PHI
)
16
Assuming the condition is true
17
Taking true branch
1676 {
1677 lhs = arg_0;
1678 header_phi = SSA_NAME_DEF_STMT (arg_1)(tree_check ((arg_1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1678, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1679 stmt = SSA_NAME_DEF_STMT (arg_0)(tree_check ((arg_0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1679, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1680 }
1681 else
1682 return false;
1683 if (gimple_bb (header_phi) != loop->header)
18
Assuming the condition is false
19
Taking false branch
1684 return false;
1685
1686 if (PHI_ARG_DEF_FROM_EDGE (header_phi, latch_e)gimple_phi_arg_def (((header_phi)), ((latch_e)->dest_idx)) != PHI_RESULT (phi)get_def_from_ptr (gimple_phi_result_ptr (phi)))
20
Assuming the condition is false
1687 return false;
1688
1689 if (gimple_code (stmt) != GIMPLE_ASSIGN
21
Assuming the condition is false
23
Taking false branch
1690 || gimple_has_volatile_ops (stmt))
22
Assuming the condition is false
1691 return false;
1692
1693 if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt)))
24
Assuming the condition is false
25
Taking false branch
1694 return false;
1695
1696 if (!is_predicated (gimple_bb (stmt)))
26
Taking false branch
1697 return false;
1698
1699 /* Check that stmt-block is predecessor of phi-block. */
1700 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)))
27
Loop condition is true. Entering loop body
1701 if (e->dest == bb)
28
Assuming 'bb' is equal to field 'dest'
29
Taking true branch
1702 {
1703 result = true;
1704 break;
1705 }
1706 if (!result
30.1
'result' is true
)
30
Execution continues on line 1706
31
Taking false branch
1707 return false;
1708
1709 if (!has_single_use (lhs))
32
Taking false branch
1710 return false;
1711
1712 reduction_op = gimple_assign_rhs_code (stmt);
1713
1714 /* Catch something like below
1715
1716 loop-header:
1717 reduc_1 = PHI <..., reduc_2>
1718 ...
1719 if (...)
1720 tmp1 = (unsigned type) reduc_1;
1721 tmp2 = tmp1 + rhs2;
1722 reduc_3 = (signed type) tmp2;
1723
1724 reduc_2 = PHI <reduc_1, reduc_3>
1725
1726 and convert to
1727
1728 reduc_2 = PHI <0, reduc_3>
1729 tmp1 = (unsigned type)reduce_1;
1730 ifcvt = cond_expr ? rhs2 : 0
1731 tmp2 = tmp1 +/- ifcvt;
1732 reduce_1 = (signed type)tmp2; */
1733
1734 if (CONVERT_EXPR_CODE_P (reduction_op)((reduction_op) == NOP_EXPR || (reduction_op) == CONVERT_EXPR
)
)
33
Assuming 'reduction_op' is not equal to NOP_EXPR
34
Assuming 'reduction_op' is not equal to CONVERT_EXPR
1735 {
1736 lhs = gimple_assign_rhs1 (stmt);
1737 if (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) != SSA_NAME
1738 || !has_single_use (lhs))
1739 return false;
1740
1741 *nop_reduc = stmt;
1742 stmt = SSA_NAME_DEF_STMT (lhs)(tree_check ((lhs), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1742, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
1743 if (gimple_bb (stmt) != gimple_bb (*nop_reduc)
1744 || !is_gimple_assign (stmt))
1745 return false;
1746
1747 *has_nop = true;
1748 reduction_op = gimple_assign_rhs_code (stmt);
1749 }
1750
1751 if (reduction_op != PLUS_EXPR
35
Assuming 'reduction_op' is equal to PLUS_EXPR
1752 && reduction_op != MINUS_EXPR
1753 && reduction_op != MULT_EXPR
1754 && reduction_op != BIT_IOR_EXPR
1755 && reduction_op != BIT_XOR_EXPR
1756 && reduction_op != BIT_AND_EXPR)
1757 return false;
1758 r_op1 = gimple_assign_rhs1 (stmt);
1759 r_op2 = gimple_assign_rhs2 (stmt);
1760
1761 r_nop1 = strip_nop_cond_scalar_reduction (*has_nop, r_op1);
1762 r_nop2 = strip_nop_cond_scalar_reduction (*has_nop, r_op2);
1763
1764 /* Make R_OP1 to hold reduction variable. */
1765 if (r_nop2 == PHI_RESULT (header_phi)get_def_from_ptr (gimple_phi_result_ptr (header_phi))
36
Assuming the condition is false
1766 && commutative_tree_code (reduction_op))
1767 {
1768 std::swap (r_op1, r_op2);
1769 std::swap (r_nop1, r_nop2);
1770 }
1771 else if (r_nop1 != PHI_RESULT (header_phi)get_def_from_ptr (gimple_phi_result_ptr (header_phi)))
37
Assuming the condition is false
38
Taking false branch
1772 return false;
1773
1774 if (*has_nop)
39
Taking false branch
1775 {
1776 /* Check that R_NOP1 is used in nop_stmt or in PHI only. */
1777 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_nop1)for ((use_p) = first_readonly_imm_use (&(imm_iter), (r_nop1
)); !end_readonly_imm_use_p (&(imm_iter)); (void) ((use_p
) = next_readonly_imm_use (&(imm_iter))))
1778 {
1779 gimple *use_stmt = USE_STMT (use_p)(use_p)->loc.stmt;
1780 if (is_gimple_debug (use_stmt))
1781 continue;
1782 if (use_stmt == SSA_NAME_DEF_STMT (r_op1)(tree_check ((r_op1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1782, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
)
1783 continue;
1784 if (use_stmt != phi)
1785 return false;
1786 }
1787 }
1788
1789 /* Check that R_OP1 is used in reduction stmt or in PHI only. */
1790 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, r_op1)for ((use_p) = first_readonly_imm_use (&(imm_iter), (r_op1
)); !end_readonly_imm_use_p (&(imm_iter)); (void) ((use_p
) = next_readonly_imm_use (&(imm_iter))))
40
Loop condition is false. Execution continues on line 1801
1791 {
1792 gimple *use_stmt = USE_STMT (use_p)(use_p)->loc.stmt;
1793 if (is_gimple_debug (use_stmt))
1794 continue;
1795 if (use_stmt == stmt)
1796 continue;
1797 if (gimple_code (use_stmt) != GIMPLE_PHI)
1798 return false;
1799 }
1800
1801 *op0 = r_op1; *op1 = r_op2;
1802 *reduc = stmt;
1803 return true;
41
Returning without writing to '*nop_reduc'
1804}
1805
1806/* Converts conditional scalar reduction into unconditional form, e.g.
1807 bb_4
1808 if (_5 != 0) goto bb_5 else goto bb_6
1809 end_bb_4
1810 bb_5
1811 res_6 = res_13 + 1;
1812 end_bb_5
1813 bb_6
1814 # res_2 = PHI <res_13(4), res_6(5)>
1815 end_bb_6
1816
1817 will be converted into sequence
1818 _ifc__1 = _5 != 0 ? 1 : 0;
1819 res_2 = res_13 + _ifc__1;
1820 Argument SWAP tells that arguments of conditional expression should be
1821 swapped.
1822 Returns rhs of resulting PHI assignment. */
1823
1824static tree
1825convert_scalar_cond_reduction (gimple *reduc, gimple_stmt_iterator *gsi,
1826 tree cond, tree op0, tree op1, bool swap,
1827 bool has_nop, gimple* nop_reduc)
1828{
1829 gimple_stmt_iterator stmt_it;
1830 gimple *new_assign;
1831 tree rhs;
1832 tree rhs1 = gimple_assign_rhs1 (reduc);
1833 tree tmp = make_temp_ssa_name (TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1833, __FUNCTION__))->typed.type)
, NULLnullptr, "_ifc_");
1834 tree c;
1835 enum tree_code reduction_op = gimple_assign_rhs_code (reduc);
1836 tree op_nochange = neutral_op_for_reduction (TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1836, __FUNCTION__))->typed.type)
, reduction_op, NULLnullptr);
1837 gimple_seq stmts = NULLnullptr;
1838
1839 if (dump_file && (dump_flags & TDF_DETAILS))
1840 {
1841 fprintf (dump_file, "Found cond scalar reduction.\n");
1842 print_gimple_stmt (dump_file, reduc, 0, TDF_SLIM);
1843 }
1844
1845 /* Build cond expression using COND and constant operand
1846 of reduction rhs. */
1847 c = fold_build_cond_expr (TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1847, __FUNCTION__))->typed.type)
,
1848 unshare_expr (cond),
1849 swap ? op_nochange : op1,
1850 swap ? op1 : op_nochange);
1851
1852 /* Create assignment stmt and insert it at GSI. */
1853 new_assign = gimple_build_assign (tmp, c);
1854 gsi_insert_before (gsi, new_assign, GSI_SAME_STMT);
1855 /* Build rhs for unconditional increment/decrement/logic_operation. */
1856 rhs = gimple_build (&stmts, reduction_op,
1857 TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1857, __FUNCTION__))->typed.type)
, op0, tmp);
1858
1859 if (has_nop)
1860 {
1861 rhs = gimple_convert (&stmts,
1862 TREE_TYPE (gimple_assign_lhs (nop_reduc))((contains_struct_check ((gimple_assign_lhs (nop_reduc)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1862, __FUNCTION__))->typed.type)
, rhs);
1863 stmt_it = gsi_for_stmt (nop_reduc);
1864 gsi_remove (&stmt_it, true);
1865 release_defs (nop_reduc);
1866 }
1867 gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
1868
1869 /* Delete original reduction stmt. */
1870 stmt_it = gsi_for_stmt (reduc);
1871 gsi_remove (&stmt_it, true);
1872 release_defs (reduc);
1873 return rhs;
1874}
1875
1876/* Produce condition for all occurrences of ARG in PHI node. */
1877
1878static tree
1879gen_phi_arg_condition (gphi *phi, vec<int> *occur,
1880 gimple_stmt_iterator *gsi)
1881{
1882 int len;
1883 int i;
1884 tree cond = NULL_TREE(tree) nullptr;
1885 tree c;
1886 edge e;
1887
1888 len = occur->length ();
1889 gcc_assert (len > 0)((void)(!(len > 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1889, __FUNCTION__), 0 : 0))
;
1890 for (i = 0; i < len; i++)
1891 {
1892 e = gimple_phi_arg_edge (phi, (*occur)[i]);
1893 c = bb_predicate (e->src);
1894 if (is_true_predicate (c))
1895 {
1896 cond = c;
1897 break;
1898 }
1899 c = force_gimple_operand_gsi (gsi, unshare_expr (c),
1900 true, NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
1901 if (cond != NULL_TREE(tree) nullptr)
1902 {
1903 /* Must build OR expression. */
1904 cond = fold_or_predicates (EXPR_LOCATION (c)((((c)) && ((tree_code_type_tmpl <0>::tree_code_type
[(int) (((enum tree_code) ((c))->base.code))]) >= tcc_reference
&& (tree_code_type_tmpl <0>::tree_code_type[(int
) (((enum tree_code) ((c))->base.code))]) <= tcc_expression
)) ? (c)->exp.locus : ((location_t) 0))
, c, cond);
1905 cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), true,
1906 NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
1907 }
1908 else
1909 cond = c;
1910 }
1911 gcc_assert (cond != NULL_TREE)((void)(!(cond != (tree) nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1911, __FUNCTION__), 0 : 0))
;
1912 return cond;
1913}
1914
1915/* Replace a scalar PHI node with a COND_EXPR using COND as condition.
1916 This routine can handle PHI nodes with more than two arguments.
1917
1918 For example,
1919 S1: A = PHI <x1(1), x2(5)>
1920 is converted into,
1921 S2: A = cond ? x1 : x2;
1922
1923 The generated code is inserted at GSI that points to the top of
1924 basic block's statement list.
1925 If PHI node has more than two arguments a chain of conditional
1926 expression is produced. */
1927
1928
1929static void
1930predicate_scalar_phi (gphi *phi, gimple_stmt_iterator *gsi)
1931{
1932 gimple *new_stmt = NULLnullptr, *reduc, *nop_reduc;
1
'nop_reduc' declared without an initial value
1933 tree rhs, res, arg0, arg1, op0, op1, scev;
1934 tree cond;
1935 unsigned int index0;
1936 unsigned int max, args_len;
1937 edge e;
1938 basic_block bb;
1939 unsigned int i;
1940 bool has_nop;
1941
1942 res = gimple_phi_result (phi);
1943 if (virtual_operand_p (res))
1944 return;
1945
1946 if ((rhs = degenerate_phi_result (phi))
2
Assuming 'rhs' is null
1947 || ((scev = analyze_scalar_evolution (gimple_bb (phi)->loop_father,
3
Assuming 'scev' is null
1948 res))
1949 && !chrec_contains_undetermined (scev)
1950 && scev != res
1951 && (rhs = gimple_phi_arg_def (phi, 0))))
1952 {
1953 if (dump_file && (dump_flags & TDF_DETAILS))
1954 {
1955 fprintf (dump_file, "Degenerate phi!\n");
1956 print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
1957 }
1958 new_stmt = gimple_build_assign (res, rhs);
1959 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
1960 update_stmt (new_stmt);
1961 return;
1962 }
1963
1964 bb = gimple_bb (phi);
1965 if (EDGE_COUNT (bb->preds)vec_safe_length (bb->preds) == 2)
4
Assuming the condition is true
5
Taking true branch
1966 {
1967 /* Predicate ordinary PHI node with 2 arguments. */
1968 edge first_edge, second_edge;
1969 basic_block true_bb;
1970 first_edge = EDGE_PRED (bb, 0)(*(bb)->preds)[(0)];
1971 second_edge = EDGE_PRED (bb, 1)(*(bb)->preds)[(1)];
1972 cond = bb_predicate (first_edge->src);
1973 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR)
6
Assuming field 'code' is not equal to TRUTH_NOT_EXPR
7
Taking false branch
1974 std::swap (first_edge, second_edge);
1975 if (EDGE_COUNT (first_edge->src->succs)vec_safe_length (first_edge->src->succs) > 1)
8
Taking false branch
1976 {
1977 cond = bb_predicate (second_edge->src);
1978 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR)
1979 cond = TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 1979, __FUNCTION__)))))
;
1980 else
1981 first_edge = second_edge;
1982 }
1983 else
1984 cond = bb_predicate (first_edge->src);
1985 /* Gimplify the condition to a valid cond-expr conditonal operand. */
1986 cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), true,
1987 NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
1988 true_bb = first_edge->src;
1989 if (EDGE_PRED (bb, 1)(*(bb)->preds)[(1)]->src == true_bb)
9
Assuming 'true_bb' is not equal to field 'src'
10
Taking false branch
1990 {
1991 arg0 = gimple_phi_arg_def (phi, 1);
1992 arg1 = gimple_phi_arg_def (phi, 0);
1993 }
1994 else
1995 {
1996 arg0 = gimple_phi_arg_def (phi, 0);
1997 arg1 = gimple_phi_arg_def (phi, 1);
1998 }
1999 if (is_cond_scalar_reduction (phi, &reduc, arg0, arg1,
11
Calling 'is_cond_scalar_reduction'
42
Returning from 'is_cond_scalar_reduction'
43
Taking true branch
2000 &op0, &op1, false, &has_nop,
2001 &nop_reduc))
2002 {
2003 /* Convert reduction stmt into vectorizable form. */
2004 rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
45
8th function call argument is an uninitialized value
2005 true_bb != gimple_bb (reduc),
44
Assuming the condition is false
2006 has_nop, nop_reduc);
2007 redundant_ssa_names.safe_push (std::make_pair (res, rhs));
2008 }
2009 else
2010 /* Build new RHS using selected condition and arguments. */
2011 rhs = fold_build_cond_expr (TREE_TYPE (res)((contains_struct_check ((res), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2011, __FUNCTION__))->typed.type)
, unshare_expr (cond),
2012 arg0, arg1);
2013 new_stmt = gimple_build_assign (res, rhs);
2014 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
2015 gimple_stmt_iterator new_gsi = gsi_for_stmt (new_stmt);
2016 if (fold_stmt (&new_gsi, follow_all_ssa_edges))
2017 {
2018 new_stmt = gsi_stmt (new_gsi);
2019 update_stmt (new_stmt);
2020 }
2021
2022 if (dump_file && (dump_flags & TDF_DETAILS))
2023 {
2024 fprintf (dump_file, "new phi replacement stmt\n");
2025 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
2026 }
2027 return;
2028 }
2029
2030 /* Create hashmap for PHI node which contain vector of argument indexes
2031 having the same value. */
2032 bool swap = false;
2033 hash_map<tree_operand_hash, auto_vec<int> > phi_arg_map;
2034 unsigned int num_args = gimple_phi_num_args (phi);
2035 int max_ind = -1;
2036 /* Vector of different PHI argument values. */
2037 auto_vec<tree> args (num_args);
2038
2039 /* Compute phi_arg_map. */
2040 for (i = 0; i < num_args; i++)
2041 {
2042 tree arg;
2043
2044 arg = gimple_phi_arg_def (phi, i);
2045 if (!phi_arg_map.get (arg))
2046 args.quick_push (arg);
2047 phi_arg_map.get_or_insert (arg).safe_push (i);
2048 }
2049
2050 /* Determine element with max number of occurrences. */
2051 max_ind = -1;
2052 max = 1;
2053 args_len = args.length ();
2054 for (i = 0; i < args_len; i++)
2055 {
2056 unsigned int len;
2057 if ((len = phi_arg_map.get (args[i])->length ()) > max)
2058 {
2059 max_ind = (int) i;
2060 max = len;
2061 }
2062 }
2063
2064 /* Put element with max number of occurences to the end of ARGS. */
2065 if (max_ind != -1 && max_ind +1 != (int) args_len)
2066 std::swap (args[args_len - 1], args[max_ind]);
2067
2068 /* Handle one special case when number of arguments with different values
2069 is equal 2 and one argument has the only occurrence. Such PHI can be
2070 handled as if would have only 2 arguments. */
2071 if (args_len == 2 && phi_arg_map.get (args[0])->length () == 1)
2072 {
2073 vec<int> *indexes;
2074 indexes = phi_arg_map.get (args[0]);
2075 index0 = (*indexes)[0];
2076 arg0 = args[0];
2077 arg1 = args[1];
2078 e = gimple_phi_arg_edge (phi, index0);
2079 cond = bb_predicate (e->src);
2080 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR)
2081 {
2082 swap = true;
2083 cond = TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2083, __FUNCTION__)))))
;
2084 }
2085 /* Gimplify the condition to a valid cond-expr conditonal operand. */
2086 cond = force_gimple_operand_gsi (gsi, unshare_expr (cond), true,
2087 NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
2088 if (!(is_cond_scalar_reduction (phi, &reduc, arg0 , arg1,
2089 &op0, &op1, true, &has_nop, &nop_reduc)))
2090 rhs = fold_build_cond_expr (TREE_TYPE (res)((contains_struct_check ((res), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2090, __FUNCTION__))->typed.type)
, unshare_expr (cond),
2091 swap? arg1 : arg0,
2092 swap? arg0 : arg1);
2093 else
2094 {
2095 /* Convert reduction stmt into vectorizable form. */
2096 rhs = convert_scalar_cond_reduction (reduc, gsi, cond, op0, op1,
2097 swap,has_nop, nop_reduc);
2098 redundant_ssa_names.safe_push (std::make_pair (res, rhs));
2099 }
2100 new_stmt = gimple_build_assign (res, rhs);
2101 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
2102 update_stmt (new_stmt);
2103 }
2104 else
2105 {
2106 /* Common case. */
2107 vec<int> *indexes;
2108 tree type = TREE_TYPE (gimple_phi_result (phi))((contains_struct_check ((gimple_phi_result (phi)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2108, __FUNCTION__))->typed.type)
;
2109 tree lhs;
2110 arg1 = args[1];
2111 for (i = 0; i < args_len; i++)
2112 {
2113 arg0 = args[i];
2114 indexes = phi_arg_map.get (args[i]);
2115 if (i != args_len - 1)
2116 lhs = make_temp_ssa_name (type, NULLnullptr, "_ifc_");
2117 else
2118 lhs = res;
2119 cond = gen_phi_arg_condition (phi, indexes, gsi);
2120 rhs = fold_build_cond_expr (type, unshare_expr (cond),
2121 arg0, arg1);
2122 new_stmt = gimple_build_assign (lhs, rhs);
2123 gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
2124 update_stmt (new_stmt);
2125 arg1 = lhs;
2126 }
2127 }
2128
2129 if (dump_file && (dump_flags & TDF_DETAILS))
2130 {
2131 fprintf (dump_file, "new extended phi replacement stmt\n");
2132 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
2133 }
2134}
2135
2136/* Replaces in LOOP all the scalar phi nodes other than those in the
2137 LOOP->header block with conditional modify expressions. */
2138
2139static void
2140predicate_all_scalar_phis (class loop *loop)
2141{
2142 basic_block bb;
2143 unsigned int orig_loop_num_nodes = loop->num_nodes;
2144 unsigned int i;
2145
2146 for (i = 1; i < orig_loop_num_nodes; i++)
2147 {
2148 gphi *phi;
2149 gimple_stmt_iterator gsi;
2150 gphi_iterator phi_gsi;
2151 bb = ifc_bbs[i];
2152
2153 if (bb == loop->header)
2154 continue;
2155
2156 phi_gsi = gsi_start_phis (bb);
2157 if (gsi_end_p (phi_gsi))
2158 continue;
2159
2160 gsi = gsi_after_labels (bb);
2161 while (!gsi_end_p (phi_gsi))
2162 {
2163 phi = phi_gsi.phi ();
2164 if (virtual_operand_p (gimple_phi_result (phi)))
2165 gsi_next (&phi_gsi);
2166 else
2167 {
2168 predicate_scalar_phi (phi, &gsi);
2169 remove_phi_node (&phi_gsi, false);
2170 }
2171 }
2172 }
2173}
2174
2175/* Insert in each basic block of LOOP the statements produced by the
2176 gimplification of the predicates. */
2177
2178static void
2179insert_gimplified_predicates (loop_p loop)
2180{
2181 unsigned int i;
2182
2183 for (i = 0; i < loop->num_nodes; i++)
2184 {
2185 basic_block bb = ifc_bbs[i];
2186 gimple_seq stmts;
2187 if (!is_predicated (bb))
2188 gcc_assert (bb_predicate_gimplified_stmts (bb) == NULL)((void)(!(bb_predicate_gimplified_stmts (bb) == nullptr) ? fancy_abort
("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2188, __FUNCTION__), 0 : 0))
;
2189 if (!is_predicated (bb))
2190 {
2191 /* Do not insert statements for a basic block that is not
2192 predicated. Also make sure that the predicate of the
2193 basic block is set to true. */
2194 reset_bb_predicate (bb);
2195 continue;
2196 }
2197
2198 stmts = bb_predicate_gimplified_stmts (bb);
2199 if (stmts)
2200 {
2201 if (need_to_predicate)
2202 {
2203 /* Insert the predicate of the BB just after the label,
2204 as the if-conversion of memory writes will use this
2205 predicate. */
2206 gimple_stmt_iterator gsi = gsi_after_labels (bb);
2207 gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
2208 }
2209 else
2210 {
2211 /* Insert the predicate of the BB at the end of the BB
2212 as this would reduce the register pressure: the only
2213 use of this predicate will be in successor BBs. */
2214 gimple_stmt_iterator gsi = gsi_last_bb (bb);
2215
2216 if (gsi_end_p (gsi)
2217 || stmt_ends_bb_p (gsi_stmt (gsi)))
2218 gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
2219 else
2220 gsi_insert_seq_after (&gsi, stmts, GSI_SAME_STMT);
2221 }
2222
2223 /* Once the sequence is code generated, set it to NULL. */
2224 set_bb_predicate_gimplified_stmts (bb, NULLnullptr);
2225 }
2226 }
2227}
2228
2229/* Helper function for predicate_statements. Returns index of existent
2230 mask if it was created for given SIZE and -1 otherwise. */
2231
2232static int
2233mask_exists (int size, const vec<int> &vec)
2234{
2235 unsigned int ix;
2236 int v;
2237 FOR_EACH_VEC_ELT (vec, ix, v)for (ix = 0; (vec).iterate ((ix), &(v)); ++(ix))
2238 if (v == size)
2239 return (int) ix;
2240 return -1;
2241}
2242
2243/* Helper function for predicate_statements. STMT is a memory read or
2244 write and it needs to be predicated by MASK. Return a statement
2245 that does so. */
2246
2247static gimple *
2248predicate_load_or_store (gimple_stmt_iterator *gsi, gassign *stmt, tree mask)
2249{
2250 gcall *new_stmt;
2251
2252 tree lhs = gimple_assign_lhs (stmt);
2253 tree rhs = gimple_assign_rhs1 (stmt);
2254 tree ref = TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == SSA_NAME ? rhs : lhs;
2255 mark_addressable (ref);
2256 tree addr = force_gimple_operand_gsi (gsi, build_fold_addr_expr (ref)build_fold_addr_expr_loc (((location_t) 0), (ref)),
2257 true, NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
2258 tree ptr = build_int_cst (reference_alias_ptr_type (ref),
2259 get_object_alignment (ref));
2260 /* Copy points-to info if possible. */
2261 if (TREE_CODE (addr)((enum tree_code) (addr)->base.code) == SSA_NAME && !SSA_NAME_PTR_INFO (addr)(tree_check ((addr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2261, __FUNCTION__, (SSA_NAME)))->ssa_name.info.ptr_info
)
2262 copy_ref_info (build2 (MEM_REF, TREE_TYPE (ref)((contains_struct_check ((ref), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2262, __FUNCTION__))->typed.type)
, addr, ptr),
2263 ref);
2264 if (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == SSA_NAME)
2265 {
2266 new_stmt
2267 = gimple_build_call_internal (IFN_MASK_LOAD, 3, addr,
2268 ptr, mask);
2269 gimple_call_set_lhs (new_stmt, lhs);
2270 gimple_set_vuse (new_stmt, gimple_vuse (stmt));
2271 }
2272 else
2273 {
2274 new_stmt
2275 = gimple_build_call_internal (IFN_MASK_STORE, 4, addr, ptr,
2276 mask, rhs);
2277 gimple_move_vops (new_stmt, stmt);
2278 }
2279 gimple_call_set_nothrow (new_stmt, true);
2280 return new_stmt;
2281}
2282
2283/* STMT uses OP_LHS. Check whether it is equivalent to:
2284
2285 ... = OP_MASK ? OP_LHS : X;
2286
2287 Return X if so, otherwise return null. OP_MASK is an SSA_NAME that is
2288 known to have value OP_COND. */
2289
2290static tree
2291check_redundant_cond_expr (gimple *stmt, tree op_mask, tree op_cond,
2292 tree op_lhs)
2293{
2294 gassign *assign = dyn_cast <gassign *> (stmt);
2295 if (!assign || gimple_assign_rhs_code (assign) != COND_EXPR)
2296 return NULL_TREE(tree) nullptr;
2297
2298 tree use_cond = gimple_assign_rhs1 (assign);
2299 tree if_true = gimple_assign_rhs2 (assign);
2300 tree if_false = gimple_assign_rhs3 (assign);
2301
2302 if ((use_cond == op_mask || operand_equal_p (use_cond, op_cond, 0))
2303 && if_true == op_lhs)
2304 return if_false;
2305
2306 if (inverse_conditions_p (use_cond, op_cond) && if_false == op_lhs)
2307 return if_true;
2308
2309 return NULL_TREE(tree) nullptr;
2310}
2311
2312/* Return true if VALUE is available for use at STMT. SSA_NAMES is
2313 the set of SSA names defined earlier in STMT's block. */
2314
2315static bool
2316value_available_p (gimple *stmt, hash_set<tree_ssa_name_hash> *ssa_names,
2317 tree value)
2318{
2319 if (is_gimple_min_invariant (value))
2320 return true;
2321
2322 if (TREE_CODE (value)((enum tree_code) (value)->base.code) == SSA_NAME)
2323 {
2324 if (SSA_NAME_IS_DEFAULT_DEF (value)(tree_check ((value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2324, __FUNCTION__, (SSA_NAME)))->base.default_def_flag
)
2325 return true;
2326
2327 basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (value)(tree_check ((value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2327, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
);
2328 basic_block use_bb = gimple_bb (stmt);
2329 return (def_bb == use_bb
2330 ? ssa_names->contains (value)
2331 : dominated_by_p (CDI_DOMINATORS, use_bb, def_bb));
2332 }
2333
2334 return false;
2335}
2336
2337/* Helper function for predicate_statements. STMT is a potentially-trapping
2338 arithmetic operation that needs to be predicated by MASK, an SSA_NAME that
2339 has value COND. Return a statement that does so. SSA_NAMES is the set of
2340 SSA names defined earlier in STMT's block. */
2341
2342static gimple *
2343predicate_rhs_code (gassign *stmt, tree mask, tree cond,
2344 hash_set<tree_ssa_name_hash> *ssa_names)
2345{
2346 tree lhs = gimple_assign_lhs (stmt);
2347 tree_code code = gimple_assign_rhs_code (stmt);
2348 unsigned int nops = gimple_num_ops (stmt);
2349 internal_fn cond_fn = get_conditional_internal_fn (code);
2350
2351 /* Construct the arguments to the conditional internal function. */
2352 auto_vec<tree, 8> args;
2353 args.safe_grow (nops + 1, true);
2354 args[0] = mask;
2355 for (unsigned int i = 1; i < nops; ++i)
2356 args[i] = gimple_op (stmt, i);
2357 args[nops] = NULL_TREE(tree) nullptr;
2358
2359 /* Look for uses of the result to see whether they are COND_EXPRs that can
2360 be folded into the conditional call. */
2361 imm_use_iterator imm_iter;
2362 gimple *use_stmt;
2363 FOR_EACH_IMM_USE_STMT (use_stmt, imm_iter, lhs)for (struct auto_end_imm_use_stmt_traverse auto_end_imm_use_stmt_traverse
((((use_stmt) = first_imm_use_stmt (&(imm_iter), (lhs)))
, &(imm_iter))); !end_imm_use_stmt_p (&(imm_iter)); (
void) ((use_stmt) = next_imm_use_stmt (&(imm_iter))))
2364 {
2365 tree new_else = check_redundant_cond_expr (use_stmt, mask, cond, lhs);
2366 if (new_else && value_available_p (stmt, ssa_names, new_else))
2367 {
2368 if (!args[nops])
2369 args[nops] = new_else;
2370 if (operand_equal_p (new_else, args[nops], 0))
2371 {
2372 /* We have:
2373
2374 LHS = IFN_COND (MASK, ..., ELSE);
2375 X = MASK ? LHS : ELSE;
2376
2377 which makes X equivalent to LHS. */
2378 tree use_lhs = gimple_assign_lhs (use_stmt);
2379 redundant_ssa_names.safe_push (std::make_pair (use_lhs, lhs));
2380 }
2381 }
2382 }
2383 if (!args[nops])
2384 args[nops] = targetm.preferred_else_value (cond_fn, TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2384, __FUNCTION__))->typed.type)
,
2385 nops - 1, &args[1]);
2386
2387 /* Create and insert the call. */
2388 gcall *new_stmt = gimple_build_call_internal_vec (cond_fn, args);
2389 gimple_call_set_lhs (new_stmt, lhs);
2390 gimple_call_set_nothrow (new_stmt, true);
2391
2392 return new_stmt;
2393}
2394
2395/* Predicate each write to memory in LOOP.
2396
2397 This function transforms control flow constructs containing memory
2398 writes of the form:
2399
2400 | for (i = 0; i < N; i++)
2401 | if (cond)
2402 | A[i] = expr;
2403
2404 into the following form that does not contain control flow:
2405
2406 | for (i = 0; i < N; i++)
2407 | A[i] = cond ? expr : A[i];
2408
2409 The original CFG looks like this:
2410
2411 | bb_0
2412 | i = 0
2413 | end_bb_0
2414 |
2415 | bb_1
2416 | if (i < N) goto bb_5 else goto bb_2
2417 | end_bb_1
2418 |
2419 | bb_2
2420 | cond = some_computation;
2421 | if (cond) goto bb_3 else goto bb_4
2422 | end_bb_2
2423 |
2424 | bb_3
2425 | A[i] = expr;
2426 | goto bb_4
2427 | end_bb_3
2428 |
2429 | bb_4
2430 | goto bb_1
2431 | end_bb_4
2432
2433 insert_gimplified_predicates inserts the computation of the COND
2434 expression at the beginning of the destination basic block:
2435
2436 | bb_0
2437 | i = 0
2438 | end_bb_0
2439 |
2440 | bb_1
2441 | if (i < N) goto bb_5 else goto bb_2
2442 | end_bb_1
2443 |
2444 | bb_2
2445 | cond = some_computation;
2446 | if (cond) goto bb_3 else goto bb_4
2447 | end_bb_2
2448 |
2449 | bb_3
2450 | cond = some_computation;
2451 | A[i] = expr;
2452 | goto bb_4
2453 | end_bb_3
2454 |
2455 | bb_4
2456 | goto bb_1
2457 | end_bb_4
2458
2459 predicate_statements is then predicating the memory write as follows:
2460
2461 | bb_0
2462 | i = 0
2463 | end_bb_0
2464 |
2465 | bb_1
2466 | if (i < N) goto bb_5 else goto bb_2
2467 | end_bb_1
2468 |
2469 | bb_2
2470 | if (cond) goto bb_3 else goto bb_4
2471 | end_bb_2
2472 |
2473 | bb_3
2474 | cond = some_computation;
2475 | A[i] = cond ? expr : A[i];
2476 | goto bb_4
2477 | end_bb_3
2478 |
2479 | bb_4
2480 | goto bb_1
2481 | end_bb_4
2482
2483 and finally combine_blocks removes the basic block boundaries making
2484 the loop vectorizable:
2485
2486 | bb_0
2487 | i = 0
2488 | if (i < N) goto bb_5 else goto bb_1
2489 | end_bb_0
2490 |
2491 | bb_1
2492 | cond = some_computation;
2493 | A[i] = cond ? expr : A[i];
2494 | if (i < N) goto bb_5 else goto bb_4
2495 | end_bb_1
2496 |
2497 | bb_4
2498 | goto bb_1
2499 | end_bb_4
2500*/
2501
2502static void
2503predicate_statements (loop_p loop)
2504{
2505 unsigned int i, orig_loop_num_nodes = loop->num_nodes;
2506 auto_vec<int, 1> vect_sizes;
2507 auto_vec<tree, 1> vect_masks;
2508 hash_set<tree_ssa_name_hash> ssa_names;
2509
2510 for (i = 1; i < orig_loop_num_nodes; i++)
2511 {
2512 gimple_stmt_iterator gsi;
2513 basic_block bb = ifc_bbs[i];
2514 tree cond = bb_predicate (bb);
2515 bool swap;
2516 int index;
2517
2518 if (is_true_predicate (cond))
2519 continue;
2520
2521 swap = false;
2522 if (TREE_CODE (cond)((enum tree_code) (cond)->base.code) == TRUTH_NOT_EXPR)
2523 {
2524 swap = true;
2525 cond = TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2525, __FUNCTION__)))))
;
2526 }
2527
2528 vect_sizes.truncate (0);
2529 vect_masks.truncate (0);
2530
2531 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
2532 {
2533 gassign *stmt = dyn_cast <gassign *> (gsi_stmt (gsi));
2534 tree lhs;
2535 if (!stmt)
2536 ;
2537 else if (is_false_predicate (cond)
2538 && gimple_vdef (stmt))
2539 {
2540 unlink_stmt_vdef (stmt);
2541 gsi_remove (&gsi, true);
2542 release_defs (stmt);
2543 continue;
2544 }
2545 else if (gimple_plf (stmt, GF_PLF_2)
2546 && is_gimple_assign (stmt))
2547 {
2548 tree lhs = gimple_assign_lhs (stmt);
2549 tree mask;
2550 gimple *new_stmt;
2551 gimple_seq stmts = NULLnullptr;
2552 machine_mode mode = TYPE_MODE (TREE_TYPE (lhs))((((enum tree_code) ((tree_class_check ((((contains_struct_check
((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2552, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2552, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode
(((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2552, __FUNCTION__))->typed.type)) : (((contains_struct_check
((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2552, __FUNCTION__))->typed.type))->type_common.mode)
;
2553 /* We checked before setting GF_PLF_2 that an equivalent
2554 integer mode exists. */
2555 int bitsize = GET_MODE_BITSIZE (mode).to_constant ();
2556 if (!vect_sizes.is_empty ()
2557 && (index = mask_exists (bitsize, vect_sizes)) != -1)
2558 /* Use created mask. */
2559 mask = vect_masks[index];
2560 else
2561 {
2562 if (COMPARISON_CLASS_P (cond)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code
) (cond)->base.code))] == tcc_comparison)
)
2563 mask = gimple_build (&stmts, TREE_CODE (cond)((enum tree_code) (cond)->base.code),
2564 boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE],
2565 TREE_OPERAND (cond, 0)(*((const_cast<tree*> (tree_operand_check ((cond), (0),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2565, __FUNCTION__)))))
,
2566 TREE_OPERAND (cond, 1)(*((const_cast<tree*> (tree_operand_check ((cond), (1),
"/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2566, __FUNCTION__)))))
);
2567 else
2568 mask = cond;
2569
2570 if (swap)
2571 {
2572 tree true_val
2573 = constant_boolean_node (true, TREE_TYPE (mask)((contains_struct_check ((mask), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2573, __FUNCTION__))->typed.type)
);
2574 mask = gimple_build (&stmts, BIT_XOR_EXPR,
2575 TREE_TYPE (mask)((contains_struct_check ((mask), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2575, __FUNCTION__))->typed.type)
, mask, true_val);
2576 }
2577 gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
2578
2579 /* Save mask and its size for further use. */
2580 vect_sizes.safe_push (bitsize);
2581 vect_masks.safe_push (mask);
2582 }
2583 if (gimple_assign_single_p (stmt))
2584 new_stmt = predicate_load_or_store (&gsi, stmt, mask);
2585 else
2586 new_stmt = predicate_rhs_code (stmt, mask, cond, &ssa_names);
2587
2588 gsi_replace (&gsi, new_stmt, true);
2589 }
2590 else if (((lhs = gimple_assign_lhs (stmt)), true)
2591 && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))(((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2591, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2591, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2591, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE
)
2592 || POINTER_TYPE_P (TREE_TYPE (lhs))(((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2592, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2592, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
)
)
2593 && TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (lhs))((((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2593, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE
|| ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2593, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE
) ? !global_options.x_flag_wrapv_pointer : (!(any_integral_type_check
((((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2593, __FUNCTION__))->typed.type)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2593, __FUNCTION__))->base.u.bits.unsigned_flag &&
!global_options.x_flag_wrapv && !global_options.x_flag_trapv
))
2594 && arith_code_with_undefined_signed_overflow
2595 (gimple_assign_rhs_code (stmt)))
2596 {
2597 gsi_remove (&gsi, true);
2598 gimple_seq stmts = rewrite_to_defined_overflow (stmt);
2599 bool first = true;
2600 for (gimple_stmt_iterator gsi2 = gsi_start (stmts);
2601 !gsi_end_p (gsi2);)
2602 {
2603 gassign *stmt2 = as_a <gassign *> (gsi_stmt (gsi2));
2604 gsi_remove (&gsi2, false);
2605 if (first)
2606 {
2607 gsi_insert_before (&gsi, stmt2, GSI_NEW_STMT);
2608 first = false;
2609 }
2610 else
2611 gsi_insert_after (&gsi, stmt2, GSI_NEW_STMT);
2612 }
2613 }
2614 else if (gimple_vdef (stmt))
2615 {
2616 tree lhs = gimple_assign_lhs (stmt);
2617 tree rhs = gimple_assign_rhs1 (stmt);
2618 tree type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2618, __FUNCTION__))->typed.type)
;
2619
2620 lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi);
2621 rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi);
2622 if (swap)
2623 std::swap (lhs, rhs);
2624 cond = force_gimple_operand_gsi (&gsi, unshare_expr (cond), true,
2625 NULL_TREE(tree) nullptr, true, GSI_SAME_STMT);
2626 rhs = fold_build_cond_expr (type, unshare_expr (cond), rhs, lhs);
2627 gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi));
2628 update_stmt (stmt);
2629 }
2630 else if (gimple_plf (stmt, GF_PLF_2)
2631 && is_gimple_call (stmt))
2632 {
2633 /* Convert functions that have a SIMD clone to IFN_MASK_CALL.
2634 This will cause the vectorizer to match the "in branch"
2635 clone variants, and serves to build the mask vector
2636 in a natural way. */
2637 gcall *call = dyn_cast <gcall *> (gsi_stmt (gsi));
2638 tree orig_fn = gimple_call_fn (call);
2639 int orig_nargs = gimple_call_num_args (call);
2640 auto_vec<tree> args;
2641 args.safe_push (orig_fn);
2642 for (int i = 0; i < orig_nargs; i++)
2643 args.safe_push (gimple_call_arg (call, i));
2644 args.safe_push (cond);
2645
2646 /* Replace the call with a IFN_MASK_CALL that has the extra
2647 condition parameter. */
2648 gcall *new_call = gimple_build_call_internal_vec (IFN_MASK_CALL,
2649 args);
2650 gimple_call_set_lhs (new_call, gimple_call_lhs (call));
2651 gsi_replace (&gsi, new_call, true);
2652 }
2653
2654 lhs = gimple_get_lhs (gsi_stmt (gsi));
2655 if (lhs && TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == SSA_NAME)
2656 ssa_names.add (lhs);
2657 gsi_next (&gsi);
2658 }
2659 ssa_names.empty ();
2660 }
2661}
2662
2663/* Remove all GIMPLE_CONDs and GIMPLE_LABELs of all the basic blocks
2664 other than the exit and latch of the LOOP. Also resets the
2665 GIMPLE_DEBUG information. */
2666
2667static void
2668remove_conditions_and_labels (loop_p loop)
2669{
2670 gimple_stmt_iterator gsi;
2671 unsigned int i;
2672
2673 for (i = 0; i < loop->num_nodes; i++)
2674 {
2675 basic_block bb = ifc_bbs[i];
2676
2677 if (bb_with_exit_edge_p (loop, bb)
2678 || bb == loop->latch)
2679 continue;
2680
2681 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
2682 switch (gimple_code (gsi_stmt (gsi)))
2683 {
2684 case GIMPLE_COND:
2685 case GIMPLE_LABEL:
2686 gsi_remove (&gsi, true);
2687 break;
2688
2689 case GIMPLE_DEBUG:
2690 /* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */
2691 if (gimple_debug_bind_p (gsi_stmt (gsi)))
2692 {
2693 gimple_debug_bind_reset_value (gsi_stmt (gsi));
2694 update_stmt (gsi_stmt (gsi));
2695 }
2696 gsi_next (&gsi);
2697 break;
2698
2699 default:
2700 gsi_next (&gsi);
2701 }
2702 }
2703}
2704
2705/* Combine all the basic blocks from LOOP into one or two super basic
2706 blocks. Replace PHI nodes with conditional modify expressions. */
2707
2708static void
2709combine_blocks (class loop *loop)
2710{
2711 basic_block bb, exit_bb, merge_target_bb;
2712 unsigned int orig_loop_num_nodes = loop->num_nodes;
2713 unsigned int i;
2714 edge e;
2715 edge_iterator ei;
2716
2717 remove_conditions_and_labels (loop);
2718 insert_gimplified_predicates (loop);
2719 predicate_all_scalar_phis (loop);
2720
2721 if (need_to_predicate || need_to_rewrite_undefined)
2722 predicate_statements (loop);
2723
2724 /* Merge basic blocks. */
2725 exit_bb = NULLnullptr;
2726 bool *predicated = XNEWVEC (bool, orig_loop_num_nodes)((bool *) xmalloc (sizeof (bool) * (orig_loop_num_nodes)));
2727 for (i = 0; i < orig_loop_num_nodes; i++)
2728 {
2729 bb = ifc_bbs[i];
2730 predicated[i] = !is_true_predicate (bb_predicate (bb));
2731 free_bb_predicate (bb);
2732 if (bb_with_exit_edge_p (loop, bb))
2733 {
2734 gcc_assert (exit_bb == NULL)((void)(!(exit_bb == nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2734, __FUNCTION__), 0 : 0))
;
2735 exit_bb = bb;
2736 }
2737 }
2738 gcc_assert (exit_bb != loop->latch)((void)(!(exit_bb != loop->latch) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2738, __FUNCTION__), 0 : 0))
;
2739
2740 merge_target_bb = loop->header;
2741
2742 /* Get at the virtual def valid for uses starting at the first block
2743 we merge into the header. Without a virtual PHI the loop has the
2744 same virtual use on all stmts. */
2745 gphi *vphi = get_virtual_phi (loop->header);
2746 tree last_vdef = NULL_TREE(tree) nullptr;
2747 if (vphi)
2748 {
2749 last_vdef = gimple_phi_result (vphi);
2750 for (gimple_stmt_iterator gsi = gsi_start_bb (loop->header);
2751 ! gsi_end_p (gsi); gsi_next (&gsi))
2752 if (gimple_vdef (gsi_stmt (gsi)))
2753 last_vdef = gimple_vdef (gsi_stmt (gsi));
2754 }
2755 for (i = 1; i < orig_loop_num_nodes; i++)
2756 {
2757 gimple_stmt_iterator gsi;
2758 gimple_stmt_iterator last;
2759
2760 bb = ifc_bbs[i];
2761
2762 if (bb == exit_bb || bb == loop->latch)
2763 continue;
2764
2765 /* We release virtual PHIs late because we have to propagate them
2766 out using the current VUSE. The def might be the one used
2767 after the loop. */
2768 vphi = get_virtual_phi (bb);
2769 if (vphi)
2770 {
2771 /* When there's just loads inside the loop a stray virtual
2772 PHI merging the uses can appear, update last_vdef from
2773 it. */
2774 if (!last_vdef)
2775 last_vdef = gimple_phi_arg_def (vphi, 0);
2776 imm_use_iterator iter;
2777 use_operand_p use_p;
2778 gimple *use_stmt;
2779 FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_phi_result (vphi))for (struct auto_end_imm_use_stmt_traverse auto_end_imm_use_stmt_traverse
((((use_stmt) = first_imm_use_stmt (&(iter), (gimple_phi_result
(vphi)))), &(iter))); !end_imm_use_stmt_p (&(iter));
(void) ((use_stmt) = next_imm_use_stmt (&(iter))))
2780 {
2781 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)for ((use_p) = first_imm_use_on_stmt (&(iter)); !end_imm_use_on_stmt_p
(&(iter)); (void) ((use_p) = next_imm_use_on_stmt (&
(iter))))
2782 SET_USE (use_p, last_vdef)set_ssa_use_from_ptr (use_p, last_vdef);
2783 }
2784 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))(tree_check ((gimple_phi_result (vphi)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2784, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
)
2785 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef)(tree_check ((last_vdef), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2785, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
= 1;
2786 gsi = gsi_for_stmt (vphi);
2787 remove_phi_node (&gsi, true);
2788 }
2789
2790 /* Make stmts member of loop->header and clear range info from all stmts
2791 in BB which is now no longer executed conditional on a predicate we
2792 could have derived it from. */
2793 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
2794 {
2795 gimple *stmt = gsi_stmt (gsi);
2796 gimple_set_bb (stmt, merge_target_bb);
2797 /* Update virtual operands. */
2798 if (last_vdef)
2799 {
2800 use_operand_p use_p = ssa_vuse_operand (stmt);
2801 if (use_p
2802 && USE_FROM_PTR (use_p)get_use_from_ptr (use_p) != last_vdef)
2803 SET_USE (use_p, last_vdef)set_ssa_use_from_ptr (use_p, last_vdef);
2804 if (gimple_vdef (stmt))
2805 last_vdef = gimple_vdef (stmt);
2806 }
2807 else
2808 /* If this is the first load we arrive at update last_vdef
2809 so we handle stray PHIs correctly. */
2810 last_vdef = gimple_vuse (stmt);
2811 if (predicated[i])
2812 {
2813 ssa_op_iter i;
2814 tree op;
2815 FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_DEF)for (op = op_iter_init_tree (&(i), stmt, 0x02); !op_iter_done
(&(i)); (void) (op = op_iter_next_tree (&(i))))
2816 reset_flow_sensitive_info (op);
2817 }
2818 }
2819
2820 /* Update stmt list. */
2821 last = gsi_last_bb (merge_target_bb);
2822 gsi_insert_seq_after_without_update (&last, bb_seq (bb), GSI_NEW_STMT);
2823 set_bb_seq (bb, NULLnullptr);
2824 }
2825
2826 /* Fixup virtual operands in the exit block. */
2827 if (exit_bb
2828 && exit_bb != loop->header)
2829 {
2830 /* We release virtual PHIs late because we have to propagate them
2831 out using the current VUSE. The def might be the one used
2832 after the loop. */
2833 vphi = get_virtual_phi (exit_bb);
2834 if (vphi)
2835 {
2836 /* When there's just loads inside the loop a stray virtual
2837 PHI merging the uses can appear, update last_vdef from
2838 it. */
2839 if (!last_vdef)
2840 last_vdef = gimple_phi_arg_def (vphi, 0);
2841 imm_use_iterator iter;
2842 use_operand_p use_p;
2843 gimple *use_stmt;
2844 FOR_EACH_IMM_USE_STMT (use_stmt, iter, gimple_phi_result (vphi))for (struct auto_end_imm_use_stmt_traverse auto_end_imm_use_stmt_traverse
((((use_stmt) = first_imm_use_stmt (&(iter), (gimple_phi_result
(vphi)))), &(iter))); !end_imm_use_stmt_p (&(iter));
(void) ((use_stmt) = next_imm_use_stmt (&(iter))))
2845 {
2846 FOR_EACH_IMM_USE_ON_STMT (use_p, iter)for ((use_p) = first_imm_use_on_stmt (&(iter)); !end_imm_use_on_stmt_p
(&(iter)); (void) ((use_p) = next_imm_use_on_stmt (&
(iter))))
2847 SET_USE (use_p, last_vdef)set_ssa_use_from_ptr (use_p, last_vdef);
2848 }
2849 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (vphi))(tree_check ((gimple_phi_result (vphi)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2849, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
)
2850 SSA_NAME_OCCURS_IN_ABNORMAL_PHI (last_vdef)(tree_check ((last_vdef), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 2850, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag
= 1;
2851 gimple_stmt_iterator gsi = gsi_for_stmt (vphi);
2852 remove_phi_node (&gsi, true);
2853 }
2854 }
2855
2856 /* Now remove all the edges in the loop, except for those from the exit
2857 block and delete the blocks we elided. */
2858 for (i = 1; i < orig_loop_num_nodes; i++)
2859 {
2860 bb = ifc_bbs[i];
2861
2862 for (ei = ei_start (bb->preds)ei_start_1 (&(bb->preds)); (e = ei_safe_edge (ei));)
2863 {
2864 if (e->src == exit_bb)
2865 ei_next (&ei);
2866 else
2867 remove_edge (e);
2868 }
2869 }
2870 for (i = 1; i < orig_loop_num_nodes; i++)
2871 {
2872 bb = ifc_bbs[i];
2873
2874 if (bb == exit_bb || bb == loop->latch)
2875 continue;
2876
2877 delete_basic_block (bb);
2878 }
2879
2880 /* Re-connect the exit block. */
2881 if (exit_bb != NULLnullptr)
2882 {
2883 if (exit_bb != loop->header)
2884 {
2885 /* Connect this node to loop header. */
2886 make_single_succ_edge (loop->header, exit_bb, EDGE_FALLTHRU);
2887 set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header);
2888 }
2889
2890 /* Redirect non-exit edges to loop->latch. */
2891 FOR_EACH_EDGE (e, ei, exit_bb->succs)for ((ei) = ei_start_1 (&((exit_bb->succs))); ei_cond (
(ei), &(e)); ei_next (&(ei)))
2892 {
2893 if (!loop_exit_edge_p (loop, e))
2894 redirect_edge_and_branch (e, loop->latch);
2895 }
2896 set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb);
2897 }
2898 else
2899 {
2900 /* If the loop does not have an exit, reconnect header and latch. */
2901 make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
2902 set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
2903 }
2904
2905 /* If possible, merge loop header to the block with the exit edge.
2906 This reduces the number of basic blocks to two, to please the
2907 vectorizer that handles only loops with two nodes. */
2908 if (exit_bb
2909 && exit_bb != loop->header)
2910 {
2911 if (can_merge_blocks_p (loop->header, exit_bb))
2912 merge_blocks (loop->header, exit_bb);
2913 }
2914
2915 free (ifc_bbs);
2916 ifc_bbs = NULLnullptr;
2917 free (predicated);
2918}
2919
2920/* Version LOOP before if-converting it; the original loop
2921 will be if-converted, the new copy of the loop will not,
2922 and the LOOP_VECTORIZED internal call will be guarding which
2923 loop to execute. The vectorizer pass will fold this
2924 internal call into either true or false.
2925
2926 Note that this function intentionally invalidates profile. Both edges
2927 out of LOOP_VECTORIZED must have 100% probability so the profile remains
2928 consistent after the condition is folded in the vectorizer. */
2929
2930static class loop *
2931version_loop_for_if_conversion (class loop *loop, vec<gimple *> *preds)
2932{
2933 basic_block cond_bb;
2934 tree cond = make_ssa_name (boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE]);
2935 class loop *new_loop;
2936 gimple *g;
2937 gimple_stmt_iterator gsi;
2938 unsigned int save_length = 0;
2939
2940 g = gimple_build_call_internal (IFN_LOOP_VECTORIZED, 2,
2941 build_int_cst (integer_type_nodeinteger_types[itk_int], loop->num),
2942 integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]);
2943 gimple_call_set_lhs (g, cond);
2944
2945 void **saved_preds = NULLnullptr;
2946 if (any_complicated_phi || need_to_predicate)
2947 {
2948 /* Save BB->aux around loop_version as that uses the same field. */
2949 save_length = loop->inner ? loop->inner->num_nodes : loop->num_nodes;
2950 saved_preds = XALLOCAVEC (void *, save_length)((void * *) __builtin_alloca(sizeof (void *) * (save_length))
)
;
2951 for (unsigned i = 0; i < save_length; i++)
2952 saved_preds[i] = ifc_bbs[i]->aux;
2953 }
2954
2955 initialize_original_copy_tables ();
2956 /* At this point we invalidate porfile confistency until IFN_LOOP_VECTORIZED
2957 is re-merged in the vectorizer. */
2958 new_loop = loop_version (loop, cond, &cond_bb,
2959 profile_probability::always (),
2960 profile_probability::always (),
2961 profile_probability::always (),
2962 profile_probability::always (), true);
2963 free_original_copy_tables ();
2964
2965 if (any_complicated_phi || need_to_predicate)
2966 for (unsigned i = 0; i < save_length; i++)
2967 ifc_bbs[i]->aux = saved_preds[i];
2968
2969 if (new_loop == NULLnullptr)
2970 return NULLnullptr;
2971
2972 new_loop->dont_vectorize = true;
2973 new_loop->force_vectorize = false;
2974 gsi = gsi_last_bb (cond_bb);
2975 gimple_call_set_arg (g, 1, build_int_cst (integer_type_nodeinteger_types[itk_int], new_loop->num));
2976 if (preds)
2977 preds->safe_push (g);
2978 gsi_insert_before (&gsi, g, GSI_SAME_STMT);
2979 update_ssa (TODO_update_ssa_no_phi(1 << 12));
2980 return new_loop;
2981}
2982
2983/* Return true when LOOP satisfies the follow conditions that will
2984 allow it to be recognized by the vectorizer for outer-loop
2985 vectorization:
2986 - The loop is not the root node of the loop tree.
2987 - The loop has exactly one inner loop.
2988 - The loop has a single exit.
2989 - The loop header has a single successor, which is the inner
2990 loop header.
2991 - Each of the inner and outer loop latches have a single
2992 predecessor.
2993 - The loop exit block has a single predecessor, which is the
2994 inner loop's exit block. */
2995
2996static bool
2997versionable_outer_loop_p (class loop *loop)
2998{
2999 if (!loop_outer (loop)
3000 || loop->dont_vectorize
3001 || !loop->inner
3002 || loop->inner->next
3003 || !single_exit (loop)
3004 || !single_succ_p (loop->header)
3005 || single_succ (loop->header) != loop->inner->header
3006 || !single_pred_p (loop->latch)
3007 || !single_pred_p (loop->inner->latch))
3008 return false;
3009
3010 basic_block outer_exit = single_pred (loop->latch);
3011 basic_block inner_exit = single_pred (loop->inner->latch);
3012
3013 if (!single_pred_p (outer_exit) || single_pred (outer_exit) != inner_exit)
3014 return false;
3015
3016 if (dump_file)
3017 fprintf (dump_file, "Found vectorizable outer loop for versioning\n");
3018
3019 return true;
3020}
3021
3022/* Performs splitting of critical edges. Skip splitting and return false
3023 if LOOP will not be converted because:
3024
3025 - LOOP is not well formed.
3026 - LOOP has PHI with more than MAX_PHI_ARG_NUM arguments.
3027
3028 Last restriction is valid only if AGGRESSIVE_IF_CONV is false. */
3029
3030static bool
3031ifcvt_split_critical_edges (class loop *loop, bool aggressive_if_conv)
3032{
3033 basic_block *body;
3034 basic_block bb;
3035 unsigned int num = loop->num_nodes;
3036 unsigned int i;
3037 gimple *stmt;
3038 edge e;
3039 edge_iterator ei;
3040 auto_vec<edge> critical_edges;
3041
3042 /* Loop is not well formed. */
3043 if (loop->inner)
3044 return false;
3045
3046 body = get_loop_body (loop);
3047 for (i = 0; i < num; i++)
3048 {
3049 bb = body[i];
3050 if (!aggressive_if_conv
3051 && phi_nodes (bb)
3052 && EDGE_COUNT (bb->preds)vec_safe_length (bb->preds) > MAX_PHI_ARG_NUM((unsigned) global_options.x_param_max_tree_if_conversion_phi_args
)
)
3053 {
3054 if (dump_file && (dump_flags & TDF_DETAILS))
3055 fprintf (dump_file,
3056 "BB %d has complicated PHI with more than %u args.\n",
3057 bb->index, MAX_PHI_ARG_NUM((unsigned) global_options.x_param_max_tree_if_conversion_phi_args
)
);
3058
3059 free (body);
3060 return false;
3061 }
3062 if (bb == loop->latch || bb_with_exit_edge_p (loop, bb))
3063 continue;
3064
3065 stmt = last_stmt (bb);
3066 /* Skip basic blocks not ending with conditional branch. */
3067 if (!stmt || gimple_code (stmt) != GIMPLE_COND)
3068 continue;
3069
3070 FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei)
, &(e)); ei_next (&(ei)))
3071 if (EDGE_CRITICAL_P (e)(vec_safe_length ((e)->src->succs) >= 2 && vec_safe_length
((e)->dest->preds) >= 2)
&& e->dest->loop_father == loop)
3072 critical_edges.safe_push (e);
3073 }
3074 free (body);
3075
3076 while (critical_edges.length () > 0)
3077 {
3078 e = critical_edges.pop ();
3079 /* Don't split if bb can be predicated along non-critical edge. */
3080 if (EDGE_COUNT (e->dest->preds)vec_safe_length (e->dest->preds) > 2 || all_preds_critical_p (e->dest))
3081 split_edge (e);
3082 }
3083
3084 return true;
3085}
3086
3087/* Delete redundant statements produced by predication which prevents
3088 loop vectorization. */
3089
3090static void
3091ifcvt_local_dce (class loop *loop)
3092{
3093 gimple *stmt;
3094 gimple *stmt1;
3095 gimple *phi;
3096 gimple_stmt_iterator gsi;
3097 auto_vec<gimple *> worklist;
3098 enum gimple_code code;
3099 use_operand_p use_p;
3100 imm_use_iterator imm_iter;
3101
3102 /* The loop has a single BB only. */
3103 basic_block bb = loop->header;
3104 tree latch_vdef = NULL_TREE(tree) nullptr;
3105
3106 worklist.create (64);
3107 /* Consider all phi as live statements. */
3108 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3109 {
3110 phi = gsi_stmt (gsi);
3111 gimple_set_plf (phi, GF_PLF_2, true);
3112 worklist.safe_push (phi);
3113 if (virtual_operand_p (gimple_phi_result (phi)))
3114 latch_vdef = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop))gimple_phi_arg_def (((phi)), ((loop_latch_edge (loop))->dest_idx
))
;
3115 }
3116 /* Consider load/store statements, CALL and COND as live. */
3117 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3118 {
3119 stmt = gsi_stmt (gsi);
3120 if (is_gimple_debug (stmt))
3121 {
3122 gimple_set_plf (stmt, GF_PLF_2, true);
3123 continue;
3124 }
3125 if (gimple_store_p (stmt) || gimple_assign_load_p (stmt))
3126 {
3127 gimple_set_plf (stmt, GF_PLF_2, true);
3128 worklist.safe_push (stmt);
3129 continue;
3130 }
3131 code = gimple_code (stmt);
3132 if (code == GIMPLE_COND || code == GIMPLE_CALL)
3133 {
3134 gimple_set_plf (stmt, GF_PLF_2, true);
3135 worklist.safe_push (stmt);
3136 continue;
3137 }
3138 gimple_set_plf (stmt, GF_PLF_2, false);
3139
3140 if (code == GIMPLE_ASSIGN)
3141 {
3142 tree lhs = gimple_assign_lhs (stmt);
3143 FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)for ((use_p) = first_readonly_imm_use (&(imm_iter), (lhs)
); !end_readonly_imm_use_p (&(imm_iter)); (void) ((use_p)
= next_readonly_imm_use (&(imm_iter))))
3144 {
3145 stmt1 = USE_STMT (use_p)(use_p)->loc.stmt;
3146 if (!is_gimple_debug (stmt1) && gimple_bb (stmt1) != bb)
3147 {
3148 gimple_set_plf (stmt, GF_PLF_2, true);
3149 worklist.safe_push (stmt);
3150 break;
3151 }
3152 }
3153 }
3154 }
3155 /* Propagate liveness through arguments of live stmt. */
3156 while (worklist.length () > 0)
3157 {
3158 ssa_op_iter iter;
3159 use_operand_p use_p;
3160 tree use;
3161
3162 stmt = worklist.pop ();
3163 FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)for ((use_p) = (gimple_code (stmt) == GIMPLE_PHI ? op_iter_init_phiuse
(&(iter), as_a <gphi *> (stmt), 0x01) : op_iter_init_use
(&(iter), stmt, 0x01)); !op_iter_done (&(iter)); (use_p
) = op_iter_next_use (&(iter)))
3164 {
3165 use = USE_FROM_PTR (use_p)get_use_from_ptr (use_p);
3166 if (TREE_CODE (use)((enum tree_code) (use)->base.code) != SSA_NAME)
3167 continue;
3168 stmt1 = SSA_NAME_DEF_STMT (use)(tree_check ((use), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3168, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
;
3169 if (gimple_bb (stmt1) != bb || gimple_plf (stmt1, GF_PLF_2))
3170 continue;
3171 gimple_set_plf (stmt1, GF_PLF_2, true);
3172 worklist.safe_push (stmt1);
3173 }
3174 }
3175 /* Delete dead statements. */
3176 gsi = gsi_last_bb (bb);
3177 while (!gsi_end_p (gsi))
3178 {
3179 gimple_stmt_iterator gsiprev = gsi;
3180 gsi_prev (&gsiprev);
3181 stmt = gsi_stmt (gsi);
3182 if (gimple_store_p (stmt) && gimple_vdef (stmt))
3183 {
3184 tree lhs = gimple_get_lhs (stmt);
3185 ao_ref write;
3186 ao_ref_init (&write, lhs);
3187
3188 if (dse_classify_store (&write, stmt, false, NULLnullptr, NULLnullptr, latch_vdef)
3189 == DSE_STORE_DEAD)
3190 delete_dead_or_redundant_assignment (&gsi, "dead");
3191 gsi = gsiprev;
3192 continue;
3193 }
3194
3195 if (gimple_plf (stmt, GF_PLF_2))
3196 {
3197 gsi = gsiprev;
3198 continue;
3199 }
3200 if (dump_file && (dump_flags & TDF_DETAILS))
3201 {
3202 fprintf (dump_file, "Delete dead stmt in bb#%d\n", bb->index);
3203 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3204 }
3205 gsi_remove (&gsi, true);
3206 release_defs (stmt);
3207 gsi = gsiprev;
3208 }
3209}
3210
3211/* Return true if VALUE is already available on edge PE. */
3212
3213static bool
3214ifcvt_available_on_edge_p (edge pe, tree value)
3215{
3216 if (is_gimple_min_invariant (value))
3217 return true;
3218
3219 if (TREE_CODE (value)((enum tree_code) (value)->base.code) == SSA_NAME)
3220 {
3221 basic_block def_bb = gimple_bb (SSA_NAME_DEF_STMT (value)(tree_check ((value), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3221, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
);
3222 if (!def_bb || dominated_by_p (CDI_DOMINATORS, pe->dest, def_bb))
3223 return true;
3224 }
3225
3226 return false;
3227}
3228
3229/* Return true if STMT can be hoisted from if-converted loop LOOP to
3230 edge PE. */
3231
3232static bool
3233ifcvt_can_hoist (class loop *loop, edge pe, gimple *stmt)
3234{
3235 if (auto *call = dyn_cast<gcall *> (stmt))
3236 {
3237 if (gimple_call_internal_p (call)
3238 && internal_fn_mask_index (gimple_call_internal_fn (call)) >= 0)
3239 return false;
3240 }
3241 else if (auto *assign = dyn_cast<gassign *> (stmt))
3242 {
3243 if (gimple_assign_rhs_code (assign) == COND_EXPR)
3244 return false;
3245 }
3246 else
3247 return false;
3248
3249 if (gimple_has_side_effects (stmt)
3250 || gimple_could_trap_p (stmt)
3251 || stmt_could_throw_p (cfun(cfun + 0), stmt)
3252 || gimple_vdef (stmt)
3253 || gimple_vuse (stmt))
3254 return false;
3255
3256 int num_args = gimple_num_args (stmt);
3257 if (pe != loop_preheader_edge (loop))
3258 {
3259 for (int i = 0; i < num_args; ++i)
3260 if (!ifcvt_available_on_edge_p (pe, gimple_arg (stmt, i)))
3261 return false;
3262 }
3263 else
3264 {
3265 for (int i = 0; i < num_args; ++i)
3266 if (!expr_invariant_in_loop_p (loop, gimple_arg (stmt, i)))
3267 return false;
3268 }
3269
3270 return true;
3271}
3272
3273/* Hoist invariant statements from LOOP to edge PE. */
3274
3275static void
3276ifcvt_hoist_invariants (class loop *loop, edge pe)
3277{
3278 gimple_stmt_iterator hoist_gsi = {};
3279 unsigned int num_blocks = loop->num_nodes;
3280 basic_block *body = get_loop_body (loop);
3281 for (unsigned int i = 0; i < num_blocks; ++i)
3282 for (gimple_stmt_iterator gsi = gsi_start_bb (body[i]); !gsi_end_p (gsi);)
3283 {
3284 gimple *stmt = gsi_stmt (gsi);
3285 if (ifcvt_can_hoist (loop, pe, stmt))
3286 {
3287 /* Once we've hoisted one statement, insert other statements
3288 after it. */
3289 gsi_remove (&gsi, false);
3290 if (hoist_gsi.ptr)
3291 gsi_insert_after (&hoist_gsi, stmt, GSI_NEW_STMT);
3292 else
3293 {
3294 gsi_insert_on_edge_immediate (pe, stmt);
3295 hoist_gsi = gsi_for_stmt (stmt);
3296 }
3297 continue;
3298 }
3299 gsi_next (&gsi);
3300 }
3301 free (body);
3302}
3303
3304/* Returns the DECL_FIELD_BIT_OFFSET of the bitfield accesse in stmt iff its
3305 type mode is not BLKmode. If BITPOS is not NULL it will hold the poly_int64
3306 value of the DECL_FIELD_BIT_OFFSET of the bitfield access and STRUCT_EXPR,
3307 if not NULL, will hold the tree representing the base struct of this
3308 bitfield. */
3309
3310static tree
3311get_bitfield_rep (gassign *stmt, bool write, tree *bitpos,
3312 tree *struct_expr)
3313{
3314 tree comp_ref = write ? gimple_assign_lhs (stmt)
3315 : gimple_assign_rhs1 (stmt);
3316
3317 tree field_decl = TREE_OPERAND (comp_ref, 1)(*((const_cast<tree*> (tree_operand_check ((comp_ref), (
1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3317, __FUNCTION__)))))
;
3318 tree rep_decl = DECL_BIT_FIELD_REPRESENTATIVE (field_decl)((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3318, __FUNCTION__, (FIELD_DECL)))->field_decl.qualifier
)
;
3319
3320 /* Bail out if the representative is not a suitable type for a scalar
3321 register variable. */
3322 if (!is_gimple_reg_type (TREE_TYPE (rep_decl)((contains_struct_check ((rep_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3322, __FUNCTION__))->typed.type)
))
3323 return NULL_TREE(tree) nullptr;
3324
3325 /* Bail out if the DECL_SIZE of the field_decl isn't the same as the BF's
3326 precision. */
3327 unsigned HOST_WIDE_INTlong bf_prec
3328 = TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (stmt)))((tree_class_check ((((contains_struct_check ((gimple_assign_lhs
(stmt)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3328, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3328, __FUNCTION__))->type_common.precision)
;
3329 if (compare_tree_int (DECL_SIZE (field_decl)((contains_struct_check ((field_decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3329, __FUNCTION__))->decl_common.size)
, bf_prec) != 0)
3330 return NULL_TREE(tree) nullptr;
3331
3332 if (struct_expr)
3333 *struct_expr = TREE_OPERAND (comp_ref, 0)(*((const_cast<tree*> (tree_operand_check ((comp_ref), (
0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3333, __FUNCTION__)))))
;
3334
3335 if (bitpos)
3336 {
3337 /* To calculate the bitposition of the BITFIELD_REF we have to determine
3338 where our bitfield starts in relation to the container REP_DECL. The
3339 DECL_FIELD_OFFSET of the original bitfield's member FIELD_DECL tells
3340 us how many bytes from the start of the structure there are until the
3341 start of the group of bitfield members the FIELD_DECL belongs to,
3342 whereas DECL_FIELD_BIT_OFFSET will tell us how many bits from that
3343 position our actual bitfield member starts. For the container
3344 REP_DECL adding DECL_FIELD_OFFSET and DECL_FIELD_BIT_OFFSET will tell
3345 us the distance between the start of the structure and the start of
3346 the container, though the first is in bytes and the later other in
3347 bits. With this in mind we calculate the bit position of our new
3348 BITFIELD_REF by subtracting the number of bits between the start of
3349 the structure and the container from the number of bits from the start
3350 of the structure and the actual bitfield member. */
3351 tree bf_pos = fold_build2 (MULT_EXPR, bitsizetype,fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3352, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
3352 DECL_FIELD_OFFSET (field_decl),fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3352, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
3353 build_int_cst (bitsizetype, BITS_PER_UNIT))fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3352, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
;
3354 bf_pos = fold_build2 (PLUS_EXPR, bitsizetype, bf_pos,fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int
) stk_bitsizetype], bf_pos, ((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3355, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
) )
3355 DECL_FIELD_BIT_OFFSET (field_decl))fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int
) stk_bitsizetype], bf_pos, ((tree_check ((field_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3355, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
) )
;
3356 tree rep_pos = fold_build2 (MULT_EXPR, bitsizetype,fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((rep_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3357, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
3357 DECL_FIELD_OFFSET (rep_decl),fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((rep_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3357, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
3358 build_int_cst (bitsizetype, BITS_PER_UNIT))fold_build2_loc (((location_t) 0), MULT_EXPR, sizetype_tab[(int
) stk_bitsizetype], ((tree_check ((rep_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3357, __FUNCTION__, (FIELD_DECL)))->field_decl.offset), build_int_cst
(sizetype_tab[(int) stk_bitsizetype], (8)) )
;
3359 rep_pos = fold_build2 (PLUS_EXPR, bitsizetype, rep_pos,fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int
) stk_bitsizetype], rep_pos, ((tree_check ((rep_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3360, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
) )
3360 DECL_FIELD_BIT_OFFSET (rep_decl))fold_build2_loc (((location_t) 0), PLUS_EXPR, sizetype_tab[(int
) stk_bitsizetype], rep_pos, ((tree_check ((rep_decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3360, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_offset
) )
;
3361
3362 *bitpos = fold_build2 (MINUS_EXPR, bitsizetype, bf_pos, rep_pos)fold_build2_loc (((location_t) 0), MINUS_EXPR, sizetype_tab[(
int) stk_bitsizetype], bf_pos, rep_pos )
;
3363 }
3364
3365 return rep_decl;
3366
3367}
3368
3369/* Lowers the bitfield described by DATA.
3370 For a write like:
3371
3372 struct.bf = _1;
3373
3374 lower to:
3375
3376 __ifc_1 = struct.<representative>;
3377 __ifc_2 = BIT_INSERT_EXPR (__ifc_1, _1, bitpos);
3378 struct.<representative> = __ifc_2;
3379
3380 For a read:
3381
3382 _1 = struct.bf;
3383
3384 lower to:
3385
3386 __ifc_1 = struct.<representative>;
3387 _1 = BIT_FIELD_REF (__ifc_1, bitsize, bitpos);
3388
3389 where representative is a legal load that contains the bitfield value,
3390 bitsize is the size of the bitfield and bitpos the offset to the start of
3391 the bitfield within the representative. */
3392
3393static void
3394lower_bitfield (gassign *stmt, bool write)
3395{
3396 tree struct_expr;
3397 tree bitpos;
3398 tree rep_decl = get_bitfield_rep (stmt, write, &bitpos, &struct_expr);
3399 tree rep_type = TREE_TYPE (rep_decl)((contains_struct_check ((rep_decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3399, __FUNCTION__))->typed.type)
;
3400 tree bf_type = TREE_TYPE (gimple_assign_lhs (stmt))((contains_struct_check ((gimple_assign_lhs (stmt)), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3400, __FUNCTION__))->typed.type)
;
3401
3402 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
3403 if (dump_file && (dump_flags & TDF_DETAILS))
3404 {
3405 fprintf (dump_file, "Lowering:\n");
3406 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3407 fprintf (dump_file, "to:\n");
3408 }
3409
3410 /* REP_COMP_REF is a COMPONENT_REF for the representative. NEW_VAL is it's
3411 defining SSA_NAME. */
3412 tree rep_comp_ref = build3 (COMPONENT_REF, rep_type, struct_expr, rep_decl,
3413 NULL_TREE(tree) nullptr);
3414 tree new_val = ifc_temp_var (rep_type, rep_comp_ref, &gsi);
3415
3416 if (dump_file && (dump_flags & TDF_DETAILS))
3417 print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (new_val)(tree_check ((new_val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3417, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
, 0, TDF_SLIM);
3418
3419 if (write)
3420 {
3421 new_val = ifc_temp_var (rep_type,
3422 build3 (BIT_INSERT_EXPR, rep_type, new_val,
3423 unshare_expr (gimple_assign_rhs1 (stmt)),
3424 bitpos), &gsi);
3425
3426 if (dump_file && (dump_flags & TDF_DETAILS))
3427 print_gimple_stmt (dump_file, SSA_NAME_DEF_STMT (new_val)(tree_check ((new_val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3427, __FUNCTION__, (SSA_NAME)))->ssa_name.def_stmt
, 0, TDF_SLIM);
3428
3429 gimple *new_stmt = gimple_build_assign (unshare_expr (rep_comp_ref),
3430 new_val);
3431 gimple_move_vops (new_stmt, stmt);
3432 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
3433
3434 if (dump_file && (dump_flags & TDF_DETAILS))
3435 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
3436 }
3437 else
3438 {
3439 tree bfr = build3 (BIT_FIELD_REF, bf_type, new_val,
3440 build_int_cst (bitsizetypesizetype_tab[(int) stk_bitsizetype], TYPE_PRECISION (bf_type)((tree_class_check ((bf_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3440, __FUNCTION__))->type_common.precision)
),
3441 bitpos);
3442 new_val = ifc_temp_var (bf_type, bfr, &gsi);
3443
3444 gimple *new_stmt = gimple_build_assign (gimple_assign_lhs (stmt),
3445 new_val);
3446 gimple_move_vops (new_stmt, stmt);
3447 gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
3448
3449 if (dump_file && (dump_flags & TDF_DETAILS))
3450 print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM);
3451 }
3452
3453 gsi_remove (&gsi, true);
3454}
3455
3456/* Return TRUE if there are bitfields to lower in this LOOP. Fill TO_LOWER
3457 with data structures representing these bitfields. */
3458
3459static bool
3460bitfields_to_lower_p (class loop *loop,
3461 vec <gassign *> &reads_to_lower,
3462 vec <gassign *> &writes_to_lower)
3463{
3464 gimple_stmt_iterator gsi;
3465
3466 if (dump_file && (dump_flags & TDF_DETAILS))
3467 {
3468 fprintf (dump_file, "Analyzing loop %d for bitfields:\n", loop->num);
3469 }
3470
3471 for (unsigned i = 0; i < loop->num_nodes; ++i)
3472 {
3473 basic_block bb = ifc_bbs[i];
3474 for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
3475 {
3476 gassign *stmt = dyn_cast<gassign*> (gsi_stmt (gsi));
3477 if (!stmt)
3478 continue;
3479
3480 tree op = gimple_assign_lhs (stmt);
3481 bool write = TREE_CODE (op)((enum tree_code) (op)->base.code) == COMPONENT_REF;
3482
3483 if (!write)
3484 op = gimple_assign_rhs1 (stmt);
3485
3486 if (TREE_CODE (op)((enum tree_code) (op)->base.code) != COMPONENT_REF)
3487 continue;
3488
3489 if (DECL_BIT_FIELD_TYPE (TREE_OPERAND (op, 1))((tree_check (((*((const_cast<tree*> (tree_operand_check
((op), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3489, __FUNCTION__)))))), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3489, __FUNCTION__, (FIELD_DECL)))->field_decl.bit_field_type
)
)
3490 {
3491 if (dump_file && (dump_flags & TDF_DETAILS))
3492 print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
3493
3494 if (!INTEGRAL_TYPE_P (TREE_TYPE (op))(((enum tree_code) (((contains_struct_check ((op), (TS_TYPED)
, "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3494, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE
|| ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3494, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE
|| ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED
), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3494, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE
)
)
3495 {
3496 if (dump_file && (dump_flags & TDF_DETAILS))
3497 fprintf (dump_file, "\t Bitfield NO OK to lower,"
3498 " field type is not Integral.\n");
3499 return false;
3500 }
3501
3502 if (!get_bitfield_rep (stmt, write, NULLnullptr, NULLnullptr))
3503 {
3504 if (dump_file && (dump_flags & TDF_DETAILS))
3505 fprintf (dump_file, "\t Bitfield NOT OK to lower,"
3506 " representative is BLKmode.\n");
3507 return false;
3508 }
3509
3510 if (dump_file && (dump_flags & TDF_DETAILS))
3511 fprintf (dump_file, "\tBitfield OK to lower.\n");
3512 if (write)
3513 writes_to_lower.safe_push (stmt);
3514 else
3515 reads_to_lower.safe_push (stmt);
3516 }
3517 }
3518 }
3519 return !reads_to_lower.is_empty () || !writes_to_lower.is_empty ();
3520}
3521
3522
3523/* If-convert LOOP when it is legal. For the moment this pass has no
3524 profitability analysis. Returns non-zero todo flags when something
3525 changed. */
3526
3527unsigned int
3528tree_if_conversion (class loop *loop, vec<gimple *> *preds)
3529{
3530 unsigned int todo = 0;
3531 bool aggressive_if_conv;
3532 class loop *rloop;
3533 auto_vec <gassign *, 4> reads_to_lower;
3534 auto_vec <gassign *, 4> writes_to_lower;
3535 bitmap exit_bbs;
3536 edge pe;
3537 auto_vec<data_reference_p, 10> refs;
3538
3539 again:
3540 rloop = NULLnullptr;
3541 ifc_bbs = NULLnullptr;
3542 need_to_lower_bitfields = false;
3543 need_to_ifcvt = false;
3544 need_to_predicate = false;
3545 need_to_rewrite_undefined = false;
3546 any_complicated_phi = false;
3547
3548 /* Apply more aggressive if-conversion when loop or its outer loop were
3549 marked with simd pragma. When that's the case, we try to if-convert
3550 loop containing PHIs with more than MAX_PHI_ARG_NUM arguments. */
3551 aggressive_if_conv = loop->force_vectorize;
3552 if (!aggressive_if_conv)
3553 {
3554 class loop *outer_loop = loop_outer (loop);
3555 if (outer_loop && outer_loop->force_vectorize)
3556 aggressive_if_conv = true;
3557 }
3558
3559 if (!single_exit (loop))
3560 goto cleanup;
3561
3562 /* If there are more than two BBs in the loop then there is at least one if
3563 to convert. */
3564 if (loop->num_nodes > 2
3565 && !ifcvt_split_critical_edges (loop, aggressive_if_conv))
3566 goto cleanup;
3567
3568 ifc_bbs = get_loop_body_in_if_conv_order (loop);
3569 if (!ifc_bbs)
3570 {
3571 if (dump_file && (dump_flags & TDF_DETAILS))
3572 fprintf (dump_file, "Irreducible loop\n");
3573 goto cleanup;
3574 }
3575
3576 if (find_data_references_in_loop (loop, &refs) == chrec_dont_knowglobal_trees[TI_CHREC_DONT_KNOW])
3577 goto cleanup;
3578
3579 if (loop->num_nodes > 2)
3580 {
3581 need_to_ifcvt = true;
3582
3583 if (!if_convertible_loop_p (loop, &refs) || !dbg_cnt (if_conversion_tree))
3584 goto cleanup;
3585
3586 if ((need_to_predicate || any_complicated_phi)
3587 && ((!flag_tree_loop_vectorizeglobal_options.x_flag_tree_loop_vectorize && !loop->force_vectorize)
3588 || loop->dont_vectorize))
3589 goto cleanup;
3590 }
3591
3592 if ((flag_tree_loop_vectorizeglobal_options.x_flag_tree_loop_vectorize || loop->force_vectorize)
3593 && !loop->dont_vectorize)
3594 need_to_lower_bitfields = bitfields_to_lower_p (loop, reads_to_lower,
3595 writes_to_lower);
3596
3597 if (!need_to_ifcvt && !need_to_lower_bitfields)
3598 goto cleanup;
3599
3600 /* The edge to insert invariant stmts on. */
3601 pe = loop_preheader_edge (loop);
3602
3603 /* Since we have no cost model, always version loops unless the user
3604 specified -ftree-loop-if-convert or unless versioning is required.
3605 Either version this loop, or if the pattern is right for outer-loop
3606 vectorization, version the outer loop. In the latter case we will
3607 still if-convert the original inner loop. */
3608 if (need_to_lower_bitfields
3609 || need_to_predicate
3610 || any_complicated_phi
3611 || flag_tree_loop_if_convertglobal_options.x_flag_tree_loop_if_convert != 1)
3612 {
3613 class loop *vloop
3614 = (versionable_outer_loop_p (loop_outer (loop))
3615 ? loop_outer (loop) : loop);
3616 class loop *nloop = version_loop_for_if_conversion (vloop, preds);
3617 if (nloop == NULLnullptr)
3618 goto cleanup;
3619 if (vloop != loop)
3620 {
3621 /* If versionable_outer_loop_p decided to version the
3622 outer loop, version also the inner loop of the non-vectorized
3623 loop copy. So we transform:
3624 loop1
3625 loop2
3626 into:
3627 if (LOOP_VECTORIZED (1, 3))
3628 {
3629 loop1
3630 loop2
3631 }
3632 else
3633 loop3 (copy of loop1)
3634 if (LOOP_VECTORIZED (4, 5))
3635 loop4 (copy of loop2)
3636 else
3637 loop5 (copy of loop4) */
3638 gcc_assert (nloop->inner && nloop->inner->next == NULL)((void)(!(nloop->inner && nloop->inner->next
== nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3638, __FUNCTION__), 0 : 0))
;
3639 rloop = nloop->inner;
3640 }
3641 else
3642 /* If we versioned loop then make sure to insert invariant
3643 stmts before the .LOOP_VECTORIZED check since the vectorizer
3644 will re-use that for things like runtime alias versioning
3645 whose condition can end up using those invariants. */
3646 pe = single_pred_edge (gimple_bb (preds->last ()));
3647 }
3648
3649 if (need_to_lower_bitfields)
3650 {
3651 if (dump_file && (dump_flags & TDF_DETAILS))
3652 {
3653 fprintf (dump_file, "-------------------------\n");
3654 fprintf (dump_file, "Start lowering bitfields\n");
3655 }
3656 while (!reads_to_lower.is_empty ())
3657 lower_bitfield (reads_to_lower.pop (), false);
3658 while (!writes_to_lower.is_empty ())
3659 lower_bitfield (writes_to_lower.pop (), true);
3660
3661 if (dump_file && (dump_flags & TDF_DETAILS))
3662 {
3663 fprintf (dump_file, "Done lowering bitfields\n");
3664 fprintf (dump_file, "-------------------------\n");
3665 }
3666 }
3667 if (need_to_ifcvt)
3668 {
3669 /* Now all statements are if-convertible. Combine all the basic
3670 blocks into one huge basic block doing the if-conversion
3671 on-the-fly. */
3672 combine_blocks (loop);
3673 }
3674
3675 /* Perform local CSE, this esp. helps the vectorizer analysis if loads
3676 and stores are involved. CSE only the loop body, not the entry
3677 PHIs, those are to be kept in sync with the non-if-converted copy.
3678 ??? We'll still keep dead stores though. */
3679 exit_bbs = BITMAP_ALLOCbitmap_alloc (NULLnullptr);
3680 bitmap_set_bit (exit_bbs, single_exit (loop)->dest->index);
3681 bitmap_set_bit (exit_bbs, loop->latch->index);
3682
3683 std::pair <tree, tree> *name_pair;
3684 unsigned ssa_names_idx;
3685 FOR_EACH_VEC_ELT (redundant_ssa_names, ssa_names_idx, name_pair)for (ssa_names_idx = 0; (redundant_ssa_names).iterate ((ssa_names_idx
), &(name_pair)); ++(ssa_names_idx))
3686 replace_uses_by (name_pair->first, name_pair->second);
3687 redundant_ssa_names.release ();
3688
3689 todo |= do_rpo_vn (cfun(cfun + 0), loop_preheader_edge (loop), exit_bbs);
3690
3691 /* Delete dead predicate computations. */
3692 ifcvt_local_dce (loop);
3693 BITMAP_FREE (exit_bbs)((void) (bitmap_obstack_free ((bitmap) exit_bbs), (exit_bbs) =
(bitmap) nullptr))
;
3694
3695 ifcvt_hoist_invariants (loop, pe);
3696
3697 todo |= TODO_cleanup_cfg(1 << 5);
3698
3699 cleanup:
3700 data_reference_p dr;
3701 unsigned int i;
3702 for (i = 0; refs.iterate (i, &dr); i++)
3703 {
3704 free (dr->aux);
3705 free_data_ref (dr);
3706 }
3707 refs.truncate (0);
3708
3709 if (ifc_bbs)
3710 {
3711 unsigned int i;
3712
3713 for (i = 0; i < loop->num_nodes; i++)
3714 free_bb_predicate (ifc_bbs[i]);
3715
3716 free (ifc_bbs);
3717 ifc_bbs = NULLnullptr;
3718 }
3719 if (rloop != NULLnullptr)
3720 {
3721 loop = rloop;
3722 reads_to_lower.truncate (0);
3723 writes_to_lower.truncate (0);
3724 goto again;
3725 }
3726
3727 return todo;
3728}
3729
3730/* Tree if-conversion pass management. */
3731
3732namespace {
3733
3734const pass_data pass_data_if_conversion =
3735{
3736 GIMPLE_PASS, /* type */
3737 "ifcvt", /* name */
3738 OPTGROUP_NONE, /* optinfo_flags */
3739 TV_TREE_LOOP_IFCVT, /* tv_id */
3740 ( PROP_cfg(1 << 3) | PROP_ssa(1 << 5) ), /* properties_required */
3741 0, /* properties_provided */
3742 0, /* properties_destroyed */
3743 0, /* todo_flags_start */
3744 0, /* todo_flags_finish */
3745};
3746
3747class pass_if_conversion : public gimple_opt_pass
3748{
3749public:
3750 pass_if_conversion (gcc::context *ctxt)
3751 : gimple_opt_pass (pass_data_if_conversion, ctxt)
3752 {}
3753
3754 /* opt_pass methods: */
3755 bool gate (function *) final override;
3756 unsigned int execute (function *) final override;
3757
3758}; // class pass_if_conversion
3759
3760bool
3761pass_if_conversion::gate (function *fun)
3762{
3763 return (((flag_tree_loop_vectorizeglobal_options.x_flag_tree_loop_vectorize || fun->has_force_vectorize_loops)
3764 && flag_tree_loop_if_convertglobal_options.x_flag_tree_loop_if_convert != 0)
3765 || flag_tree_loop_if_convertglobal_options.x_flag_tree_loop_if_convert == 1);
3766}
3767
3768unsigned int
3769pass_if_conversion::execute (function *fun)
3770{
3771 unsigned todo = 0;
3772
3773 if (number_of_loops (fun) <= 1)
3774 return 0;
3775
3776 auto_vec<gimple *> preds;
3777 for (auto loop : loops_list (cfun(cfun + 0), 0))
3778 if (flag_tree_loop_if_convertglobal_options.x_flag_tree_loop_if_convert == 1
3779 || ((flag_tree_loop_vectorizeglobal_options.x_flag_tree_loop_vectorize || loop->force_vectorize)
3780 && !loop->dont_vectorize))
3781 todo |= tree_if_conversion (loop, &preds);
3782
3783 if (todo)
3784 {
3785 free_numbers_of_iterations_estimates (fun);
3786 scev_reset ();
3787 }
3788
3789 if (flag_checkingglobal_options.x_flag_checking)
3790 {
3791 basic_block bb;
3792 FOR_EACH_BB_FN (bb, fun)for (bb = (fun)->cfg->x_entry_block_ptr->next_bb; bb
!= (fun)->cfg->x_exit_block_ptr; bb = bb->next_bb)
3793 gcc_assert (!bb->aux)((void)(!(!bb->aux) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-if-conv.cc"
, 3793, __FUNCTION__), 0 : 0))
;
3794 }
3795
3796 /* Perform IL update now, it might elide some loops. */
3797 if (todo & TODO_cleanup_cfg(1 << 5))
3798 {
3799 cleanup_tree_cfg ();
3800 if (need_ssa_update_p (fun))
3801 todo |= TODO_update_ssa(1 << 11);
3802 }
3803 if (todo & TODO_update_ssa_any((1 << 11) | (1 << 12) | (1 << 13) | (1 <<
14))
)
3804 update_ssa (todo & TODO_update_ssa_any((1 << 11) | (1 << 12) | (1 << 13) | (1 <<
14))
);
3805
3806 /* If if-conversion elided the loop fall back to the original one. */
3807 for (unsigned i = 0; i < preds.length (); ++i)
3808 {
3809 gimple *g = preds[i];
3810 if (!gimple_bb (g))
3811 continue;
3812 unsigned ifcvt_loop = tree_to_uhwi (gimple_call_arg (g, 0));
3813 unsigned orig_loop = tree_to_uhwi (gimple_call_arg (g, 1));
3814 if (!get_loop (fun, ifcvt_loop) || !get_loop (fun, orig_loop))
3815 {
3816 if (dump_file)
3817 fprintf (dump_file, "If-converted loop vanished\n");
3818 fold_loop_internal_call (g, boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]);
3819 }
3820 }
3821
3822 return 0;
3823}
3824
3825} // anon namespace
3826
3827gimple_opt_pass *
3828make_pass_if_conversion (gcc::context *ctxt)
3829{
3830 return new pass_if_conversion (ctxt);
3831}