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 : 1253640 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
73 : : {
74 : 1253640 : hash_set<tree> *pset = (hash_set<tree> *) data;
75 : :
76 : 1253640 : 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 : 64365 : *walk_subtrees = 0;
82 : 80088 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
83 : : {
84 : 15723 : if (TREE_STATIC (decl))
85 : 149 : continue;
86 : 15574 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
87 : : pset);
88 : 15574 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
89 : 15574 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
90 : : pset);
91 : : }
92 : 64365 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
93 : : }
94 : 1189275 : else if (TREE_CODE (*tp) == ADDR_EXPR
95 : 1189275 : && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
96 : : {
97 : 259 : 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 : 259 : tree aref = TREE_OPERAND (*tp, 0);
103 : 259 : pset->add (aref);
104 : 259 : *walk_subtrees = 0;
105 : 259 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
106 : 259 : walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
107 : 259 : walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
108 : 259 : walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
109 : : }
110 : 1189016 : else if (TREE_CODE (*tp) == ARRAY_REF)
111 : 3984 : ubsan_maybe_instrument_array_ref (tp, false);
112 : 1185032 : 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 : 65882 : *walk_subtrees = 0;
121 : 65882 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
122 : 65882 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
123 : : }
124 : 1253640 : 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 : 7319739 : begin_bc_block (enum bc_t bc, location_t location)
149 : : {
150 : 7319739 : tree label = create_artificial_label (location);
151 : 7319739 : DECL_CHAIN (label) = bc_label[bc];
152 : 7319739 : bc_label[bc] = label;
153 : 7319739 : if (bc == bc_break)
154 : 3810766 : LABEL_DECL_BREAK (label) = true;
155 : : else
156 : 3508973 : LABEL_DECL_CONTINUE (label) = true;
157 : 7319739 : 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 : 7319739 : finish_bc_block (tree *block, enum bc_t bc, tree label)
169 : : {
170 : 7319739 : gcc_assert (label == bc_label[bc]);
171 : :
172 : 7319739 : if (TREE_USED (label))
173 : 2869210 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
174 : : block);
175 : :
176 : 7319739 : bc_label[bc] = DECL_CHAIN (label);
177 : 7319739 : DECL_CHAIN (label) = NULL_TREE;
178 : 7319739 : }
179 : :
180 : : /* For named loop or switch with NAME, remember corresponding break
181 : : label BLAB and continue label CLAB. */
182 : :
183 : : static void
184 : 51 : note_named_bc (tree name, tree blab, tree clab)
185 : : {
186 : 51 : if (bc_hash_map == NULL)
187 : 15 : bc_hash_map = new bc_hash_map_t (32);
188 : 51 : bc_hash_map->put (name, std::make_pair (blab, clab));
189 : 51 : }
190 : :
191 : : /* Remove NAME from the map after processing body of the loop or
192 : : switch. */
193 : :
194 : : static void
195 : 51 : 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 : 76800600 : save_bc_state (bc_state_t *state)
204 : : {
205 : 76800600 : state->bc_label[bc_break] = bc_label[bc_break];
206 : 76800600 : state->bc_label[bc_continue] = bc_label[bc_continue];
207 : 76800600 : state->bc_hash_map = bc_hash_map;
208 : 76800600 : bc_label[bc_break] = NULL_TREE;
209 : 76800600 : bc_label[bc_continue] = NULL_TREE;
210 : 76800600 : bc_hash_map = NULL;
211 : 76800600 : }
212 : :
213 : : void
214 : 76800600 : restore_bc_state (bc_state_t *state)
215 : : {
216 : 76800600 : gcc_assert (bc_label[bc_break] == NULL);
217 : 76800600 : gcc_assert (bc_label[bc_continue] == NULL);
218 : 76800600 : gcc_assert (bc_hash_map == NULL);
219 : 76800600 : bc_label[bc_break] = state->bc_label[bc_break];
220 : 76800600 : bc_label[bc_continue] = state->bc_label[bc_continue];
221 : 76800600 : bc_hash_map = state->bc_hash_map;
222 : 76800600 : }
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 : 3996205 : get_bc_label (enum bc_t bc)
229 : : {
230 : 3996205 : tree label = bc_label[bc];
231 : 3996205 : gcc_assert (label);
232 : :
233 : : /* Mark the label used for finish_bc_block. */
234 : 3996205 : TREE_USED (label) = 1;
235 : 3996205 : return label;
236 : : }
237 : :
238 : : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
239 : :
240 : : location_t
241 : 8288547 : expr_loc_or_loc (const_tree expr, location_t or_loc)
242 : : {
243 : 8288547 : tree t = CONST_CAST_TREE (expr);
244 : 8288547 : location_t loc = UNKNOWN_LOCATION;
245 : 8288547 : if (t)
246 : 6295675 : loc = EXPR_LOCATION (t);
247 : 5065030 : if (loc == UNKNOWN_LOCATION)
248 : 4504411 : loc = or_loc;
249 : 8288547 : 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 : 3466601 : 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 : 3466601 : tree blab, clab;
273 : 3466601 : tree entry = NULL, exit = NULL, t;
274 : 3466601 : tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
275 : 3466601 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
276 : 3466601 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
277 : :
278 : 3466601 : protected_set_expr_location_if_unset (incr, start_locus);
279 : :
280 : 3466601 : walk_tree_1 (&cond_prep, func, data, NULL, lh);
281 : 3466601 : walk_tree_1 (&cond, func, data, NULL, lh);
282 : 3466601 : walk_tree_1 (&incr, func, data, NULL, lh);
283 : :
284 : 3466601 : blab = begin_bc_block (bc_break, start_locus);
285 : 3466601 : clab = begin_bc_block (bc_continue, start_locus);
286 : 3466601 : if (name)
287 : 39 : note_named_bc (name, blab, clab);
288 : :
289 : 3466601 : walk_tree_1 (&body, func, data, NULL, lh);
290 : 3466601 : *walk_subtrees = 0;
291 : :
292 : 3466601 : if (name)
293 : 39 : release_named_bc (name);
294 : :
295 : 3466601 : 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 : 9941 : gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
316 : 9941 : tree top = build1 (LABEL_EXPR, void_type_node,
317 : : create_artificial_label (start_locus));
318 : 9941 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
319 : 9941 : append_to_statement_list (top, &outer_stmt_list);
320 : 9941 : append_to_statement_list (cond_prep, &outer_stmt_list);
321 : 9941 : stmt_list_p = &BIND_EXPR_BODY (cond_prep);
322 : 9941 : 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 : 9941 : stmt_list = *stmt_list_p;
330 : 9941 : *stmt_list_p = NULL_TREE;
331 : 9941 : tree after_cond = create_artificial_label (cond_locus);
332 : 9941 : tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
333 : 9941 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
334 : 9941 : t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
335 : : goto_after_cond, t);
336 : 9941 : append_to_statement_list (t, &stmt_list);
337 : 9941 : t = build1 (LABEL_EXPR, void_type_node, after_cond);
338 : 9941 : append_to_statement_list (t, &stmt_list);
339 : : }
340 : 3456660 : else if (cond && integer_zerop (cond))
341 : : {
342 : : /* If condition is zero don't generate a loop construct. */
343 : 1180996 : if (cond_is_first)
344 : : {
345 : 268 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
346 : : get_bc_label (bc_break));
347 : 268 : append_to_statement_list (t, &stmt_list);
348 : : }
349 : : }
350 : : else
351 : : {
352 : : /* Expand to gotos. */
353 : 2275664 : 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 : 2275664 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
360 : :
361 : 2275664 : 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 : 2161635 : if (cond_is_first)
367 : : {
368 : 2011629 : if (incr)
369 : : {
370 : 1532158 : entry = build1 (LABEL_EXPR, void_type_node,
371 : : create_artificial_label (start_locus));
372 : 3064316 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
373 : 1532158 : LABEL_EXPR_LABEL (entry));
374 : : }
375 : : else
376 : 479471 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
377 : : get_bc_label (bc_continue));
378 : 2011629 : append_to_statement_list (t, &stmt_list);
379 : : }
380 : :
381 : 2161635 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
382 : 2161635 : 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 : 114029 : location_t loc = expr_loc_or_loc (expr_first (body),
391 : : start_locus);
392 : 114029 : SET_EXPR_LOCATION (exit, loc);
393 : : }
394 : 2275664 : append_to_statement_list (top, &stmt_list);
395 : : }
396 : :
397 : 3466601 : append_to_statement_list (body, &stmt_list);
398 : 3466601 : if (c_dialect_cxx ()
399 : 3005833 : && stmt_list
400 : 3003936 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
401 : : {
402 : 3003936 : tree_stmt_iterator tsi = tsi_last (stmt_list);
403 : 3003936 : if (!tsi_end_p (tsi))
404 : : {
405 : 3003936 : tree t = *tsi;
406 : 3003936 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
407 : : || TREE_CODE (t) == EXPR_STMT
408 : 5417553 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
409 : 2413617 : 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 : 3003936 : if (TREE_CODE (t) == CALL_EXPR
414 : 121527 : && !CALL_EXPR_FN (t)
415 : 3003948 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
416 : 12 : TREE_NOTHROW (t) = 1;
417 : : }
418 : : }
419 : 3466601 : finish_bc_block (&stmt_list, bc_continue, clab);
420 : 3466601 : if (incr)
421 : : {
422 : 1539443 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
423 : : {
424 : 1241316 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
425 : 1241316 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
426 : 1241316 : append_to_statement_list (d, &stmt_list);
427 : : }
428 : 1539443 : append_to_statement_list (incr, &stmt_list);
429 : : }
430 : 3466601 : append_to_statement_list (entry, &stmt_list);
431 : :
432 : 3466601 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
433 : : {
434 : 2944212 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
435 : 2944212 : SET_EXPR_LOCATION (d, cond_locus);
436 : 2944212 : append_to_statement_list (d, &stmt_list);
437 : : }
438 : 3466601 : append_to_statement_list (exit, &stmt_list);
439 : 3466601 : if (stmt_list_p)
440 : : {
441 : 9941 : *stmt_list_p = stmt_list;
442 : 9941 : stmt_list = outer_stmt_list;
443 : : }
444 : 3466601 : finish_bc_block (&stmt_list, bc_break, blab);
445 : 3466601 : if (!stmt_list)
446 : 3681 : stmt_list = build_empty_stmt (start_locus);
447 : :
448 : 3466601 : *stmt_p = stmt_list;
449 : 3466601 : }
450 : :
451 : : /* Genericize a FOR_STMT node *STMT_P. */
452 : :
453 : : static void
454 : 1605426 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
455 : : walk_tree_fn func, walk_tree_lh lh)
456 : : {
457 : 1605426 : tree stmt = *stmt_p;
458 : 1605426 : tree expr = NULL;
459 : 1605426 : tree loop;
460 : 1605426 : tree init = FOR_INIT_STMT (stmt);
461 : :
462 : 1605426 : if (init)
463 : : {
464 : 0 : walk_tree_1 (&init, func, data, NULL, lh);
465 : 0 : append_to_statement_list (init, &expr);
466 : : }
467 : :
468 : 3210852 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
469 : 1605426 : FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
470 : 1605426 : FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
471 : : walk_subtrees, data, func, lh);
472 : 1605426 : append_to_statement_list (loop, &expr);
473 : 1605426 : if (expr == NULL_TREE)
474 : 0 : expr = loop;
475 : 1605426 : *stmt_p = expr;
476 : 1605426 : }
477 : :
478 : : /* Genericize a WHILE_STMT node *STMT_P. */
479 : :
480 : : static void
481 : 530045 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
482 : : walk_tree_fn func, walk_tree_lh lh)
483 : : {
484 : 530045 : tree stmt = *stmt_p;
485 : 1060090 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
486 : 530045 : WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
487 : 530045 : WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
488 : : walk_subtrees, data, func, lh);
489 : 530045 : }
490 : :
491 : : /* Genericize a DO_STMT node *STMT_P. */
492 : :
493 : : static void
494 : 1331130 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
495 : : walk_tree_fn func, walk_tree_lh lh)
496 : : {
497 : 1331130 : tree stmt = *stmt_p;
498 : 2662260 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
499 : 1331130 : DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
500 : : NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
501 : 1331130 : }
502 : :
503 : : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
504 : :
505 : : static void
506 : 344165 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
507 : : walk_tree_fn func, walk_tree_lh lh)
508 : : {
509 : 344165 : tree stmt = *stmt_p;
510 : 344165 : tree blab, body, cond, type;
511 : 344165 : location_t stmt_locus = EXPR_LOCATION (stmt);
512 : :
513 : 344165 : body = SWITCH_STMT_BODY (stmt);
514 : 344165 : if (!body)
515 : 0 : body = build_empty_stmt (stmt_locus);
516 : 344165 : cond = SWITCH_STMT_COND (stmt);
517 : 344165 : type = SWITCH_STMT_TYPE (stmt);
518 : :
519 : 344165 : walk_tree_1 (&cond, func, data, NULL, lh);
520 : :
521 : 344165 : blab = begin_bc_block (bc_break, stmt_locus);
522 : 344165 : if (SWITCH_STMT_NAME (stmt))
523 : 12 : note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
524 : :
525 : 344165 : walk_tree_1 (&body, func, data, NULL, lh);
526 : :
527 : 344165 : if (SWITCH_STMT_NAME (stmt))
528 : 12 : release_named_bc (SWITCH_STMT_NAME (stmt));
529 : :
530 : 344165 : walk_tree_1 (&type, func, data, NULL, lh);
531 : 344165 : *walk_subtrees = 0;
532 : :
533 : 344165 : if (TREE_USED (blab))
534 : 157282 : SWITCH_BREAK_LABEL_P (blab) = 1;
535 : 344165 : finish_bc_block (&body, bc_break, blab);
536 : 344165 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
537 : 344165 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
538 : 344165 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
539 : : || !TREE_USED (blab));
540 : 344165 : }
541 : :
542 : : /* Genericize a CONTINUE_STMT node *STMT_P. */
543 : :
544 : : static void
545 : 17075 : genericize_continue_stmt (tree *stmt_p)
546 : : {
547 : 17075 : tree stmt_list = NULL;
548 : 17075 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
549 : 17075 : tree label;
550 : 17075 : if (CONTINUE_NAME (*stmt_p))
551 : : {
552 : 42 : tree_pair *slot = bc_hash_map->get (CONTINUE_NAME (*stmt_p));
553 : 42 : gcc_checking_assert (slot);
554 : 42 : label = slot->second;
555 : 42 : TREE_USED (label) = 1;
556 : : }
557 : : else
558 : 17033 : label = get_bc_label (bc_continue);
559 : 17075 : location_t location = EXPR_LOCATION (*stmt_p);
560 : 17075 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
561 : 17075 : append_to_statement_list_force (pred, &stmt_list);
562 : 17075 : append_to_statement_list (jump, &stmt_list);
563 : 17075 : *stmt_p = stmt_list;
564 : 17075 : }
565 : :
566 : : /* Genericize a BREAK_STMT node *STMT_P. */
567 : :
568 : : static void
569 : 1327910 : genericize_break_stmt (tree *stmt_p)
570 : : {
571 : 1327910 : tree label;
572 : 1327910 : if (BREAK_NAME (*stmt_p))
573 : : {
574 : 53 : tree_pair *slot = bc_hash_map->get (BREAK_NAME (*stmt_p));
575 : 53 : gcc_checking_assert (slot);
576 : 53 : label = slot->first;
577 : 53 : TREE_USED (label) = 1;
578 : : }
579 : : else
580 : 1327857 : label = get_bc_label (bc_break);
581 : 1327910 : location_t location = EXPR_LOCATION (*stmt_p);
582 : 1327910 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
583 : 1327910 : }
584 : :
585 : : /* Genericize a OMP_FOR node *STMT_P. */
586 : :
587 : : static void
588 : 42372 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
589 : : walk_tree_fn func, walk_tree_lh lh)
590 : : {
591 : 42372 : tree stmt = *stmt_p;
592 : 42372 : location_t locus = EXPR_LOCATION (stmt);
593 : 42372 : tree clab = begin_bc_block (bc_continue, locus);
594 : :
595 : 42372 : walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
596 : 42372 : if (TREE_CODE (stmt) != OMP_TASKLOOP)
597 : 40966 : walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
598 : 42372 : walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
599 : 42372 : walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
600 : 42372 : walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
601 : 42372 : walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
602 : 42372 : *walk_subtrees = 0;
603 : :
604 : 42372 : finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
605 : 42372 : }
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 : 697859527 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
637 : : walk_tree_fn func, walk_tree_lh lh)
638 : : {
639 : 697859527 : tree stmt = *stmt_p;
640 : :
641 : 697859527 : switch (TREE_CODE (stmt))
642 : : {
643 : 1605426 : case FOR_STMT:
644 : 1605426 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
645 : 1605426 : break;
646 : :
647 : 530045 : case WHILE_STMT:
648 : 530045 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
649 : 530045 : break;
650 : :
651 : 1331130 : case DO_STMT:
652 : 1331130 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
653 : 1331130 : break;
654 : :
655 : 344165 : case SWITCH_STMT:
656 : 344165 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
657 : 344165 : break;
658 : :
659 : 17075 : case CONTINUE_STMT:
660 : 17075 : genericize_continue_stmt (stmt_p);
661 : 17075 : break;
662 : :
663 : 1327910 : case BREAK_STMT:
664 : 1327910 : genericize_break_stmt (stmt_p);
665 : 1327910 : break;
666 : :
667 : 42372 : case OMP_FOR:
668 : 42372 : case OMP_SIMD:
669 : 42372 : case OMP_DISTRIBUTE:
670 : 42372 : case OMP_LOOP:
671 : 42372 : case OMP_TASKLOOP:
672 : 42372 : case OMP_TILE:
673 : 42372 : case OMP_UNROLL:
674 : 42372 : case OACC_LOOP:
675 : 42372 : genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
676 : 42372 : 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 : 52416915 : case STATEMENT_LIST:
684 : 52416915 : if (TREE_SIDE_EFFECTS (stmt))
685 : : {
686 : 50114444 : tree_stmt_iterator i;
687 : 50114444 : int nondebug_stmts = 0;
688 : 50114444 : 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 : 46528248 : hash_set<tree> *pset = (c_dialect_cxx ()
697 : 50114444 : ? nullptr
698 : : : static_cast<hash_set<tree> *>(data));
699 : 216690568 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
700 : : {
701 : 166576124 : tree t = tsi_stmt (i);
702 : 166576124 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
703 : 78111104 : nondebug_stmts++;
704 : 166576124 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
705 : 166576124 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
706 : 166576124 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
707 : : clear_side_effects = false;
708 : : }
709 : 50114444 : if (clear_side_effects)
710 : 375 : TREE_SIDE_EFFECTS (stmt) = 0;
711 : 50114444 : *walk_subtrees = 0;
712 : : }
713 : : break;
714 : :
715 : : default:
716 : : break;
717 : : }
718 : :
719 : 697859527 : 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 : 644557872 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
729 : : {
730 : 644557872 : tree stmt = *stmt_p;
731 : : /* Mark stores to parts of complex automatic non-addressable
732 : : variables as DECL_NOT_GIMPLE_REG_P for -O0. This can't be
733 : : done during gimplification. See PR119120. */
734 : 644557872 : if (TREE_CODE (stmt) == MODIFY_EXPR
735 : 36609484 : && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
736 : 36608412 : || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
737 : 2156 : && !optimize
738 : 138 : && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
739 : 644557996 : && is_gimple_reg (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)))
740 : 63 : DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
741 : :
742 : 644557872 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
743 : : c_genericize_control_r, NULL);
744 : 644557872 : return NULL;
745 : : }
746 : :
747 : : /* Convert the tree representation of FNDECL from C frontend trees to
748 : : GENERIC. */
749 : :
750 : : void
751 : 76800600 : c_genericize (tree fndecl)
752 : : {
753 : 76800600 : dump_file_info *dfi;
754 : 76800600 : FILE *dump_orig;
755 : 76800600 : dump_flags_t local_dump_flags;
756 : 76800600 : struct cgraph_node *cgn;
757 : :
758 : 76800600 : if (flag_sanitize & SANITIZE_BOUNDS)
759 : : {
760 : 66335 : hash_set<tree> pset;
761 : 66335 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
762 : : &pset);
763 : 66335 : }
764 : :
765 : : /* Genericize loops and other structured control constructs. The C++
766 : : front end has already done this in lang-specific code. */
767 : 76800600 : if (!c_dialect_cxx ())
768 : : {
769 : 35349674 : bc_state_t save_state;
770 : 35349674 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
771 : 35349674 : save_bc_state (&save_state);
772 : 35349674 : hash_set<tree> pset;
773 : 35349674 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
774 : : &pset);
775 : 35349689 : delete bc_hash_map;
776 : 35349674 : bc_hash_map = NULL;
777 : 35349674 : restore_bc_state (&save_state);
778 : 35349674 : pop_cfun ();
779 : 35349674 : }
780 : :
781 : 76800600 : if (warn_duplicated_branches)
782 : 130 : walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
783 : : do_warn_duplicated_branches_r, NULL);
784 : :
785 : : /* Dump the C-specific tree IR. */
786 : 76800600 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
787 : 76800600 : dump_orig = dfi->pstream;
788 : 76800600 : local_dump_flags = dfi->pflags;
789 : 76800600 : if (dump_orig)
790 : : {
791 : 5582 : fprintf (dump_orig, "\n;; Function %s",
792 : 5582 : lang_hooks.decl_printable_name (fndecl, 2));
793 : 5582 : fprintf (dump_orig, " (%s)\n",
794 : 5582 : (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
795 : 59 : : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
796 : 5582 : fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
797 : 5582 : fprintf (dump_orig, "\n");
798 : :
799 : 5582 : if (local_dump_flags & TDF_RAW)
800 : 1 : dump_node (DECL_SAVED_TREE (fndecl),
801 : : TDF_SLIM | local_dump_flags, dump_orig);
802 : : else
803 : 5581 : print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl), local_dump_flags);
804 : 5582 : fprintf (dump_orig, "\n");
805 : : }
806 : :
807 : : /* Dump all nested functions now. */
808 : 76800600 : cgn = cgraph_node::get_create (fndecl);
809 : 76802126 : for (cgn = first_nested_function (cgn);
810 : 76802126 : cgn; cgn = next_nested_function (cgn))
811 : 1526 : c_genericize (cgn->decl);
812 : 76800600 : }
813 : :
814 : : static void
815 : 0 : add_block_to_enclosing (tree block)
816 : : {
817 : 0 : unsigned i;
818 : 0 : tree enclosing;
819 : 0 : gbind *bind;
820 : 0 : vec<gbind *> stack = gimple_bind_expr_stack ();
821 : :
822 : 0 : FOR_EACH_VEC_ELT (stack, i, bind)
823 : 0 : if (gimple_bind_block (bind))
824 : : break;
825 : :
826 : 0 : enclosing = gimple_bind_block (bind);
827 : 0 : BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
828 : 0 : }
829 : :
830 : : /* Genericize a scope by creating a new BIND_EXPR.
831 : : BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
832 : : In the latter case, we need to create a new BLOCK and add it to the
833 : : BLOCK_SUBBLOCKS of the enclosing block.
834 : : BODY is a chain of C _STMT nodes for the contents of the scope, to be
835 : : genericized. */
836 : :
837 : : tree
838 : 133694744 : c_build_bind_expr (location_t loc, tree block, tree body)
839 : : {
840 : 133694744 : tree decls, bind;
841 : :
842 : 133694744 : if (block == NULL_TREE)
843 : : decls = NULL_TREE;
844 : 57983031 : else if (TREE_CODE (block) == BLOCK)
845 : 57983031 : decls = BLOCK_VARS (block);
846 : : else
847 : : {
848 : 0 : decls = block;
849 : 0 : if (DECL_ARTIFICIAL (decls))
850 : : block = NULL_TREE;
851 : : else
852 : : {
853 : 0 : block = make_node (BLOCK);
854 : 0 : BLOCK_VARS (block) = decls;
855 : 0 : add_block_to_enclosing (block);
856 : : }
857 : : }
858 : :
859 : 133694744 : if (!body)
860 : 0 : body = build_empty_stmt (loc);
861 : 133694744 : if (decls || block)
862 : : {
863 : 57983031 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
864 : 57983031 : TREE_SIDE_EFFECTS (bind) = 1;
865 : 57983031 : SET_EXPR_LOCATION (bind, loc);
866 : : }
867 : : else
868 : : bind = body;
869 : :
870 : 133694744 : return bind;
871 : : }
872 : :
873 : : /* Helper for c_gimplify_expr: test if target supports fma-like FN. */
874 : :
875 : : static bool
876 : 0 : fma_supported_p (enum internal_fn fn, tree type)
877 : : {
878 : 0 : return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
879 : : }
880 : :
881 : : /* Gimplification of expression trees. */
882 : :
883 : : /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in
884 : : gimplify_expr. */
885 : :
886 : : int
887 : 267823982 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
888 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
889 : : {
890 : 267823982 : enum tree_code code = TREE_CODE (*expr_p);
891 : :
892 : 267823982 : switch (code)
893 : : {
894 : 371042 : case LSHIFT_EXPR:
895 : 371042 : case RSHIFT_EXPR:
896 : 371042 : case LROTATE_EXPR:
897 : 371042 : case RROTATE_EXPR:
898 : 371042 : {
899 : : /* We used to convert the right operand of a shift-expression
900 : : to an integer_type_node in the FEs. But it is unnecessary
901 : : and not desirable for diagnostics and sanitizers. We keep
902 : : this here to not pessimize the code, but we convert to an
903 : : unsigned type, because negative shift counts are undefined
904 : : anyway.
905 : : We should get rid of this conversion when we have a proper
906 : : type demotion/promotion pass. */
907 : 371042 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
908 : 371042 : if (!error_operand_p (*op1_p)
909 : 371041 : && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
910 : 369325 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
911 : : unsigned_type_node)
912 : 679238 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
913 : : integer_type_node))
914 : : /* Make sure to unshare the result, tree sharing is invalid
915 : : during gimplification. */
916 : 26845 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
917 : : break;
918 : : }
919 : :
920 : 1136193 : case PREINCREMENT_EXPR:
921 : 1136193 : case PREDECREMENT_EXPR:
922 : 1136193 : case POSTINCREMENT_EXPR:
923 : 1136193 : case POSTDECREMENT_EXPR:
924 : 1136193 : {
925 : 1136193 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
926 : 1136193 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
927 : : {
928 : 5914 : if (!TYPE_OVERFLOW_WRAPS (type))
929 : 3376 : type = unsigned_type_for (type);
930 : 5914 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
931 : : }
932 : : break;
933 : : }
934 : :
935 : 7626406 : case PLUS_EXPR:
936 : 7626406 : case MINUS_EXPR:
937 : 7626406 : {
938 : 7626406 : tree type = TREE_TYPE (*expr_p);
939 : : /* For -ffp-contract=on we need to attempt FMA contraction only
940 : : during initial gimplification. Late contraction across statement
941 : : boundaries would violate language semantics. */
942 : 7626406 : if (SCALAR_FLOAT_TYPE_P (type)
943 : 956300 : && flag_fp_contract_mode == FP_CONTRACT_ON
944 : 0 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
945 : 7626406 : && fma_supported_p (IFN_FMA, type))
946 : : {
947 : 0 : bool neg_mul = false, neg_add = code == MINUS_EXPR;
948 : :
949 : 0 : tree *op0_p = &TREE_OPERAND (*expr_p, 0);
950 : 0 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
951 : :
952 : : /* Look for ±(x * y) ± z, swapping operands if necessary. */
953 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR
954 : 0 : && TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
955 : : /* '*EXPR_P' is '-(x * y) ± z'. This is fine. */;
956 : 0 : else if (TREE_CODE (*op0_p) != MULT_EXPR)
957 : : {
958 : : std::swap (op0_p, op1_p);
959 : : std::swap (neg_mul, neg_add);
960 : : }
961 : 0 : if (TREE_CODE (*op0_p) == NEGATE_EXPR)
962 : : {
963 : 0 : op0_p = &TREE_OPERAND (*op0_p, 0);
964 : 0 : neg_mul = !neg_mul;
965 : : }
966 : 0 : if (TREE_CODE (*op0_p) != MULT_EXPR)
967 : : break;
968 : 0 : auto_vec<tree, 3> ops (3);
969 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 0));
970 : 0 : ops.quick_push (TREE_OPERAND (*op0_p, 1));
971 : 0 : ops.quick_push (*op1_p);
972 : :
973 : 0 : enum internal_fn ifn = IFN_FMA;
974 : 0 : if (neg_mul)
975 : : {
976 : 0 : if (fma_supported_p (IFN_FNMA, type))
977 : : ifn = IFN_FNMA;
978 : : else
979 : 0 : ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
980 : : }
981 : 0 : if (neg_add)
982 : : {
983 : 0 : enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
984 : 0 : if (fma_supported_p (ifn2, type))
985 : : ifn = ifn2;
986 : : else
987 : 0 : ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
988 : : }
989 : : /* Avoid gimplify_arg: it emits all side effects into *PRE_P. */
990 : 0 : for (auto &&op : ops)
991 : 0 : if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
992 : : == GS_ERROR)
993 : : return GS_ERROR;
994 : :
995 : 0 : gcall *call = gimple_build_call_internal_vec (ifn, ops);
996 : 0 : gimple_seq_add_stmt_without_update (pre_p, call);
997 : 0 : *expr_p = create_tmp_var (type);
998 : 0 : gimple_call_set_lhs (call, *expr_p);
999 : 0 : return GS_ALL_DONE;
1000 : 0 : }
1001 : : break;
1002 : : }
1003 : :
1004 : 3724328 : case CALL_EXPR:
1005 : 3724328 : {
1006 : 3724328 : tree fndecl = get_callee_fndecl (*expr_p);
1007 : 3724328 : if (fndecl
1008 : 3475045 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
1009 : 52 : && call_expr_nargs (*expr_p) == 2
1010 : 3724380 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
1011 : : {
1012 : 52 : tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
1013 : 52 : tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
1014 : : fndecl, 1, a);
1015 : 104 : *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
1016 : : integer_type_node,
1017 : 52 : build2_loc (EXPR_LOCATION (*expr_p),
1018 : : NE_EXPR, boolean_type_node, a,
1019 : 52 : build_zero_cst (TREE_TYPE (a))),
1020 : 52 : c, CALL_EXPR_ARG (*expr_p, 1));
1021 : 52 : return GS_OK;
1022 : : }
1023 : : break;
1024 : : }
1025 : :
1026 : : default:;
1027 : : }
1028 : :
1029 : : return GS_UNHANDLED;
1030 : : }
|