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 : :
70 : : /* Check whether TP is an address computation whose base is a call to
71 : : .ACCESS_WITH_SIZE. */
72 : :
73 : : static bool
74 : 1139445 : is_address_with_access_with_size (tree tp)
75 : : {
76 : 1139445 : if (TREE_CODE (tp) == POINTER_PLUS_EXPR
77 : 1139445 : && is_access_with_size_p (TREE_OPERAND (tp, 0)))
78 : : return true;
79 : : return false;
80 : : }
81 : :
82 : : /* Callback for c_genericize. */
83 : :
84 : : static tree
85 : 1265069 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
86 : : {
87 : 1265069 : hash_set<tree> *pset = (hash_set<tree> *) data;
88 : :
89 : 1265069 : if (TREE_CODE (*tp) == BIND_EXPR)
90 : : {
91 : : /* Since walk_tree doesn't call the callback function on the decls
92 : : in BIND_EXPR_VARS, we have to walk them manually, so we can avoid
93 : : instrumenting DECL_INITIAL of TREE_STATIC vars. */
94 : 64960 : *walk_subtrees = 0;
95 : 80826 : for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
96 : : {
97 : 15866 : if (TREE_STATIC (decl))
98 : 150 : continue;
99 : 15716 : walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
100 : : pset);
101 : 15716 : walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
102 : 15716 : walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
103 : : pset);
104 : : }
105 : 64960 : walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
106 : : }
107 : 1200109 : else if (TREE_CODE (*tp) == ADDR_EXPR
108 : 1200109 : && TREE_CODE (TREE_OPERAND (*tp, 0)) == ARRAY_REF)
109 : : {
110 : 259 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), true);
111 : : /* Make sure ubsan_maybe_instrument_array_ref is not called again
112 : : on the ARRAY_REF, the above call might not instrument anything
113 : : as the index might be constant or masked, so ensure it is not
114 : : walked again and walk its subtrees manually. */
115 : 259 : tree aref = TREE_OPERAND (*tp, 0);
116 : 259 : pset->add (aref);
117 : 259 : *walk_subtrees = 0;
118 : 259 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
119 : 259 : walk_tree (&TREE_OPERAND (aref, 1), ubsan_walk_array_refs_r, pset, pset);
120 : 259 : walk_tree (&TREE_OPERAND (aref, 2), ubsan_walk_array_refs_r, pset, pset);
121 : 259 : walk_tree (&TREE_OPERAND (aref, 3), ubsan_walk_array_refs_r, pset, pset);
122 : : }
123 : 1199850 : else if (TREE_CODE (*tp) == ARRAY_REF)
124 : 4014 : ubsan_maybe_instrument_array_ref (tp, false);
125 : 1195836 : else if (TREE_CODE (*tp) == MODIFY_EXPR)
126 : : {
127 : : /* Since r7-1900, we gimplify RHS before LHS. Consider
128 : : a[b] |= c;
129 : : wherein we can have a single shared tree a[b] in both LHS and RHS.
130 : : If we only instrument the LHS and the access is invalid, the program
131 : : could crash before emitting a UBSan error. So instrument the RHS
132 : : first. */
133 : 66415 : *walk_subtrees = 0;
134 : 66415 : walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
135 : 66415 : walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
136 : : }
137 : 1129421 : else if (TREE_CODE (*tp) == INDIRECT_REF
138 : 1129421 : && is_address_with_access_with_size (TREE_OPERAND (*tp, 0)))
139 : : {
140 : 45 : ubsan_maybe_instrument_array_ref (&TREE_OPERAND (*tp, 0), false);
141 : : /* Make sure ubsan_maybe_instrument_array_ref is not called again on
142 : : the POINTER_PLUS_EXPR, so ensure it is not walked again and walk
143 : : its subtrees manually. */
144 : 45 : tree aref = TREE_OPERAND (*tp, 0);
145 : 45 : pset->add (aref);
146 : 45 : *walk_subtrees = 0;
147 : 45 : walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
148 : : }
149 : 1129376 : else if (is_address_with_access_with_size (*tp))
150 : 0 : ubsan_maybe_instrument_array_ref (tp, true);
151 : 1265069 : return NULL_TREE;
152 : : }
153 : :
154 : : /* Gimplification of statement trees. */
155 : :
156 : : /* Local declarations. */
157 : :
158 : : enum bc_t { bc_break = 0, bc_continue = 1 };
159 : :
160 : : /* Stack of labels which are targets for "break" or "continue",
161 : : linked through TREE_CHAIN. */
162 : : static tree bc_label[2];
163 : :
164 : : /* Hash map from loop/switch names (identified by LABEL_DECL) to
165 : : corresponding break and (if any) continue labels. */
166 : : static bc_hash_map_t *bc_hash_map;
167 : :
168 : : /* Begin a scope which can be exited by a break or continue statement. BC
169 : : indicates which.
170 : :
171 : : Just creates a label with location LOCATION and pushes it into the current
172 : : context. */
173 : :
174 : : static tree
175 : 7288634 : begin_bc_block (enum bc_t bc, location_t location)
176 : : {
177 : 7288634 : tree label = create_artificial_label (location);
178 : 7288634 : DECL_CHAIN (label) = bc_label[bc];
179 : 7288634 : bc_label[bc] = label;
180 : 7288634 : if (bc == bc_break)
181 : 3799344 : LABEL_DECL_BREAK (label) = true;
182 : : else
183 : 3489290 : LABEL_DECL_CONTINUE (label) = true;
184 : 7288634 : return label;
185 : : }
186 : :
187 : : /* Finish a scope which can be exited by a break or continue statement.
188 : : LABEL was returned from the most recent call to begin_bc_block. BLOCK is
189 : : an expression for the contents of the scope.
190 : :
191 : : If we saw a break (or continue) in the scope, append a LABEL_EXPR to
192 : : BLOCK. Otherwise, just forget the label. */
193 : :
194 : : static void
195 : 7288634 : finish_bc_block (tree *block, enum bc_t bc, tree label)
196 : : {
197 : 7288634 : gcc_assert (label == bc_label[bc]);
198 : :
199 : 7288634 : if (TREE_USED (label))
200 : 2950085 : append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
201 : : block);
202 : :
203 : 7288634 : bc_label[bc] = DECL_CHAIN (label);
204 : 7288634 : DECL_CHAIN (label) = NULL_TREE;
205 : 7288634 : }
206 : :
207 : : /* For named loop or switch with NAME, remember corresponding break
208 : : label BLAB and continue label CLAB. */
209 : :
210 : : static void
211 : 51 : note_named_bc (tree name, tree blab, tree clab)
212 : : {
213 : 51 : if (bc_hash_map == NULL)
214 : 15 : bc_hash_map = new bc_hash_map_t (32);
215 : 51 : bc_hash_map->put (name, std::make_pair (blab, clab));
216 : 51 : }
217 : :
218 : : /* Remove NAME from the map after processing body of the loop or
219 : : switch. */
220 : :
221 : : static void
222 : 51 : release_named_bc (tree name)
223 : : {
224 : 0 : bc_hash_map->remove (name);
225 : 0 : }
226 : :
227 : : /* Allow saving and restoring break/continue state. */
228 : :
229 : : void
230 : 78139914 : save_bc_state (bc_state_t *state)
231 : : {
232 : 78139914 : state->bc_label[bc_break] = bc_label[bc_break];
233 : 78139914 : state->bc_label[bc_continue] = bc_label[bc_continue];
234 : 78139914 : state->bc_hash_map = bc_hash_map;
235 : 78139914 : bc_label[bc_break] = NULL_TREE;
236 : 78139914 : bc_label[bc_continue] = NULL_TREE;
237 : 78139914 : bc_hash_map = NULL;
238 : 78139914 : }
239 : :
240 : : void
241 : 78139914 : restore_bc_state (bc_state_t *state)
242 : : {
243 : 78139914 : gcc_assert (bc_label[bc_break] == NULL);
244 : 78139914 : gcc_assert (bc_label[bc_continue] == NULL);
245 : 78139914 : gcc_assert (bc_hash_map == NULL);
246 : 78139914 : bc_label[bc_break] = state->bc_label[bc_break];
247 : 78139914 : bc_label[bc_continue] = state->bc_label[bc_continue];
248 : 78139914 : bc_hash_map = state->bc_hash_map;
249 : 78139914 : }
250 : :
251 : : /* Get the LABEL_EXPR to represent a break or continue statement
252 : : in the current block scope. BC indicates which. */
253 : :
254 : : static tree
255 : 4090963 : get_bc_label (enum bc_t bc)
256 : : {
257 : 4090963 : tree label = bc_label[bc];
258 : 4090963 : gcc_assert (label);
259 : :
260 : : /* Mark the label used for finish_bc_block. */
261 : 4090963 : TREE_USED (label) = 1;
262 : 4090963 : return label;
263 : : }
264 : :
265 : : /* Return the location from EXPR, or OR_LOC if the former is unknown. */
266 : :
267 : : location_t
268 : 8289481 : expr_loc_or_loc (const_tree expr, location_t or_loc)
269 : : {
270 : 8289481 : tree t = CONST_CAST_TREE (expr);
271 : 8289481 : location_t loc = UNKNOWN_LOCATION;
272 : 8289481 : if (t)
273 : 6351350 : loc = EXPR_LOCATION (t);
274 : 5201934 : if (loc == UNKNOWN_LOCATION)
275 : 4406294 : loc = or_loc;
276 : 8289481 : return loc;
277 : : }
278 : :
279 : : /* Build a generic representation of one of the C loop forms. COND is the
280 : : loop condition or NULL_TREE. BODY is the (possibly compound) statement
281 : : controlled by the loop. INCR is the increment expression of a for-loop,
282 : : or NULL_TREE. COND_IS_FIRST indicates whether the condition is
283 : : evaluated before the loop body as in while and for loops, or after the
284 : : loop body as in do-while loops. COND_PREP and COND_CLEANUP are used
285 : : for C++ for/while loops with variable declaration as condition. COND_PREP
286 : : is a BIND_EXPR with the declaration and initialization of the condition
287 : : variable, into which COND, BODY, continue label if needed and INCR if
288 : : non-NULL should be appended, and COND_CLEANUP is number of nested
289 : : CLEANUP_STMT -> TRY_FINALLY_EXPR statements at the end. If non-NULL,
290 : : COND, BODY, continue label if needed and INCR if non-NULL should be
291 : : appended to the body of the COND_CLEANUP's nested TRY_FINALLY_EXPR. */
292 : :
293 : : static void
294 : 3446913 : genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
295 : : tree incr, tree name, tree cond_prep, tree cond_cleanup,
296 : : bool cond_is_first, int *walk_subtrees, void *data,
297 : : walk_tree_fn func, walk_tree_lh lh)
298 : : {
299 : 3446913 : tree blab, clab;
300 : 3446913 : tree entry = NULL, exit = NULL, t;
301 : 3446913 : tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
302 : 3446913 : location_t cond_locus = expr_loc_or_loc (cond, start_locus);
303 : 3446913 : location_t incr_locus = expr_loc_or_loc (incr, start_locus);
304 : :
305 : 3446913 : protected_set_expr_location_if_unset (incr, start_locus);
306 : :
307 : 3446913 : walk_tree_1 (&cond_prep, func, data, NULL, lh);
308 : 3446913 : walk_tree_1 (&cond, func, data, NULL, lh);
309 : 3446913 : walk_tree_1 (&incr, func, data, NULL, lh);
310 : :
311 : 3446913 : blab = begin_bc_block (bc_break, start_locus);
312 : 3446913 : clab = begin_bc_block (bc_continue, start_locus);
313 : 3446913 : if (name)
314 : 39 : note_named_bc (name, blab, clab);
315 : :
316 : 3446913 : walk_tree_1 (&body, func, data, NULL, lh);
317 : 3446913 : *walk_subtrees = 0;
318 : :
319 : 3446913 : if (name)
320 : 39 : release_named_bc (name);
321 : :
322 : 3446913 : if (cond_prep)
323 : : {
324 : : /* The C++ cases of
325 : : while (A x = 42) body;
326 : : for (; A x = 42; expr) body;
327 : : This should be expanded into:
328 : :
329 : : top:
330 : : COND_PREP
331 : :
332 : : with either
333 : :
334 : : if (COND); else break;
335 : : BODY;
336 : : cont:
337 : : EXPR;
338 : : goto top;
339 : :
340 : : appended into COND_PREP body or body of some TRY_FINALLY_EXPRs
341 : : at the end of COND_PREP. */
342 : 10161 : gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
343 : 10161 : tree top = build1 (LABEL_EXPR, void_type_node,
344 : : create_artificial_label (start_locus));
345 : 10161 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
346 : 10161 : append_to_statement_list (top, &outer_stmt_list);
347 : 10161 : append_to_statement_list (cond_prep, &outer_stmt_list);
348 : 10161 : stmt_list_p = &BIND_EXPR_BODY (cond_prep);
349 : 10161 : if (cond_cleanup)
350 : 206 : for (unsigned depth = tree_to_uhwi (cond_cleanup); depth; --depth)
351 : : {
352 : 109 : t = tsi_stmt (tsi_last (*stmt_list_p));
353 : 109 : gcc_assert (TREE_CODE (t) == TRY_FINALLY_EXPR);
354 : 109 : stmt_list_p = &TREE_OPERAND (t, 0);
355 : : }
356 : 10161 : stmt_list = *stmt_list_p;
357 : 10161 : *stmt_list_p = NULL_TREE;
358 : 10161 : tree after_cond = create_artificial_label (cond_locus);
359 : 10161 : tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
360 : 10161 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
361 : 10161 : t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
362 : : goto_after_cond, t);
363 : 10161 : append_to_statement_list (t, &stmt_list);
364 : 10161 : t = build1 (LABEL_EXPR, void_type_node, after_cond);
365 : 10161 : append_to_statement_list (t, &stmt_list);
366 : : }
367 : 3436752 : else if (cond && integer_zerop (cond))
368 : : {
369 : : /* If condition is zero don't generate a loop construct. */
370 : 1098598 : if (cond_is_first)
371 : : {
372 : 272 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
373 : : get_bc_label (bc_break));
374 : 272 : append_to_statement_list (t, &stmt_list);
375 : : }
376 : : }
377 : : else
378 : : {
379 : : /* Expand to gotos. */
380 : 2338154 : tree top = build1 (LABEL_EXPR, void_type_node,
381 : : create_artificial_label (start_locus));
382 : :
383 : : /* If we have an exit condition, then we build an IF with gotos either
384 : : out of the loop, or to the top of it. If there's no exit condition,
385 : : then we just build a jump back to the top. */
386 : 2338154 : exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
387 : :
388 : 2338154 : if (cond && !integer_nonzerop (cond))
389 : : {
390 : : /* Canonicalize the loop condition to the end. This means
391 : : generating a branch to the loop condition. Reuse the
392 : : continue label, if there is no incr expression. */
393 : 2220446 : if (cond_is_first)
394 : : {
395 : 2066869 : if (incr)
396 : : {
397 : 1569527 : entry = build1 (LABEL_EXPR, void_type_node,
398 : : create_artificial_label (start_locus));
399 : 3139054 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
400 : 1569527 : LABEL_EXPR_LABEL (entry));
401 : : }
402 : : else
403 : 497342 : t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
404 : : get_bc_label (bc_continue));
405 : 2066869 : append_to_statement_list (t, &stmt_list);
406 : : }
407 : :
408 : 2220446 : t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
409 : 2220446 : exit = fold_build3_loc (cond_locus,
410 : : COND_EXPR, void_type_node, cond, exit, t);
411 : : }
412 : : else
413 : : {
414 : : /* For the backward-goto's location of an unconditional loop
415 : : use the beginning of the body, or, if there is none, the
416 : : top of the loop. */
417 : 117708 : location_t loc = expr_loc_or_loc (expr_first (body),
418 : : start_locus);
419 : 117708 : SET_EXPR_LOCATION (exit, loc);
420 : : }
421 : 2338154 : append_to_statement_list (top, &stmt_list);
422 : : }
423 : :
424 : 3446913 : append_to_statement_list (body, &stmt_list);
425 : 3446913 : if (c_dialect_cxx ()
426 : 2985143 : && stmt_list
427 : 2983246 : && TREE_CODE (stmt_list) == STATEMENT_LIST)
428 : : {
429 : 2983246 : tree_stmt_iterator tsi = tsi_last (stmt_list);
430 : 2983246 : if (!tsi_end_p (tsi))
431 : : {
432 : 2983246 : tree t = *tsi;
433 : 2983246 : while (TREE_CODE (t) == CLEANUP_POINT_EXPR
434 : : || TREE_CODE (t) == EXPR_STMT
435 : 5480970 : || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
436 : 2497724 : t = TREE_OPERAND (t, 0);
437 : : /* For C++, if iteration statement body ends with fallthrough
438 : : statement, mark it such that we diagnose it even if next
439 : : statement would be labeled statement with case/default label. */
440 : 2983246 : if (TREE_CODE (t) == CALL_EXPR
441 : 126902 : && !CALL_EXPR_FN (t)
442 : 2983258 : && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
443 : 12 : TREE_NOTHROW (t) = 1;
444 : : }
445 : : }
446 : 3446913 : finish_bc_block (&stmt_list, bc_continue, clab);
447 : 3446913 : if (incr)
448 : : {
449 : 1577046 : if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
450 : : {
451 : 1277947 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
452 : 1277947 : SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
453 : 1277947 : append_to_statement_list (d, &stmt_list);
454 : : }
455 : 1577046 : append_to_statement_list (incr, &stmt_list);
456 : : }
457 : 3446913 : append_to_statement_list (entry, &stmt_list);
458 : :
459 : 3446913 : if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
460 : : {
461 : 2922790 : tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
462 : 2922790 : SET_EXPR_LOCATION (d, cond_locus);
463 : 2922790 : append_to_statement_list (d, &stmt_list);
464 : : }
465 : 3446913 : append_to_statement_list (exit, &stmt_list);
466 : 3446913 : if (stmt_list_p)
467 : : {
468 : 10161 : *stmt_list_p = stmt_list;
469 : 10161 : stmt_list = outer_stmt_list;
470 : : }
471 : 3446913 : finish_bc_block (&stmt_list, bc_break, blab);
472 : 3446913 : if (!stmt_list)
473 : 3695 : stmt_list = build_empty_stmt (start_locus);
474 : :
475 : 3446913 : *stmt_p = stmt_list;
476 : 3446913 : }
477 : :
478 : : /* Genericize a FOR_STMT node *STMT_P. */
479 : :
480 : : static void
481 : 1646119 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
482 : : walk_tree_fn func, walk_tree_lh lh)
483 : : {
484 : 1646119 : tree stmt = *stmt_p;
485 : 1646119 : tree expr = NULL;
486 : 1646119 : tree loop;
487 : 1646119 : tree init = FOR_INIT_STMT (stmt);
488 : :
489 : 1646119 : if (init)
490 : : {
491 : 0 : walk_tree_1 (&init, func, data, NULL, lh);
492 : 0 : append_to_statement_list (init, &expr);
493 : : }
494 : :
495 : 3292238 : genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
496 : 1646119 : FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
497 : 1646119 : FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
498 : : walk_subtrees, data, func, lh);
499 : 1646119 : append_to_statement_list (loop, &expr);
500 : 1646119 : if (expr == NULL_TREE)
501 : 0 : expr = loop;
502 : 1646119 : *stmt_p = expr;
503 : 1646119 : }
504 : :
505 : : /* Genericize a WHILE_STMT node *STMT_P. */
506 : :
507 : : static void
508 : 548479 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
509 : : walk_tree_fn func, walk_tree_lh lh)
510 : : {
511 : 548479 : tree stmt = *stmt_p;
512 : 1096958 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
513 : 548479 : WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
514 : 548479 : WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
515 : : walk_subtrees, data, func, lh);
516 : 548479 : }
517 : :
518 : : /* Genericize a DO_STMT node *STMT_P. */
519 : :
520 : : static void
521 : 1252315 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
522 : : walk_tree_fn func, walk_tree_lh lh)
523 : : {
524 : 1252315 : tree stmt = *stmt_p;
525 : 2504630 : genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
526 : 1252315 : DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
527 : : NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
528 : 1252315 : }
529 : :
530 : : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */
531 : :
532 : : static void
533 : 352431 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
534 : : walk_tree_fn func, walk_tree_lh lh)
535 : : {
536 : 352431 : tree stmt = *stmt_p;
537 : 352431 : tree blab, body, cond, type;
538 : 352431 : location_t stmt_locus = EXPR_LOCATION (stmt);
539 : :
540 : 352431 : body = SWITCH_STMT_BODY (stmt);
541 : 352431 : if (!body)
542 : 0 : body = build_empty_stmt (stmt_locus);
543 : 352431 : cond = SWITCH_STMT_COND (stmt);
544 : 352431 : type = SWITCH_STMT_TYPE (stmt);
545 : :
546 : 352431 : walk_tree_1 (&cond, func, data, NULL, lh);
547 : :
548 : 352431 : blab = begin_bc_block (bc_break, stmt_locus);
549 : 352431 : if (SWITCH_STMT_NAME (stmt))
550 : 12 : note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
551 : :
552 : 352431 : walk_tree_1 (&body, func, data, NULL, lh);
553 : :
554 : 352431 : if (SWITCH_STMT_NAME (stmt))
555 : 12 : release_named_bc (SWITCH_STMT_NAME (stmt));
556 : :
557 : 352431 : walk_tree_1 (&type, func, data, NULL, lh);
558 : 352431 : *walk_subtrees = 0;
559 : :
560 : 352431 : if (TREE_USED (blab))
561 : 160454 : SWITCH_BREAK_LABEL_P (blab) = 1;
562 : 352431 : finish_bc_block (&body, bc_break, blab);
563 : 352431 : *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
564 : 352431 : SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
565 : 352431 : gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
566 : : || !TREE_USED (blab));
567 : 352431 : }
568 : :
569 : : /* Genericize a CONTINUE_STMT node *STMT_P. */
570 : :
571 : : static void
572 : 16668 : genericize_continue_stmt (tree *stmt_p)
573 : : {
574 : 16668 : tree stmt_list = NULL;
575 : 16668 : tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
576 : 16668 : tree label;
577 : 16668 : if (CONTINUE_NAME (*stmt_p))
578 : : {
579 : 42 : tree_pair *slot = bc_hash_map->get (CONTINUE_NAME (*stmt_p));
580 : 42 : gcc_checking_assert (slot);
581 : 42 : label = slot->second;
582 : 42 : TREE_USED (label) = 1;
583 : : }
584 : : else
585 : 16626 : label = get_bc_label (bc_continue);
586 : 16668 : location_t location = EXPR_LOCATION (*stmt_p);
587 : 16668 : tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
588 : 16668 : append_to_statement_list_force (pred, &stmt_list);
589 : 16668 : append_to_statement_list (jump, &stmt_list);
590 : 16668 : *stmt_p = stmt_list;
591 : 16668 : }
592 : :
593 : : /* Genericize a BREAK_STMT node *STMT_P. */
594 : :
595 : : static void
596 : 1346169 : genericize_break_stmt (tree *stmt_p)
597 : : {
598 : 1346169 : tree label;
599 : 1346169 : if (BREAK_NAME (*stmt_p))
600 : : {
601 : 53 : tree_pair *slot = bc_hash_map->get (BREAK_NAME (*stmt_p));
602 : 53 : gcc_checking_assert (slot);
603 : 53 : label = slot->first;
604 : 53 : TREE_USED (label) = 1;
605 : : }
606 : : else
607 : 1346116 : label = get_bc_label (bc_break);
608 : 1346169 : location_t location = EXPR_LOCATION (*stmt_p);
609 : 1346169 : *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
610 : 1346169 : }
611 : :
612 : : /* Genericize a OMP_FOR node *STMT_P. */
613 : :
614 : : static void
615 : 42377 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
616 : : walk_tree_fn func, walk_tree_lh lh)
617 : : {
618 : 42377 : tree stmt = *stmt_p;
619 : 42377 : location_t locus = EXPR_LOCATION (stmt);
620 : 42377 : tree clab = begin_bc_block (bc_continue, locus);
621 : :
622 : 42377 : walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
623 : 42377 : if (TREE_CODE (stmt) != OMP_TASKLOOP)
624 : 40968 : walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
625 : 42377 : walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
626 : 42377 : walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
627 : 42377 : walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
628 : 42377 : walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
629 : 42377 : *walk_subtrees = 0;
630 : :
631 : 42377 : finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
632 : 42377 : }
633 : :
634 : : /* Genericize a OMP_METADIRECTIVE node *STMT_P. */
635 : :
636 : : static void
637 : 24 : genericize_omp_metadirective_stmt (tree *stmt_p, int *walk_subtrees,
638 : : void *data, walk_tree_fn func,
639 : : walk_tree_lh lh)
640 : : {
641 : 24 : tree stmt = *stmt_p;
642 : :
643 : 24 : for (tree variant = OMP_METADIRECTIVE_VARIANTS (stmt);
644 : 94 : variant != NULL_TREE;
645 : 70 : variant = TREE_CHAIN (variant))
646 : : {
647 : 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_DIRECTIVE (variant),
648 : : func, data, NULL, lh);
649 : 70 : walk_tree_1 (&OMP_METADIRECTIVE_VARIANT_BODY (variant),
650 : : func, data, NULL, lh);
651 : : }
652 : :
653 : 24 : *walk_subtrees = 0;
654 : 24 : }
655 : :
656 : : /* Lower structured control flow tree nodes, such as loops. The
657 : : STMT_P, WALK_SUBTREES, and DATA arguments are as for the walk_tree_fn
658 : : type. FUNC and LH are language-specific functions passed to walk_tree_1
659 : : for node visiting and traversal, respectively; they are used to do
660 : : subtree processing in a language-dependent way. */
661 : :
662 : : tree
663 : 700126409 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
664 : : walk_tree_fn func, walk_tree_lh lh)
665 : : {
666 : 700126409 : tree stmt = *stmt_p;
667 : :
668 : 700126409 : switch (TREE_CODE (stmt))
669 : : {
670 : 1646119 : case FOR_STMT:
671 : 1646119 : genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
672 : 1646119 : break;
673 : :
674 : 548479 : case WHILE_STMT:
675 : 548479 : genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
676 : 548479 : break;
677 : :
678 : 1252315 : case DO_STMT:
679 : 1252315 : genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
680 : 1252315 : break;
681 : :
682 : 352431 : case SWITCH_STMT:
683 : 352431 : genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
684 : 352431 : break;
685 : :
686 : 16668 : case CONTINUE_STMT:
687 : 16668 : genericize_continue_stmt (stmt_p);
688 : 16668 : break;
689 : :
690 : 1346169 : case BREAK_STMT:
691 : 1346169 : genericize_break_stmt (stmt_p);
692 : 1346169 : break;
693 : :
694 : 42377 : case OMP_FOR:
695 : 42377 : case OMP_SIMD:
696 : 42377 : case OMP_DISTRIBUTE:
697 : 42377 : case OMP_LOOP:
698 : 42377 : case OMP_TASKLOOP:
699 : 42377 : case OMP_TILE:
700 : 42377 : case OMP_UNROLL:
701 : 42377 : case OACC_LOOP:
702 : 42377 : genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
703 : 42377 : break;
704 : :
705 : 24 : case OMP_METADIRECTIVE:
706 : 24 : genericize_omp_metadirective_stmt (stmt_p, walk_subtrees, data, func,
707 : : lh);
708 : 24 : break;
709 : :
710 : 54017668 : case STATEMENT_LIST:
711 : 54017668 : if (TREE_SIDE_EFFECTS (stmt))
712 : : {
713 : 51629652 : tree_stmt_iterator i;
714 : 51629652 : int nondebug_stmts = 0;
715 : 51629652 : bool clear_side_effects = true;
716 : : /* Genericization can clear TREE_SIDE_EFFECTS, e.g. when
717 : : transforming an IF_STMT into COND_EXPR. If such stmt
718 : : appears in a STATEMENT_LIST that contains only that
719 : : stmt and some DEBUG_BEGIN_STMTs, without -g where the
720 : : STATEMENT_LIST wouldn't be present at all the resulting
721 : : expression wouldn't have TREE_SIDE_EFFECTS set, so make sure
722 : : to clear it even on the STATEMENT_LIST in such cases. */
723 : 48039793 : hash_set<tree> *pset = (c_dialect_cxx ()
724 : 51629652 : ? nullptr
725 : : : static_cast<hash_set<tree> *>(data));
726 : 222820006 : for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
727 : : {
728 : 171190354 : tree t = tsi_stmt (i);
729 : 171190354 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
730 : 80453339 : nondebug_stmts++;
731 : 171190354 : walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
732 : 171190354 : if (TREE_CODE (t) != DEBUG_BEGIN_STMT
733 : 171190354 : && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
734 : : clear_side_effects = false;
735 : : }
736 : 51629652 : if (clear_side_effects)
737 : 375 : TREE_SIDE_EFFECTS (stmt) = 0;
738 : 51629652 : *walk_subtrees = 0;
739 : : }
740 : : break;
741 : :
742 : : default:
743 : : break;
744 : : }
745 : :
746 : 700126409 : return NULL;
747 : : }
748 : :
749 : :
750 : : /* Wrapper for c_genericize_control_stmt to allow it to be used as a walk_tree
751 : : callback. This is appropriate for C; C++ calls c_genericize_control_stmt
752 : : directly. */
753 : :
754 : : static tree
755 : 645221985 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
756 : : {
757 : 645221985 : tree stmt = *stmt_p;
758 : : /* Mark stores to parts of complex automatic non-addressable
759 : : variables as DECL_NOT_GIMPLE_REG_P for -O0. This can't be
760 : : done during gimplification. See PR119120. */
761 : 645221985 : if (TREE_CODE (stmt) == MODIFY_EXPR
762 : 36643656 : && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
763 : 36642584 : || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
764 : 2156 : && !optimize
765 : 138 : && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
766 : 645222109 : && is_gimple_reg (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)))
767 : 63 : DECL_NOT_GIMPLE_REG_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0)) = 1;
768 : :
769 : 645221985 : c_genericize_control_stmt (stmt_p, walk_subtrees, data,
770 : : c_genericize_control_r, NULL);
771 : 645221985 : return NULL;
772 : : }
773 : :
774 : : /* Convert the tree representation of FNDECL from C frontend trees to
775 : : GENERIC. */
776 : :
777 : : void
778 : 78139914 : c_genericize (tree fndecl)
779 : : {
780 : 78139914 : dump_file_info *dfi;
781 : 78139914 : FILE *dump_orig;
782 : 78139914 : dump_flags_t local_dump_flags;
783 : 78139914 : struct cgraph_node *cgn;
784 : :
785 : 78139914 : if (flag_sanitize & SANITIZE_BOUNDS)
786 : : {
787 : 66825 : hash_set<tree> pset;
788 : 66825 : walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
789 : : &pset);
790 : 66825 : }
791 : :
792 : : /* Genericize loops and other structured control constructs. The C++
793 : : front end has already done this in lang-specific code. */
794 : 78139914 : if (!c_dialect_cxx ())
795 : : {
796 : 35380148 : bc_state_t save_state;
797 : 35380148 : push_cfun (DECL_STRUCT_FUNCTION (fndecl));
798 : 35380148 : save_bc_state (&save_state);
799 : 35380148 : hash_set<tree> pset;
800 : 35380148 : walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
801 : : &pset);
802 : 35380163 : delete bc_hash_map;
803 : 35380148 : bc_hash_map = NULL;
804 : 35380148 : restore_bc_state (&save_state);
805 : 35380148 : pop_cfun ();
806 : 35380148 : }
807 : :
808 : 78139914 : if (warn_duplicated_branches)
809 : 133 : walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
810 : : do_warn_duplicated_branches_r, NULL);
811 : :
812 : : /* Dump the C-specific tree IR. */
813 : 78139914 : dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
814 : 78139914 : dump_orig = dfi->pstream;
815 : 78139914 : local_dump_flags = dfi->pflags;
816 : 78139914 : if (dump_orig)
817 : : {
818 : 5907 : fprintf (dump_orig, "\n;; Function %s",
819 : 5907 : lang_hooks.decl_printable_name (fndecl, 2));
820 : 5907 : fprintf (dump_orig, " (%s)\n",
821 : 5907 : (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
822 : 59 : : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
823 : 5907 : fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
824 : 5907 : fprintf (dump_orig, "\n");
825 : :
826 : 5907 : if (local_dump_flags & TDF_RAW)
827 : 1 : dump_node (DECL_SAVED_TREE (fndecl),
828 : : TDF_SLIM | local_dump_flags, dump_orig);
829 : : else
830 : 5906 : print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl), local_dump_flags);
831 : 5907 : fprintf (dump_orig, "\n");
832 : : }
833 : :
834 : : /* Dump all nested functions now. */
835 : 78139914 : cgn = cgraph_node::get_create (fndecl);
836 : 78141485 : for (cgn = first_nested_function (cgn);
837 : 78141485 : cgn; cgn = next_nested_function (cgn))
838 : 1571 : c_genericize (cgn->decl);
839 : 78139914 : }
840 : :
841 : : static void
842 : 0 : add_block_to_enclosing (tree block)
843 : : {
844 : 0 : unsigned i;
845 : 0 : tree enclosing;
846 : 0 : gbind *bind;
847 : 0 : vec<gbind *> stack = gimple_bind_expr_stack ();
848 : :
849 : 0 : FOR_EACH_VEC_ELT (stack, i, bind)
850 : 0 : if (gimple_bind_block (bind))
851 : : break;
852 : :
853 : 0 : enclosing = gimple_bind_block (bind);
854 : 0 : BLOCK_SUBBLOCKS (enclosing) = chainon (BLOCK_SUBBLOCKS (enclosing), block);
855 : 0 : }
856 : :
857 : : /* Genericize a scope by creating a new BIND_EXPR.
858 : : BLOCK is either a BLOCK representing the scope or a chain of _DECLs.
859 : : In the latter case, we need to create a new BLOCK and add it to the
860 : : BLOCK_SUBBLOCKS of the enclosing block.
861 : : BODY is a chain of C _STMT nodes for the contents of the scope, to be
862 : : genericized. */
863 : :
864 : : tree
865 : 136927815 : c_build_bind_expr (location_t loc, tree block, tree body)
866 : : {
867 : 136927815 : tree decls, bind;
868 : :
869 : 136927815 : if (block == NULL_TREE)
870 : : decls = NULL_TREE;
871 : 58803305 : else if (TREE_CODE (block) == BLOCK)
872 : 58803305 : decls = BLOCK_VARS (block);
873 : : else
874 : : {
875 : 0 : decls = block;
876 : 0 : if (DECL_ARTIFICIAL (decls))
877 : : block = NULL_TREE;
878 : : else
879 : : {
880 : 0 : block = make_node (BLOCK);
881 : 0 : BLOCK_VARS (block) = decls;
882 : 0 : add_block_to_enclosing (block);
883 : : }
884 : : }
885 : :
886 : 136927815 : if (!body)
887 : 0 : body = build_empty_stmt (loc);
888 : 136927815 : if (decls || block)
889 : : {
890 : 58803305 : bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
891 : 58803305 : TREE_SIDE_EFFECTS (bind) = 1;
892 : 58803305 : SET_EXPR_LOCATION (bind, loc);
893 : : }
894 : : else
895 : : bind = body;
896 : :
897 : 136927815 : return bind;
898 : : }
899 : :
900 : : /* Helper for c_gimplify_expr: test if target supports fma-like FN. */
901 : :
902 : : static bool
903 : 24 : fma_supported_p (enum internal_fn fn, tree type)
904 : : {
905 : 22 : return direct_internal_fn_supported_p (fn, type, OPTIMIZE_FOR_BOTH);
906 : : }
907 : :
908 : : /* Gimplification of expression trees. */
909 : :
910 : : /* Do C-specific gimplification on *EXPR_P. PRE_P and POST_P are as in
911 : : gimplify_expr. */
912 : :
913 : : int
914 : 269087655 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
915 : : gimple_seq *post_p ATTRIBUTE_UNUSED)
916 : : {
917 : 269087655 : enum tree_code code = TREE_CODE (*expr_p);
918 : :
919 : 269087655 : switch (code)
920 : : {
921 : 337358 : case LSHIFT_EXPR:
922 : 337358 : case RSHIFT_EXPR:
923 : 337358 : case LROTATE_EXPR:
924 : 337358 : case RROTATE_EXPR:
925 : 337358 : {
926 : : /* We used to convert the right operand of a shift-expression
927 : : to an integer_type_node in the FEs. But it is unnecessary
928 : : and not desirable for diagnostics and sanitizers. We keep
929 : : this here to not pessimize the code, but we convert to an
930 : : unsigned type, because negative shift counts are undefined
931 : : anyway.
932 : : We should get rid of this conversion when we have a proper
933 : : type demotion/promotion pass. */
934 : 337358 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
935 : 337358 : if (!error_operand_p (*op1_p)
936 : 337357 : && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
937 : 335641 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
938 : : unsigned_type_node)
939 : 633645 : && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
940 : : integer_type_node))
941 : : /* Make sure to unshare the result, tree sharing is invalid
942 : : during gimplification. */
943 : 13583 : *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
944 : : break;
945 : : }
946 : :
947 : 1141887 : case PREINCREMENT_EXPR:
948 : 1141887 : case PREDECREMENT_EXPR:
949 : 1141887 : case POSTINCREMENT_EXPR:
950 : 1141887 : case POSTDECREMENT_EXPR:
951 : 1141887 : {
952 : 1141887 : tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
953 : 1141887 : if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
954 : : {
955 : 5983 : if (!TYPE_OVERFLOW_WRAPS (type))
956 : 3391 : type = unsigned_type_for (type);
957 : 5983 : return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
958 : : }
959 : : break;
960 : : }
961 : :
962 : 7664329 : case PLUS_EXPR:
963 : 7664329 : case MINUS_EXPR:
964 : 7664329 : {
965 : 7664329 : tree type = TREE_TYPE (*expr_p);
966 : : /* For -ffp-contract=on we need to attempt FMA contraction only
967 : : during initial gimplification. Late contraction across statement
968 : : boundaries would violate language semantics. */
969 : 7664329 : if (SCALAR_FLOAT_TYPE_P (type)
970 : 956739 : && flag_fp_contract_mode == FP_CONTRACT_ON
971 : 22 : && cfun && !(cfun->curr_properties & PROP_gimple_any)
972 : 7664351 : && fma_supported_p (IFN_FMA, type))
973 : : {
974 : 22 : bool neg_mul = false, neg_add = code == MINUS_EXPR;
975 : :
976 : 22 : tree *op0_p = &TREE_OPERAND (*expr_p, 0);
977 : 22 : tree *op1_p = &TREE_OPERAND (*expr_p, 1);
978 : :
979 : : /* Look for ±(x * y) ± z, swapping operands if necessary. */
980 : 22 : if (TREE_CODE (*op0_p) == NEGATE_EXPR
981 : 22 : && TREE_CODE (TREE_OPERAND (*op0_p, 0)) == MULT_EXPR)
982 : : /* '*EXPR_P' is '-(x * y) ± z'. This is fine. */;
983 : 22 : else if (TREE_CODE (*op0_p) != MULT_EXPR)
984 : : {
985 : : std::swap (op0_p, op1_p);
986 : : std::swap (neg_mul, neg_add);
987 : : }
988 : 22 : if (TREE_CODE (*op0_p) == NEGATE_EXPR)
989 : : {
990 : 0 : op0_p = &TREE_OPERAND (*op0_p, 0);
991 : 0 : neg_mul = !neg_mul;
992 : : }
993 : 22 : if (TREE_CODE (*op0_p) != MULT_EXPR)
994 : : break;
995 : 12 : auto_vec<tree, 3> ops (3);
996 : 12 : ops.quick_push (TREE_OPERAND (*op0_p, 0));
997 : 12 : ops.quick_push (TREE_OPERAND (*op0_p, 1));
998 : 12 : ops.quick_push (*op1_p);
999 : :
1000 : 12 : enum internal_fn ifn = IFN_FMA;
1001 : 12 : if (neg_mul)
1002 : : {
1003 : 0 : if (fma_supported_p (IFN_FNMA, type))
1004 : : ifn = IFN_FNMA;
1005 : : else
1006 : 0 : ops[0] = build1 (NEGATE_EXPR, type, ops[0]);
1007 : : }
1008 : 12 : if (neg_add)
1009 : : {
1010 : 2 : enum internal_fn ifn2 = ifn == IFN_FMA ? IFN_FMS : IFN_FNMS;
1011 : 2 : if (fma_supported_p (ifn2, type))
1012 : : ifn = ifn2;
1013 : : else
1014 : 0 : ops[2] = build1 (NEGATE_EXPR, type, ops[2]);
1015 : : }
1016 : : /* Avoid gimplify_arg: it emits all side effects into *PRE_P. */
1017 : 72 : for (auto &&op : ops)
1018 : 36 : if (gimplify_expr (&op, pre_p, post_p, is_gimple_val, fb_rvalue)
1019 : : == GS_ERROR)
1020 : : return GS_ERROR;
1021 : :
1022 : 12 : gcall *call = gimple_build_call_internal_vec (ifn, ops);
1023 : 12 : gimple_seq_add_stmt_without_update (pre_p, call);
1024 : 12 : *expr_p = create_tmp_var (type);
1025 : 12 : gimple_call_set_lhs (call, *expr_p);
1026 : 12 : return GS_ALL_DONE;
1027 : 12 : }
1028 : : break;
1029 : : }
1030 : :
1031 : 3741623 : case CALL_EXPR:
1032 : 3741623 : {
1033 : 3741623 : tree fndecl = get_callee_fndecl (*expr_p);
1034 : 3741623 : if (fndecl
1035 : 3491711 : && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
1036 : 52 : && call_expr_nargs (*expr_p) == 2
1037 : 3741675 : && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
1038 : : {
1039 : 52 : tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
1040 : 52 : tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
1041 : : fndecl, 1, a);
1042 : 104 : *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
1043 : : integer_type_node,
1044 : 52 : build2_loc (EXPR_LOCATION (*expr_p),
1045 : : NE_EXPR, boolean_type_node, a,
1046 : 52 : build_zero_cst (TREE_TYPE (a))),
1047 : 52 : c, CALL_EXPR_ARG (*expr_p, 1));
1048 : 52 : return GS_OK;
1049 : : }
1050 : : break;
1051 : : }
1052 : :
1053 : : default:;
1054 : : }
1055 : :
1056 : : return GS_UNHANDLED;
1057 : : }
|