Branch data Line data Source code
1 : : /* Tree lowering pass. This pass gimplifies the tree representation built
2 : : by the C-based front ends. The structure of gimplified, or
3 : : language-independent, trees is dictated by the grammar described in this
4 : : file.
5 : : Copyright (C) 2002-2025 Free Software Foundation, Inc.
6 : : Lowering of expressions contributed by Sebastian Pop <s.pop@laposte.net>
7 : : Re-written to support lowering of whole function trees, documentation
8 : : and miscellaneous cleanups by Diego Novillo <dnovillo@redhat.com>
9 : :
10 : : This file is part of GCC.
11 : :
12 : : GCC is free software; you can redistribute it and/or modify it under
13 : : the terms of the GNU General Public License as published by the Free
14 : : Software Foundation; either version 3, or (at your option) any later
15 : : version.
16 : :
17 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
18 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 : : for more details.
21 : :
22 : : You should have received a copy of the GNU General Public License
23 : : along with GCC; see the file COPYING3. If not see
24 : : <http://www.gnu.org/licenses/>. */
25 : :
26 : : #include "config.h"
27 : : #include "system.h"
28 : : #include "coretypes.h"
29 : : #include "tm.h"
30 : : #include "function.h"
31 : : #include "basic-block.h"
32 : : #include "tree.h"
33 : : #include "tree-iterator.h"
34 : : #include "predict.h"
35 : : #include "gimple.h"
36 : : #include "cgraph.h"
37 : : #include "c-pretty-print.h"
38 : : #include "gimplify.h"
39 : : #include "langhooks.h"
40 : : #include "dumpfile.h"
41 : : #include "c-ubsan.h"
42 : : #include "tree-nested.h"
43 : : #include "context.h"
44 : : #include "tree-pass.h"
45 : : #include "internal-fn.h"
46 : : #include "omp-general.h"
47 : :
48 : : /* The gimplification pass converts the language-dependent trees
49 : : (ld-trees) emitted by the parser into language-independent trees
50 : : (li-trees) that are the target of SSA analysis and transformations.
51 : :
52 : : Language-independent trees are based on the SIMPLE intermediate
53 : : representation used in the McCAT compiler framework:
54 : :
55 : : "Designing the McCAT Compiler Based on a Family of Structured
56 : : Intermediate Representations,"
57 : : L. Hendren, C. Donawa, M. Emami, G. Gao, Justiani, and B. Sridharan,
58 : : Proceedings of the 5th International Workshop on Languages and
59 : : Compilers for Parallel Computing, no. 757 in Lecture Notes in
60 : : Computer Science, New Haven, Connecticut, pp. 406-420,
61 : : Springer-Verlag, August 3-5, 1992.
62 : :
63 : : http://www-acaps.cs.mcgill.ca/info/McCAT/McCAT.html
64 : :
65 : : Basically, we walk down gimplifying the nodes that we encounter. As we
66 : : walk back up, we check that they fit our constraints, and copy them
67 : : into temporaries if not. */
68 : :
69 : : /* Callback for c_genericize. */
70 : :
71 : : static tree
72 : 1282932 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
73 : : {
74 : 1282932 : hash_set<tree> *pset = (hash_set<tree> *) data;
75 : :
76 : 1282932 : if (TREE_CODE (*tp) == BIND_EXPR)
77 : : {
78 : : /* Since walk_tree doesn't call the callback function on the decls
79 : : in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
80 : : instrumenting DECL_INITIAL of TREE_STATIC vars. */
81 : 65884 : *walk_subtrees = 0;
82 : 81521 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
83 : : {
84 : 15637 : if (TREE_STATIC (decl))
85 : 138 : continue;
86 : 15499 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
87 : : pset);
88 : 15499 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
89 : 15499 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
90 : : pset);
91 : : }
92 : 65884 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
93 : : }
94 : 1217048 : else if (TREE_CODE (*tp) == ADDR_EXPR
95 : 1217048 : && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
96 : : {
97 : 257 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true);
98 : : /* Make sure ubsan_maybe_instrument_array_ref is not called again
99 : : on the ARRAY_REF, the above call might not instrument anything
100 : : as the index might be constant or masked, so ensure it is not
101 : : walked again and walk its subtrees manually. */
102 : 257 : tree aref = TREE_OPERAND (*tp, 0);
103 : 257 : pset->add (aref);
104 : 257 : *walk_subtrees = 0;
105 : 257 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
106 : 257 : walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
107 : 257 : walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
108 : 257 : walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
109 : : }
110 : 1216791 : else if (TREE_CODE (*tp) == ARRAY_REF)
111 : 3983 : ubsan_maybe_instrument_array_ref (tp, false);
112 : 1212808 : else if (TREE_CODE (*tp) == MODIFY_EXPR)
113 : : {
114 : : /* Since r7-1900, we gimplify RHS before LHS. Consider
115 : : a[b] |= c;
116 : : wherein we can have a single shared tree a[b] in both LHS and RHS.
117 : : If we only instrument the LHS and the access is invalid, the program
118 : : could crash before emitting a UBSan error. So instrument the RHS
119 : : first. */
120 : 67664 : *walk_subtrees = 0;
121 : 67664 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
122 : 67664 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
123 : : }
124 : 1282932 : return NULL_TREE;
125 : : }
126 : :
127 : : /* Gimplification of statement trees. */
128 : :
129 : : /* Local declarations. */
130 : :
131 : : enum bc_t { bc_break = 0, bc_continue = 1 };
132 : :
133 : : /* Stack of labels which are targets for "break" or "continue",
134 : : linked through TREE_CHAIN. */
135 : : static tree bc_label[2];
136 : :
137 : : /* Hash map from loop/switch names (identified by LABEL_DECL) to
138 : : corresponding break and (if any) continue labels. */
139 : : static bc_hash_map_t *bc_hash_map;
140 : :
141 : : /* Begin a scope which can be exited by a break or continue statement. BC
142 : : indicates which.
143 : :
144 : : Just creates a label with location LOCATION and pushes it into the current
145 : : context. */
146 : :
147 : : static tree
148 : 6926791 : begin_bc_block (enum bc_t bc, location_t location)
149 : : {
150 : 6926791 : tree label = create_artificial_label (location);
151 : 6926791 : DECL_CHAIN (label) = bc_label[bc];
152 : 6926791 : bc_label[bc] = label;
153 : 6926791 : if (bc == bc_break)
154 : 3596655 : LABEL_DECL_BREAK (label) = true;
155 : : else
156 : 3330136 : LABEL_DECL_CONTINUE (label) = true;
157 : 6926791 : return label;
158 : : }
159 : :
160 : : /* Finish a scope which can be exited by a break or continue statement.
161 : : LABEL was returned from the most recent call to begin_bc_block. BLOCK is
162 : : an expression for the contents of the scope.
163 : :
164 : : If we saw a break (or continue) in the scope, append a LABEL_EXPR to
165 : : BLOCK. Otherwise, just forget the label. */
166 : :
167 : : static void
168 : 6926791 : finish_bc_block (tree *block, enum bc_t bc, tree label)
169 : : {
170 : 6926791 : gcc_assert (label == bc_label[bc]);
171 : :
172 : 6926791 : if (TREE_USED (label))
173 : 2756445 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
174 : : block);
175 : :
176 : 6926791 : bc_label[bc] = DECL_CHAIN (label);
177 : 6926791 : DECL_CHAIN (label) = NULL_TREE;
178 : 6926791 : }
179 : :
180 : : /* For named loop or switch with NAME, remember corresponding break
181 : : label BLAB and continue label CLAB. */
182 : :
183 : : static void
184 : 46 : note_named_bc (tree name, tree blab, tree clab)
185 : : {
186 : 46 : if (bc_hash_map == NULL)
187 : 14 : bc_hash_map = new bc_hash_map_t (32);
188 : 46 : bc_hash_map->put (name, std::make_pair (blab, clab));
189 : 46 : }
190 : :
191 : : /* Remove NAME from the map after processing body of the loop or
192 : : switch. */
193 : :
194 : : static void
195 : 46 : release_named_bc (tree name)
196 : : {
197 : 0 : bc_hash_map->remove (name);
198 : 0 : }
199 : :
200 : : /* Allow saving and restoring break/continue state. */
201 : :
202 : : void
203 : 76236126 : save_bc_state (bc_state_t *state)
204 : : {
205 : 76236126 : state->bc_label[bc_break] = bc_label[bc_break];
206 : 76236126 : state->bc_label[bc_continue] = bc_label[bc_continue];
207 : 76236126 : state->bc_hash_map = bc_hash_map;
208 : 76236126 : bc_label[bc_break] = NULL_TREE;
209 : 76236126 : bc_label[bc_continue] = NULL_TREE;
210 : 76236126 : bc_hash_map = NULL;
211 : 76236126 : }
212 : :
213 : : void
214 : 76236126 : restore_bc_state (bc_state_t *state)
215 : : {
216 : 76236126 : gcc_assert (bc_label[bc_break] == NULL);
217 : 76236126 : gcc_assert (bc_label[bc_continue] == NULL);
218 : 76236126 : gcc_assert (bc_hash_map == NULL);
219 : 76236126 : bc_label[bc_break] = state->bc_label[bc_break];
220 : 76236126 : bc_label[bc_continue] = state->bc_label[bc_continue];
221 : 76236126 : bc_hash_map = state->bc_hash_map;
222 : 76236126 : }
223 : :
224 : : /* Get the LABEL_EXPR to represent a break or continue statement
225 : : in the current block scope. BC indicates which. */
226 : :
227 : : static tree
228 : 3834980 : get_bc_label (enum bc_t bc)
229 : : {
230 : 3834980 : tree label = bc_label[bc];
231 : 3834980 : gcc_assert (label);
232 : :
233 : : /* Mark the label used for finish_bc_block. */
234 : 3834980 : TREE_USED (label) = 1;
235 : 3834980 : return label;
236 : : }
237 : :
238 : : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
239 : :
240 : : location_t
241 : 7886606 : expr_loc_or_loc (const_tree expr, location_t or_loc)
242 : : {
243 : 7886606 : tree t = CONST_CAST_TREE (expr);
244 : 7886606 : location_t loc = UNKNOWN_LOCATION;
245 : 7886606 : if (t)
246 : 6037554 : loc = EXPR_LOCATION (t);
247 : 4913159 : if (loc == UNKNOWN_LOCATION)
248 : 4212335 : loc = or_loc;
249 : 7886606 : return loc;
250 : : }
251 : :
252 : : /* Build a generic representation of one of the C loop forms. COND is the
253 : : loop condition or NULL_TREE. BODY is the (possibly compound) statement
254 : : controlled by the loop. INCR is the increment expression of a for-loop,
255 : : or NULL_TREE. COND_IS_FIRST indicates whether the condition is
256 : : evaluated before the loop body as in while and for loops, or after the
257 : : loop body as in do-while loops. COND_PREP and COND_CLEANUP are used
258 : : for C++ for/while loops with variable declaration as condition. COND_PREP
259 : : is a BIND_EXPR with the declaration and initialization of the condition
260 : : variable, into which COND, BODY, continue label if needed and INCR if
261 : : non-NULL should be appended, and COND_CLEANUP is number of nested
262 : : CLEANUP_STMT -> TRY_FINALLY_EXPR statements at the end. If non-NULL,
263 : : COND, BODY, continue label if needed and INCR if non-NULL should be
264 : : appended to the body of the COND_CLEANUP's nested TRY_FINALLY_EXPR. */
265 : :
266 : : static void
267 : 3287831 : genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
268 : : tree incr, tree name, tree cond_prep, tree cond_cleanup,
269 : : bool cond_is_first, int *walk_subtrees, void *data,
270 : : walk_tree_fn func, walk_tree_lh lh)
271 : : {
272 : 3287831 : tree blab, clab;
273 : 3287831 : tree entry = NULL, exit = NULL, t;
274 : 3287831 : tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
275 : 3287831 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
276 : 3287831 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
277 : :
278 : 3287831 : protected_set_expr_location_if_unset (incr, start_locus);
279 : :
280 : 3287831 : walk_tree_1 (&cond_prep, func, data, NULL, lh);
281 : 3287831 : walk_tree_1 (&cond, func, data, NULL, lh);
282 : 3287831 : walk_tree_1 (&incr, func, data, NULL, lh);
283 : :
284 : 3287831 : blab = begin_bc_block (bc_break, start_locus);
285 : 3287831 : clab = begin_bc_block (bc_continue, start_locus);
286 : 3287831 : if (name)
287 : 35 : note_named_bc (name, blab, clab);
288 : :
289 : 3287831 : walk_tree_1 (&body, func, data, NULL, lh);
290 : 3287831 : *walk_subtrees = 0;
291 : :
292 : 3287831 : if (name)
293 : 35 : release_named_bc (name);
294 : :
295 : 3287831 : if (cond_prep)
296 : : {
297 : : /* The C++ cases of
298 : : while (A x = 42) body;
299 : : for (; A x = 42; expr) body;
300 : : This should be expanded into:
301 : :
302 : : top:
303 : : COND_PREP
304 : :
305 : : with either
306 : :
307 : : if (COND); else break;
308 : : BODY;
309 : : cont:
310 : : EXPR;
311 : : goto top;
312 : :
313 : : appended into COND_PREP body or body of some TRY_FINALLY_EXPRs
314 : : at the end of COND_PREP. */
315 : 9768 : gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
316 : 9768 : tree top = build1 (LABEL_EXPR, void_type_node,
317 : : create_artificial_label (start_locus));
318 : 9768 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
319 : 9768 : append_to_statement_list (top, &outer_stmt_list);
320 : 9768 : append_to_statement_list (cond_prep, &outer_stmt_list);
321 : 9768 : stmt_list_p = &BIND_EXPR_BODY (cond_prep);
322 : 9768 : if (cond_cleanup)
323 : 206 : for (unsigned depth = tree_to_uhwi (cond_cleanup); depth; --depth)
324 : : {
325 : 109 : t = tsi_stmt (tsi_last (*stmt_list_p));
326 : 109 : gcc_assert (TREE_CODE (t) == TRY_FINALLY_EXPR);
327 : 109 : stmt_list_p = &TREE_OPERAND (t, 0);
328 : : }
329 : 9768 : stmt_list = *stmt_list_p;
330 : 9768 : *stmt_list_p = NULL_TREE;
331 : 9768 : tree after_cond = create_artificial_label (cond_locus);
332 : 9768 : tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
333 : 9768 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
334 : 9768 : t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
335 : : goto_after_cond, t);
336 : 9768 : append_to_statement_list (t, &stmt_list);
337 : 9768 : t = build1 (LABEL_EXPR, void_type_node, after_cond);
338 : 9768 : append_to_statement_list (t, &stmt_list);
339 : : }
340 : 3278063 : else if (cond && integer_zerop (cond))
341 : : {
342 : : /* If condition is zero don't generate a loop construct. */
343 : 1076068 : if (cond_is_first)
344 : : {
345 : 196 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
346 : : get_bc_label (bc_break));
347 : 196 : append_to_statement_list (t, &stmt_list);
348 : : }
349 : : }
350 : : else
351 : : {
352 : : /* Expand to gotos. */
353 : 2201995 : tree top = build1 (LABEL_EXPR, void_type_node,
354 : : create_artificial_label (start_locus));
355 : :
356 : : /* If we have an exit condition, then we build an IF with gotos either
357 : : out of the loop, or to the top of it. If there's no exit condition,
358 : : then we just build a jump back to the top. */
359 : 2201995 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
360 : :
361 : 2201995 : if (cond && !integer_nonzerop (cond))
362 : : {
363 : : /* Canonicalize the loop condition to the end. This means
364 : : generating a branch to the loop condition. Reuse the
365 : : continue label, if there is no incr expression. */
366 : 2094784 : if (cond_is_first)
367 : : {
368 : 1940930 : if (incr)
369 : : {
370 : 1496365 : entry = build1 (LABEL_EXPR, void_type_node,
371 : : create_artificial_label (start_locus));
372 : 2992730 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
373 : 1496365 : LABEL_EXPR_LABEL (entry));
374 : : }
375 : : else
376 : 444565 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
377 : : get_bc_label (bc_continue));
378 : 1940930 : append_to_statement_list (t, &stmt_list);
379 : : }
380 : :
381 : 2094784 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
382 : 2094784 : exit = fold_build3_loc (cond_locus,
383 : : COND_EXPR, void_type_node, cond, exit, t);
384 : : }
385 : : else
386 : : {
387 : : /* For the backward-goto's location of an unconditional loop
388 : : use the beginning of the body, or, if there is none, the
389 : : top of the loop. */
390 : 107211 : location_t loc = expr_loc_or_loc (expr_first (body),
391 : : start_locus);
392 : 107211 : SET_EXPR_LOCATION (exit, loc);
393 : : }
394 : 2201995 : append_to_statement_list (top, &stmt_list);
395 : : }
396 : :
397 : 3287831 : append_to_statement_list (body, &stmt_list);
398 : 3287831 : if (c_dialect_cxx ()
399 : 2828176 : && stmt_list
400 : 2826279 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
401 : : {
402 : 2826279 : tree_stmt_iterator tsi = tsi_last (stmt_list);
403 : 2826279 : if (!tsi_end_p (tsi))
404 : : {
405 : 2826279 : tree t = *tsi;
406 : 2826279 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
407 : : || TREE_CODE (t) == EXPR_STMT
408 : 5072473 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
409 : 2246194 : t = TREE_OPERAND (t, 0);
410 : : /* For C++, if iteration statement body ends with fallthrough
411 : : statement, mark it such that we diagnose it even if next
412 : : statement would be labeled statement with case/default label. */
413 : 2826279 : if (TREE_CODE (t) == CALL_EXPR
414 : 104911 : && !CALL_EXPR_FN (t)
415 : 2826291 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
416 : 12 : TREE_NOTHROW (t) = 1;
417 : : }
418 : : }
419 : 3287831 : finish_bc_block (&stmt_list, bc_continue, clab);
420 : 3287831 : if (incr)
421 : : {
422 : 1498972 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
423 : : {
424 : 1203733 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
425 : 1203733 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
426 : 1203733 : append_to_statement_list (d, &stmt_list);
427 : : }
428 : 1498972 : append_to_statement_list (incr, &stmt_list);
429 : : }
430 : 3287831 : append_to_statement_list (entry, &stmt_list);
431 : :
432 : 3287831 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
433 : : {
434 : 2774989 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
435 : 2774989 : SET_EXPR_LOCATION (d, cond_locus);
436 : 2774989 : append_to_statement_list (d, &stmt_list);
437 : : }
438 : 3287831 : append_to_statement_list (exit, &stmt_list);
439 : 3287831 : if (stmt_list_p)
440 : : {
441 : 9768 : *stmt_list_p = stmt_list;
442 : 9768 : stmt_list = outer_stmt_list;
443 : : }
444 : 3287831 : finish_bc_block (&stmt_list, bc_break, blab);
445 : 3287831 : if (!stmt_list)
446 : 3585 : stmt_list = build_empty_stmt (start_locus);
447 : :
448 : 3287831 : *stmt_p = stmt_list;
449 : 3287831 : }
450 : :
451 : : /* Genericize a FOR_STMT node *STMT_P. */
452 : :
453 : : static void
454 : 1561772 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
455 : : walk_tree_fn func, walk_tree_lh lh)
456 : : {
457 : 1561772 : tree stmt = *stmt_p;
458 : 1561772 : tree expr = NULL;
459 : 1561772 : tree loop;
460 : 1561772 : tree init = FOR_INIT_STMT (stmt);
461 : :
462 : 1561772 : if (init)
463 : : {
464 : 0 : walk_tree_1 (&init, func, data, NULL, lh);
465 : 0 : append_to_statement_list (init, &expr);
466 : : }
467 : :
468 : 3123544 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
469 : 1561772 : FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
470 : 1561772 : FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
471 : : walk_subtrees, data, func, lh);
472 : 1561772 : append_to_statement_list (loop, &expr);
473 : 1561772 : if (expr == NULL_TREE)
474 : 0 : expr = loop;
475 : 1561772 : *stmt_p = expr;
476 : 1561772 : }
477 : :
478 : : /* Genericize a WHILE_STMT node *STMT_P. */
479 : :
480 : : static void
481 : 495937 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
482 : : walk_tree_fn func, walk_tree_lh lh)
483 : : {
484 : 495937 : tree stmt = *stmt_p;
485 : 991874 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
486 : 495937 : WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
487 : 495937 : WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
488 : : walk_subtrees, data, func, lh);
489 : 495937 : }
490 : :
491 : : /* Genericize a DO_STMT node *STMT_P. */
492 : :
493 : : static void
494 : 1230122 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
495 : : walk_tree_fn func, walk_tree_lh lh)
496 : : {
497 : 1230122 : tree stmt = *stmt_p;
498 : 2460244 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
499 : 1230122 : DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
500 : : NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
501 : 1230122 : }
502 : :
503 : : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
504 : :
505 : : static void
506 : 308824 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
507 : : walk_tree_fn func, walk_tree_lh lh)
508 : : {
509 : 308824 : tree stmt = *stmt_p;
510 : 308824 : tree blab, body, cond, type;
511 : 308824 : location_t stmt_locus = EXPR_LOCATION (stmt);
512 : :
513 : 308824 : body = SWITCH_STMT_BODY (stmt);
514 : 308824 : if (!body)
515 : 0 : body = build_empty_stmt (stmt_locus);
516 : 308824 : cond = SWITCH_STMT_COND (stmt);
517 : 308824 : type = SWITCH_STMT_TYPE (stmt);
518 : :
519 : 308824 : walk_tree_1 (&cond, func, data, NULL, lh);
520 : :
521 : 308824 : blab = begin_bc_block (bc_break, stmt_locus);
522 : 308824 : if (SWITCH_STMT_NAME (stmt))
523 : 11 : note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
524 : :
525 : 308824 : walk_tree_1 (&body, func, data, NULL, lh);
526 : :
527 : 308824 : if (SWITCH_STMT_NAME (stmt))
528 : 11 : release_named_bc (SWITCH_STMT_NAME (stmt));
529 : :
530 : 308824 : walk_tree_1 (&type, func, data, NULL, lh);
531 : 308824 : *walk_subtrees = 0;
532 : :
533 : 308824 : if (TREE_USED (blab))
534 : 150094 : SWITCH_BREAK_LABEL_P (blab) = 1;
535 : 308824 : finish_bc_block (&body, bc_break, blab);
536 : 308824 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
537 : 308824 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
538 : 308824 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
539 : : || !TREE_USED (blab));
540 : 308824 : }
541 : :
542 : : /* Genericize a CONTINUE_STMT node *STMT_P. */
543 : :
544 : : static void
545 : 16705 : genericize_continue_stmt (tree *stmt_p)
546 : : {
547 : 16705 : tree stmt_list = NULL;
548 : 16705 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
549 : 16705 : tree label;
550 : 16705 : if (CONTINUE_NAME (*stmt_p))
551 : : {
552 : 38 : tree_pair *slot = bc_hash_map->get (CONTINUE_NAME (*stmt_p));
553 : 38 : gcc_checking_assert (slot);
554 : 38 : label = slot->second;
555 : 38 : TREE_USED (label) = 1;
556 : : }
557 : : else
558 : 16667 : label = get_bc_label (bc_continue);
559 : 16705 : location_t location = EXPR_LOCATION (*stmt_p);
560 : 16705 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
561 : 16705 : append_to_statement_list_force (pred, &stmt_list);
562 : 16705 : append_to_statement_list (jump, &stmt_list);
563 : 16705 : *stmt_p = stmt_list;
564 : 16705 : }
565 : :
566 : : /* Genericize a BREAK_STMT node *STMT_P. */
567 : :
568 : : static void
569 : 1269048 : genericize_break_stmt (tree *stmt_p)
570 : : {
571 : 1269048 : tree label;
572 : 1269048 : if (BREAK_NAME (*stmt_p))
573 : : {
574 : 48 : tree_pair *slot = bc_hash_map->get (BREAK_NAME (*stmt_p));
575 : 48 : gcc_checking_assert (slot);
576 : 48 : label = slot->first;
577 : 48 : TREE_USED (label) = 1;
578 : : }
579 : : else
580 : 1269000 : label = get_bc_label (bc_break);
581 : 1269048 : location_t location = EXPR_LOCATION (*stmt_p);
582 : 1269048 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
583 : 1269048 : }
584 : :
585 : : /* Genericize a OMP_FOR node *STMT_P. */
586 : :
587 : : static void
588 : 42305 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
589 : : walk_tree_fn func, walk_tree_lh lh)
590 : : {
591 : 42305 : tree stmt = *stmt_p;
592 : 42305 : location_t locus = EXPR_LOCATION (stmt);
593 : 42305 : tree clab = begin_bc_block (bc_continue, locus);
594 : :
595 : 42305 : walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
596 : 42305 : if (TREE_CODE (stmt) != OMP_TASKLOOP)
597 : 40899 : walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
598 : 42305 : walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
599 : 42305 : walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
600 : 42305 : walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
601 : 42305 : walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
602 : 42305 : *walk_subtrees = 0;
603 : :
604 : 42305 : finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
605 : 42305 : }
606 : :
607 : : /* Genericize a OMP_METADIRECTIVE node *STMT_P. */
608 : :
609 : : static void
610 : 24 : genericize_omp_metadirective_stmt (tree *stmt_p, int *walk_subtrees,
611 : : void *data, walk_tree_fn func,
612 : : walk_tree_lh lh)
613 : : {
614 : 24 : tree stmt = *stmt_p;
615 : :
616 : 24 : for (tree variant = OMP_METADIRECTIVE_VARIANTS (stmt);
617 : 94 : variant != NULL_TREE;
618 : 70 : variant = TREE_CHAIN (variant))
619 : : {
620 : 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_DIRECTIVE (variant),
621 : : func, data, NULL, lh);
622 : 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_BODY (variant),
623 : : func, data, NULL, lh);
624 : : }
625 : :
626 : 24 : *walk_subtrees = 0;
627 : 24 : }
628 : :
629 : : /* Lower structured control flow tree nodes, such as loops. The
630 : : STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn
631 : : type. FUNC and LH are language-specific functions passed to walk_tree_1
632 : : for node visiting and traversal, respectively; they are used to do
633 : : subtree processing in a language-dependent way. */
634 : :
635 : : tree
636 : 729395925 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
637 : : walk_tree_fn func, walk_tree_lh lh)
638 : : {
639 : 729395925 : tree stmt = *stmt_p;
640 : :
641 : 729395925 : switch (TREE_CODE (stmt))
642 : : {
643 : 1561772 : case FOR_STMT:
644 : 1561772 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
645 : 1561772 : break;
646 : :
647 : 495937 : case WHILE_STMT:
648 : 495937 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
649 : 495937 : break;
650 : :
651 : 1230122 : case DO_STMT:
652 : 1230122 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
653 : 1230122 : break;
654 : :
655 : 308824 : case SWITCH_STMT:
656 : 308824 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
657 : 308824 : break;
658 : :
659 : 16705 : case CONTINUE_STMT:
660 : 16705 : genericize_continue_stmt (stmt_p);
661 : 16705 : break;
662 : :
663 : 1269048 : case BREAK_STMT:
664 : 1269048 : genericize_break_stmt (stmt_p);
665 : 1269048 : break;
666 : :
667 : 42305 : case OMP_FOR:
668 : 42305 : case OMP_SIMD:
669 : 42305 : case OMP_DISTRIBUTE:
670 : 42305 : case OMP_LOOP:
671 : 42305 : case OMP_TASKLOOP:
672 : 42305 : case OMP_TILE:
673 : 42305 : case OMP_UNROLL:
674 : 42305 : case OACC_LOOP:
675 : 42305 : genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
676 : 42305 : break;
677 : :
678 : 24 : case OMP_METADIRECTIVE:
679 : 24 : genericize_omp_metadirective_stmt (stmt_p, walk_subtrees, data, func,
680 : : lh);
681 : 24 : break;
682 : :
683 : 50440438 : case STATEMENT_LIST:
684 : 50440438 : if (TREE_SIDE_EFFECTS (stmt))
685 : : {
686 : 48167481 : tree_stmt_iterator i;
687 : 48167481 : int nondebug_stmts = 0;
688 : 48167481 : bool clear_side_effects = true;
689 : : /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when
690 : : transforming an IF_STMT into COND_EXPR. If such stmt
691 : : appears in a STATEMENT_LIST that contains only that
692 : : stmt and some DEBUG_BEGIN_STMTs, without -g where the
693 : : STATEMENT_LIST wouldn't be present at all the resulting
694 : : expression wouldn't have TREE_SIDE_EFFECTS set, so make sure
695 : : to clear it even on the STATEMENT_LIST in such cases. */
696 : 96334962 : hash_set<tree> *pset = (c_dialect_cxx ()
697 : 48167481 : ? nullptr
698 : : : static_cast<hash_set<tree> *>(data));
699 : 207804931 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
700 : : {
701 : 159637450 : tree t = tsi_stmt (i);
702 : 159637450 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
703 : 74708888 : nondebug_stmts++;
704 : 159637450 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
705 : 159637450 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
706 : 159637450 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
707 : : clear_side_effects = false;
708 : : }
709 : 48167481 : if (clear_side_effects)
710 : 2567 : TREE_SIDE_EFFECTS (stmt) = 0;
711 : 48167481 : *walk_subtrees = 0;
712 : : }
713 : : break;
714 : :
715 : : default:
716 : : break;
717 : : }
718 : :
719 : 729395925 : return NULL;
720 : : }
721 : :
722 : :
723 : : /* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree
724 : : callback. This is appropriate for C; C++ calls c_genericize_control_stmt
725 : : directly. */
726 : :
727 : : static tree
728 : 678385033 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
729 : : {
730 : 678385033 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
731 : : c_genericize_control_r, NULL);
732 : 678385033 : return NULL;
733 : : }
734 : :
735 : : /* Convert the tree representation of FNDECL from C frontend trees to
736 : : GENERIC. */
737 : :
738 : : void
739 : 76236126 : c_genericize (tree fndecl)
740 : : {
741 : 76236126 : dump_file_info *dfi;
742 : 76236126 : FILE *dump_orig;
743 : 76236126 : dump_flags_t local_dump_flags;
744 : 76236126 : struct cgraph_node *cgn;
745 : :
746 : 76236126 : if (flag_sanitize & SANITIZE_BOUNDS)
747 : : {
748 : 67812 : hash_set<tree> pset;
749 : 67812 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
750 : : &pset);
751 : 67812 : }
752 : :
753 : : /* Genericize loops and other structured control constructs. The C++
754 : : front end has already done this in lang-specific code. */
755 : 76236126 : if (!c_dialect_cxx ())
756 : : {
757 : 36851329 : bc_state_t save_state;
758 : 36851329 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
759 : 36851329 : save_bc_state (&save_state);
760 : 36851329 : hash_set<tree> pset;
761 : 36851329 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
762 : : &pset);
763 : 36851343 : delete bc_hash_map;
764 : 36851329 : bc_hash_map = NULL;
765 : 36851329 : restore_bc_state (&save_state);
766 : 36851329 : pop_cfun ();
767 : 36851329 : }
768 : :
769 : 76236126 : if (warn_duplicated_branches)
770 : 130 : walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
771 : : do_warn_duplicated_branches_r, NULL);
772 : :
773 : : /* Dump the C-specific tree IR. */
774 : 76236126 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
775 : 76236126 : dump_orig = dfi->pstream;
776 : 76236126 : local_dump_flags = dfi->pflags;
777 : 76236126 : if (dump_orig)
778 : : {
779 : 5510 : fprintf (dump_orig, "\n;; Function %s",
780 : 5510 : lang_hooks.decl_printable_name (fndecl, 2));
781 : 5510 : fprintf (dump_orig, " (%s)\n",
782 : 5510 : (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
783 : 60 : : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
784 : 5510 : fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
785 : 5510 : fprintf (dump_orig, "\n");
786 : :
787 : 5510 : if (local_dump_flags & TDF_RAW)
788 : 1 : dump_node (DECL_SAVED_TREE (fndecl),
789 : : TDF_SLIM | local_dump_flags, dump_orig);
790 : : else
791 : 5509 : print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl), local_dump_flags);
792 : 5510 : fprintf (dump_orig, "\n");
793 : : }
794 : :
795 : : /* Dump all nested functions now. */
796 : 76236126 : cgn = cgraph_node::get_create (fndecl);
797 : 76237652 : for (cgn = first_nested_function (cgn);
798 : 76237652 : cgn; cgn = next_nested_function (cgn))
799 : 1526 : c_genericize (cgn->decl);
800 : 76236126 : }
801 : :
802 : : static void
803 : 0 : add_block_to_enclosing (tree block)
804 : : {
805 : 0 : unsigned i;
806 : 0 : tree enclosing;
807 : 0 : gbind *bind;
808 : 0 : vec<gbind *> stack = gimple_bind_expr_stack ();
809 : :
810 : 0 : FOR_EACH_VEC_ELT (stack, i, bind)
811 : 0 : if (gimple_bind_block (bind))
812 : : break;
813 : :
814 : 0 : enclosing = gimple_bind_block (bind);
815 : 0 : BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
816 : 0 : }
817 : :
818 : : /* Genericize a scope by creating a new BIND_EXPR.
819 : : BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
820 : : In the latter case, we need to create a new BLOCK and add it to the
821 : : BLOCK_SUBBLOCKS of the enclosing block.
822 : : BODY is a chain of C _STMT nodes for the contents of the scope, to be
823 : : genericized. */
824 : :
825 : : tree
826 : 129115289 : c_build_bind_expr (location_t loc, tree block, tree body)
827 : : {
828 : 129115289 : tree decls, bind;
829 : :
830 : 129115289 : if (block == NULL_TREE)
831 : : decls = NULL_TREE;
832 : 58051987 : else if (TREE_CODE (block) == BLOCK)
833 : 58051987 : decls = BLOCK_VARS (block);
834 : : else
835 : : {
836 : 0 : decls = block;
837 : 0 : if (DECL_ARTIFICIAL (decls))
838 : : block = NULL_TREE;
839 : : else
840 : : {
841 : 0 : block = make_node (BLOCK);
842 : 0 : BLOCK_VARS (block) = decls;
843 : 0 : add_block_to_enclosing (block);
844 : : }
845 : : }
846 : :
847 : 129115289 : if (!body)
848 : 0 : body = build_empty_stmt (loc);
849 : 129115289 : if (decls || block)
850 : : {
851 : 58051987 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
852 : 58051987 : TREE_SIDE_EFFECTS (bind) = 1;
853 : 58051987 : SET_EXPR_LOCATION (bind, loc);
854 : : }
855 : : else
856 : : bind = body;
857 : :
858 : 129115289 : return bind;
859 : : }
860 : :
861 : : /* Helper for c_gimplify_expr: test if target supports fma-like FN. */
862 : :
863 : : static bool
864 : 0 : fma_supported_p (enum internal_fn fn, tree type)
865 : : {
866 : 0 : return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
867 : : }
868 : :
869 : : /* Gimplification of expression trees. */
870 : :
871 : : /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in
872 : : gimplify_expr. */
873 : :
874 : : int
875 : 252537148 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
876 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
877 : : {
878 : 252537148 : enum tree_code code = TREE_CODE (*expr_p);
879 : :
880 : 252537148 : switch (code)
881 : : {
882 : 364363 : case LSHIFT_EXPR:
883 : 364363 : case RSHIFT_EXPR:
884 : 364363 : case LROTATE_EXPR:
885 : 364363 : case RROTATE_EXPR:
886 : 364363 : {
887 : : /* We used to convert the right operand of a shift-expression
888 : : to an integer_type_node in the FEs. But it is unnecessary
889 : : and not desirable for diagnostics and sanitizers. We keep
890 : : this here to not pessimize the code, but we convert to an
891 : : unsigned type, because negative shift counts are undefined
892 : : anyway.
893 : : We should get rid of this conversion when we have a proper
894 : : type demotion/promotion pass. */
895 : 364363 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
896 : 364363 : if (!error_operand_p (*op1_p)
897 : 364362 : && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
898 : 362647 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
899 : : unsigned_type_node)
900 : 667771 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
901 : : integer_type_node))
902 : : /* Make sure to unshare the result, tree sharing is invalid
903 : : during gimplification. */
904 : 25198 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
905 : : break;
906 : : }
907 : :
908 : 1117941 : case PREINCREMENT_EXPR:
909 : 1117941 : case PREDECREMENT_EXPR:
910 : 1117941 : case POSTINCREMENT_EXPR:
911 : 1117941 : case POSTDECREMENT_EXPR:
912 : 1117941 : {
913 : 1117941 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
914 : 1117941 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
915 : : {
916 : 5510 : if (!TYPE_OVERFLOW_WRAPS (type))
917 : 3231 : type = unsigned_type_for (type);
918 : 5510 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
919 : : }
920 : : break;
921 : : }
922 : :
923 : 7431398 : case PLUS_EXPR:
924 : 7431398 : case MINUS_EXPR:
925 : 7431398 : {
926 : 7431398 : tree type = TREE_TYPE (*expr_p);
927 : : /* For -ffp-contract=on we need to attempt FMA contraction only
928 : : during initial gimplification. Late contraction across statement
929 : : boundaries would violate language semantics. */
930 : 7431398 : if (SCALAR_FLOAT_TYPE_P (type)
931 : 955209 : && flag_fp_contract_mode == FP_CONTRACT_ON
932 : 0 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
933 : 7431398 : && fma_supported_p (IFN_FMA, type))
934 : : {
935 : 0 : bool neg_mul = false, neg_add = code == MINUS_EXPR;
936 : :
937 : 0 : tree *op0_p = &TREE_OPERAND (*expr_p, 0);
938 : 0 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
939 : :
940 : : /* Look for ±(x * y) ± z, swapping operands if necessary. */
941 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR
942 : 0 : && TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
943 : : /* '*EXPR_P' is '-(x * y) ± z'. This is fine. */;
944 : 0 : else if (TREE_CODE (*op0_p) != MULT_EXPR)
945 : : {
946 : : std::swap (op0_p, op1_p);
947 : : std::swap (neg_mul, neg_add);
948 : : }
949 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR)
950 : : {
951 : 0 : op0_p = &TREE_OPERAND (*op0_p, 0);
952 : 0 : neg_mul = !neg_mul;
953 : : }
954 : 0 : if (TREE_CODE (*op0_p) != MULT_EXPR)
955 : : break;
956 : 0 : auto_vec<tree, 3> ops (3);
957 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 0));
958 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 1));
959 : 0 : ops.quick_push (*op1_p);
960 : :
961 : 0 : enum internal_fn ifn = IFN_FMA;
962 : 0 : if (neg_mul)
963 : : {
964 : 0 : if (fma_supported_p (IFN_FNMA, type))
965 : : ifn = IFN_FNMA;
966 : : else
967 : 0 : ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
968 : : }
969 : 0 : if (neg_add)
970 : : {
971 : 0 : enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
972 : 0 : if (fma_supported_p (ifn2, type))
973 : : ifn = ifn2;
974 : : else
975 : 0 : ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
976 : : }
977 : : /* Avoid gimplify_arg: it emits all side effects into *PRE_P. */
978 : 0 : for (auto &&op : ops)
979 : 0 : if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
980 : : == GS_ERROR)
981 : : return GS_ERROR;
982 : :
983 : 0 : gcall *call = gimple_build_call_internal_vec (ifn, ops);
984 : 0 : gimple_seq_add_stmt_without_update (pre_p, call);
985 : 0 : *expr_p = create_tmp_var (type);
986 : 0 : gimple_call_set_lhs (call, *expr_p);
987 : 0 : return GS_ALL_DONE;
988 : 0 : }
989 : : break;
990 : : }
991 : :
992 : 3728582 : case CALL_EXPR:
993 : 3728582 : {
994 : 3728582 : tree fndecl = get_callee_fndecl (*expr_p);
995 : 3728582 : if (fndecl
996 : 3479415 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
997 : 52 : && call_expr_nargs (*expr_p) == 2
998 : 3728634 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
999 : : {
1000 : 52 : tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
1001 : 52 : tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
1002 : : fndecl, 1, a);
1003 : 104 : *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
1004 : : integer_type_node,
1005 : 52 : build2_loc (EXPR_LOCATION (*expr_p),
1006 : : NE_EXPR, boolean_type_node, a,
1007 : 52 : build_zero_cst (TREE_TYPE (a))),
1008 : 52 : c, CALL_EXPR_ARG (*expr_p, 1));
1009 : 52 : return GS_OK;
1010 : : }
1011 : : break;
1012 : : }
1013 : :
1014 : : default:;
1015 : : }
1016 : :
1017 : : return GS_UNHANDLED;
1018 : : }
|