LCOV - code coverage report
Current view: top level - gcc/c-family - c-gimplify.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.4 % 499 471
Test Date: 2026-02-28 14:20:25 Functions: 96.2 % 26 25
Legend: Lines:     hit not hit

            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-2026 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      1157874 : is_address_with_access_with_size (tree tp)
      75              : {
      76      1157874 :   if (TREE_CODE (tp) == POINTER_PLUS_EXPR
      77      1157874 :       && 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      1283763 : ubsan_walk_array_refs_r (tree *tp, int *walk_subtrees, void *data)
      86              : {
      87      1283763 :   hash_set<tree> *pset = (hash_set<tree> *) data;
      88              : 
      89      1283763 :   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        65326 :       *walk_subtrees = 0;
      95        81281 :       for (tree decl = BIND_EXPR_VARS (*tp); decl; decl = DECL_CHAIN (decl))
      96              :         {
      97        15955 :           if (TREE_STATIC (decl))
      98          155 :             continue;
      99        15800 :           walk_tree (&DECL_INITIAL (decl), ubsan_walk_array_refs_r, pset,
     100              :                      pset);
     101        15800 :           walk_tree (&DECL_SIZE (decl), ubsan_walk_array_refs_r, pset, pset);
     102        15800 :           walk_tree (&DECL_SIZE_UNIT (decl), ubsan_walk_array_refs_r, pset,
     103              :                      pset);
     104              :         }
     105        65326 :       walk_tree (&BIND_EXPR_BODY (*tp), ubsan_walk_array_refs_r, pset, pset);
     106              :     }
     107      1218437 :   else if (TREE_CODE (*tp) == ADDR_EXPR
     108      1218437 :            && 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      1218178 :   else if (TREE_CODE (*tp) == ARRAY_REF)
     124         4068 :     ubsan_maybe_instrument_array_ref (tp, false);
     125      1214110 :   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        66882 :       *walk_subtrees = 0;
     134        66882 :       walk_tree (&TREE_OPERAND (*tp, 1), ubsan_walk_array_refs_r, pset, pset);
     135        66882 :       walk_tree (&TREE_OPERAND (*tp, 0), ubsan_walk_array_refs_r, pset, pset);
     136              :     }
     137      1147228 :   else if (TREE_CODE (*tp) == INDIRECT_REF
     138      1147228 :            && is_address_with_access_with_size (TREE_OPERAND (*tp, 0)))
     139              :     {
     140           77 :       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           77 :       tree aref = TREE_OPERAND (*tp, 0);
     145           77 :       pset->add (aref);
     146           77 :       *walk_subtrees = 0;
     147           77 :       walk_tree (&TREE_OPERAND (aref, 0), ubsan_walk_array_refs_r, pset, pset);
     148              :     }
     149      1147151 :   else if (is_address_with_access_with_size (*tp))
     150            0 :     ubsan_maybe_instrument_array_ref (tp, true);
     151      1283763 :   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      9989574 : begin_bc_block (enum bc_t bc, location_t location)
     176              : {
     177      9989574 :   tree label = create_artificial_label (location);
     178      9989574 :   DECL_CHAIN (label) = bc_label[bc];
     179      9989574 :   bc_label[bc] = label;
     180      9989574 :   if (bc == bc_break)
     181      5297873 :     LABEL_DECL_BREAK (label) = true;
     182              :   else
     183      4691701 :     LABEL_DECL_CONTINUE (label) = true;
     184      9989574 :   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      9989574 : finish_bc_block (tree *block, enum bc_t bc, tree label)
     196              : {
     197      9989574 :   gcc_assert (label == bc_label[bc]);
     198              : 
     199      9989574 :   if (TREE_USED (label))
     200      4339178 :     append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label),
     201              :                               block);
     202              : 
     203      9989574 :   bc_label[bc] = DECL_CHAIN (label);
     204      9989574 :   DECL_CHAIN (label) = NULL_TREE;
     205      9989574 : }
     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     91273449 : save_bc_state (bc_state_t *state)
     231              : {
     232     91273449 :   state->bc_label[bc_break] = bc_label[bc_break];
     233     91273449 :   state->bc_label[bc_continue] = bc_label[bc_continue];
     234     91273449 :   state->bc_hash_map = bc_hash_map;
     235     91273449 :   bc_label[bc_break] = NULL_TREE;
     236     91273449 :   bc_label[bc_continue] = NULL_TREE;
     237     91273449 :   bc_hash_map = NULL;
     238     91273449 : }
     239              : 
     240              : void
     241     91273449 : restore_bc_state (bc_state_t *state)
     242              : {
     243     91273449 :   gcc_assert (bc_label[bc_break] == NULL);
     244     91273449 :   gcc_assert (bc_label[bc_continue] == NULL);
     245     91273449 :   gcc_assert (bc_hash_map == NULL);
     246     91273449 :   bc_label[bc_break] = state->bc_label[bc_break];
     247     91273449 :   bc_label[bc_continue] = state->bc_label[bc_continue];
     248     91273449 :   bc_hash_map = state->bc_hash_map;
     249     91273449 : }
     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      6169750 : get_bc_label (enum bc_t bc)
     256              : {
     257      6169750 :   tree label = bc_label[bc];
     258      6169750 :   gcc_assert (label);
     259              : 
     260              :   /* Mark the label used for finish_bc_block.  */
     261      6169750 :   TREE_USED (label) = 1;
     262      6169750 :   return label;
     263              : }
     264              : 
     265              : /* Return the location from EXPR, or OR_LOC if the former is unknown.  */
     266              : 
     267              : location_t
     268     11090033 : expr_loc_or_loc (const_tree expr, location_t or_loc)
     269              : {
     270     11090033 :   tree t = const_cast<tree> (expr);
     271     11090033 :   location_t loc = UNKNOWN_LOCATION;
     272     11090033 :   if (t)
     273      8349360 :     loc = EXPR_LOCATION (t);
     274      6881973 :   if (loc == UNKNOWN_LOCATION)
     275      5939385 :     loc = or_loc;
     276     11090033 :   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      4649381 : 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      4649381 :   tree blab, clab;
     300      4649381 :   tree entry = NULL, exit = NULL, t;
     301      4649381 :   tree stmt_list = NULL, outer_stmt_list = NULL_TREE, *stmt_list_p = NULL;
     302      4649381 :   location_t cond_locus = expr_loc_or_loc (cond, start_locus);
     303      4649381 :   location_t incr_locus = expr_loc_or_loc (incr, start_locus);
     304              : 
     305      4649381 :   protected_set_expr_location_if_unset (incr, start_locus);
     306              : 
     307      4649381 :   walk_tree_1 (&cond_prep, func, data, NULL, lh);
     308      4649381 :   walk_tree_1 (&cond, func, data, NULL, lh);
     309      4649381 :   walk_tree_1 (&incr, func, data, NULL, lh);
     310              : 
     311      4649381 :   blab = begin_bc_block (bc_break, start_locus);
     312      4649381 :   clab = begin_bc_block (bc_continue, start_locus);
     313      4649381 :   if (name)
     314           39 :     note_named_bc (name, blab, clab);
     315              : 
     316      4649381 :   walk_tree_1 (&body, func, data, NULL, lh);
     317      4649381 :   *walk_subtrees = 0;
     318              : 
     319      4649381 :   if (name)
     320           39 :     release_named_bc (name);
     321              : 
     322      4649381 :   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         9356 :       gcc_assert (cond_is_first && TREE_CODE (cond_prep) == BIND_EXPR);
     343         9356 :       tree top = build1 (LABEL_EXPR, void_type_node,
     344              :                          create_artificial_label (start_locus));
     345         9356 :       exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
     346         9356 :       append_to_statement_list (top, &outer_stmt_list);
     347         9356 :       append_to_statement_list (cond_prep, &outer_stmt_list);
     348         9356 :       stmt_list_p = &BIND_EXPR_BODY (cond_prep);
     349         9356 :       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         9356 :       stmt_list = *stmt_list_p;
     357         9356 :       *stmt_list_p = NULL_TREE;
     358         9356 :       tree after_cond = create_artificial_label (cond_locus);
     359         9356 :       tree goto_after_cond = build1 (GOTO_EXPR, void_type_node, after_cond);
     360         9356 :       t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
     361         9356 :       t = fold_build3_loc (cond_locus, COND_EXPR, void_type_node, cond,
     362              :                            goto_after_cond, t);
     363         9356 :       append_to_statement_list (t, &stmt_list);
     364         9356 :       t = build1 (LABEL_EXPR, void_type_node, after_cond);
     365         9356 :       append_to_statement_list (t, &stmt_list);
     366              :     }
     367      4640025 :   else if (cond && integer_zerop (cond))
     368              :     {
     369              :       /* If condition is zero don't generate a loop construct.  */
     370      1412875 :       if (cond_is_first)
     371              :         {
     372          403 :           t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
     373              :                           get_bc_label (bc_break));
     374          403 :           append_to_statement_list (t, &stmt_list);
     375              :         }
     376              :     }
     377              :   else
     378              :     {
     379              :       /* Expand to gotos.  */
     380      3227150 :       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      3227150 :       exit = build1 (GOTO_EXPR, void_type_node, LABEL_EXPR_LABEL (top));
     387              : 
     388      3227150 :       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      3094985 :           if (cond_is_first)
     394              :             {
     395      2798772 :               if (incr)
     396              :                 {
     397      1966890 :                   entry = build1 (LABEL_EXPR, void_type_node,
     398              :                                   create_artificial_label (start_locus));
     399      3933780 :                   t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
     400      1966890 :                                   LABEL_EXPR_LABEL (entry));
     401              :                 }
     402              :               else
     403       831882 :                 t = build1_loc (start_locus, GOTO_EXPR, void_type_node,
     404              :                                 get_bc_label (bc_continue));
     405      2798772 :               append_to_statement_list (t, &stmt_list);
     406              :             }
     407              : 
     408      3094985 :           t = build1 (GOTO_EXPR, void_type_node, get_bc_label (bc_break));
     409      3094985 :           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       132165 :           location_t loc = expr_loc_or_loc (expr_first (body),
     418              :                                             start_locus);
     419       132165 :           SET_EXPR_LOCATION (exit, loc);
     420              :         }
     421      3227150 :       append_to_statement_list (top, &stmt_list);
     422              :     }
     423              : 
     424      4649381 :   append_to_statement_list (body, &stmt_list);
     425      4649381 :   if (c_dialect_cxx ()
     426      4175301 :       && stmt_list
     427      4173404 :       && TREE_CODE (stmt_list) == STATEMENT_LIST)
     428              :     {
     429      4173404 :       tree_stmt_iterator tsi = tsi_last (stmt_list);
     430      4173404 :       if (!tsi_end_p (tsi))
     431              :         {
     432      4173404 :           tree t = *tsi;
     433      4173404 :           while (TREE_CODE (t) == CLEANUP_POINT_EXPR
     434              :                  || TREE_CODE (t) == EXPR_STMT
     435      8267949 :                  || CONVERT_EXPR_CODE_P (TREE_CODE (t)))
     436      4094545 :             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      4173404 :           if (TREE_CODE (t) == CALL_EXPR
     441       305439 :               && !CALL_EXPR_FN (t)
     442      4173416 :               && CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
     443           12 :             TREE_NOTHROW (t) = 1;
     444              :         }
     445              :     }
     446      4649381 :   finish_bc_block (&stmt_list, bc_continue, clab);
     447      4649381 :   if (incr)
     448              :     {
     449      1987759 :       if (MAY_HAVE_DEBUG_MARKER_STMTS && incr_locus != UNKNOWN_LOCATION)
     450              :         {
     451      1659106 :           tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
     452      1659106 :           SET_EXPR_LOCATION (d, expr_loc_or_loc (incr, start_locus));
     453      1659106 :           append_to_statement_list (d, &stmt_list);
     454              :         }
     455      1987759 :       append_to_statement_list (incr, &stmt_list);
     456              :     }
     457      4649381 :   append_to_statement_list (entry, &stmt_list);
     458              : 
     459      4649381 :   if (MAY_HAVE_DEBUG_MARKER_STMTS && cond_locus != UNKNOWN_LOCATION)
     460              :     {
     461      4067777 :       tree d = build0 (DEBUG_BEGIN_STMT, void_type_node);
     462      4067777 :       SET_EXPR_LOCATION (d, cond_locus);
     463      4067777 :       append_to_statement_list (d, &stmt_list);
     464              :     }
     465      4649381 :   append_to_statement_list (exit, &stmt_list);
     466      4649381 :   if (stmt_list_p)
     467              :     {
     468         9356 :       *stmt_list_p = stmt_list;
     469         9356 :       stmt_list = outer_stmt_list;
     470              :     }
     471      4649381 :   finish_bc_block (&stmt_list, bc_break, blab);
     472      4649381 :   if (!stmt_list)
     473         3709 :     stmt_list = build_empty_stmt (start_locus);
     474              : 
     475      4649381 :   *stmt_p = stmt_list;
     476      4649381 : }
     477              : 
     478              : /* Genericize a FOR_STMT node *STMT_P.  */
     479              : 
     480              : static void
     481      2060436 : genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     482              :                      walk_tree_fn func, walk_tree_lh lh)
     483              : {
     484      2060436 :   tree stmt = *stmt_p;
     485      2060436 :   tree expr = NULL;
     486      2060436 :   tree loop;
     487      2060436 :   tree init = FOR_INIT_STMT (stmt);
     488              : 
     489      2060436 :   if (init)
     490              :     {
     491            0 :       walk_tree_1 (&init, func, data, NULL, lh);
     492            0 :       append_to_statement_list (init, &expr);
     493              :     }
     494              : 
     495      4120872 :   genericize_c_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt),
     496      2060436 :                      FOR_BODY (stmt), FOR_EXPR (stmt), FOR_NAME (stmt),
     497      2060436 :                      FOR_COND_PREP (stmt), FOR_COND_CLEANUP (stmt), 1,
     498              :                      walk_subtrees, data, func, lh);
     499      2060436 :   append_to_statement_list (loop, &expr);
     500      2060436 :   if (expr == NULL_TREE)
     501            0 :     expr = loop;
     502      2060436 :   *stmt_p = expr;
     503      2060436 : }
     504              : 
     505              : /* Genericize a WHILE_STMT node *STMT_P.  */
     506              : 
     507              : static void
     508       879844 : genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     509              :                        walk_tree_fn func, walk_tree_lh lh)
     510              : {
     511       879844 :   tree stmt = *stmt_p;
     512      1759688 :   genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt),
     513       879844 :                      WHILE_BODY (stmt), NULL_TREE, WHILE_NAME (stmt),
     514       879844 :                      WHILE_COND_PREP (stmt), WHILE_COND_CLEANUP (stmt), 1,
     515              :                      walk_subtrees, data, func, lh);
     516       879844 : }
     517              : 
     518              : /* Genericize a DO_STMT node *STMT_P.  */
     519              : 
     520              : static void
     521      1709101 : genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     522              :                     walk_tree_fn func, walk_tree_lh lh)
     523              : {
     524      1709101 :   tree stmt = *stmt_p;
     525      3418202 :   genericize_c_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt),
     526      1709101 :                      DO_BODY (stmt), NULL_TREE, DO_NAME (stmt),
     527              :                      NULL_TREE, NULL_TREE, 0, walk_subtrees, data, func, lh);
     528      1709101 : }
     529              : 
     530              : /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR.  */
     531              : 
     532              : static void
     533       648492 : genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     534              :                         walk_tree_fn func, walk_tree_lh lh)
     535              : {
     536       648492 :   tree stmt = *stmt_p;
     537       648492 :   tree blab, body, cond, type;
     538       648492 :   location_t stmt_locus = EXPR_LOCATION (stmt);
     539              : 
     540       648492 :   body = SWITCH_STMT_BODY (stmt);
     541       648492 :   if (!body)
     542            0 :     body = build_empty_stmt (stmt_locus);
     543       648492 :   cond = SWITCH_STMT_COND (stmt);
     544       648492 :   type = SWITCH_STMT_TYPE (stmt);
     545              : 
     546       648492 :   walk_tree_1 (&cond, func, data, NULL, lh);
     547              : 
     548       648492 :   blab = begin_bc_block (bc_break, stmt_locus);
     549       648492 :   if (SWITCH_STMT_NAME (stmt))
     550           12 :     note_named_bc (SWITCH_STMT_NAME (stmt), blab, NULL_TREE);
     551              : 
     552       648492 :   walk_tree_1 (&body, func, data, NULL, lh);
     553              : 
     554       648492 :   if (SWITCH_STMT_NAME (stmt))
     555           12 :     release_named_bc (SWITCH_STMT_NAME (stmt));
     556              : 
     557       648492 :   walk_tree_1 (&type, func, data, NULL, lh);
     558       648492 :   *walk_subtrees = 0;
     559              : 
     560       648492 :   if (TREE_USED (blab))
     561       336895 :     SWITCH_BREAK_LABEL_P (blab) = 1;
     562       648492 :   finish_bc_block (&body, bc_break, blab);
     563       648492 :   *stmt_p = build2_loc (stmt_locus, SWITCH_EXPR, type, cond, body);
     564       648492 :   SWITCH_ALL_CASES_P (*stmt_p) = SWITCH_STMT_ALL_CASES_P (stmt);
     565       648492 :   gcc_checking_assert (!SWITCH_STMT_NO_BREAK_P (stmt)
     566              :                        || !TREE_USED (blab));
     567       648492 : }
     568              : 
     569              : /* Genericize a CONTINUE_STMT node *STMT_P.  */
     570              : 
     571              : static void
     572        17401 : genericize_continue_stmt (tree *stmt_p)
     573              : {
     574        17401 :   tree stmt_list = NULL;
     575        17401 :   tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN);
     576        17401 :   tree label;
     577        17401 :   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        17359 :     label = get_bc_label (bc_continue);
     586        17401 :   location_t location = EXPR_LOCATION (*stmt_p);
     587        17401 :   tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label);
     588        17401 :   append_to_statement_list_force (pred, &stmt_list);
     589        17401 :   append_to_statement_list (jump, &stmt_list);
     590        17401 :   *stmt_p = stmt_list;
     591        17401 : }
     592              : 
     593              : /* Genericize a BREAK_STMT node *STMT_P.  */
     594              : 
     595              : static void
     596      2215818 : genericize_break_stmt (tree *stmt_p)
     597              : {
     598      2215818 :   tree label;
     599      2215818 :   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      2215765 :     label = get_bc_label (bc_break);
     608      2215818 :   location_t location = EXPR_LOCATION (*stmt_p);
     609      2215818 :   *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label);
     610      2215818 : }
     611              : 
     612              : /* Genericize a OMP_FOR node *STMT_P.  */
     613              : 
     614              : static void
     615        42320 : genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     616              :                          walk_tree_fn func, walk_tree_lh lh)
     617              : {
     618        42320 :   tree stmt = *stmt_p;
     619        42320 :   location_t locus = EXPR_LOCATION (stmt);
     620        42320 :   tree clab = begin_bc_block (bc_continue, locus);
     621              : 
     622        42320 :   walk_tree_1 (&OMP_FOR_BODY (stmt), func, data, NULL, lh);
     623        42320 :   if (TREE_CODE (stmt) != OMP_TASKLOOP)
     624        40907 :     walk_tree_1 (&OMP_FOR_CLAUSES (stmt), func, data, NULL, lh);
     625        42320 :   walk_tree_1 (&OMP_FOR_INIT (stmt), func, data, NULL, lh);
     626        42320 :   walk_tree_1 (&OMP_FOR_COND (stmt), func, data, NULL, lh);
     627        42320 :   walk_tree_1 (&OMP_FOR_INCR (stmt), func, data, NULL, lh);
     628        42320 :   walk_tree_1 (&OMP_FOR_PRE_BODY (stmt), func, data, NULL, lh);
     629        42320 :   *walk_subtrees = 0;
     630              : 
     631        42320 :   finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab);
     632        42320 : }
     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    747112325 : c_genericize_control_stmt (tree *stmt_p, int *walk_subtrees, void *data,
     664              :                            walk_tree_fn func, walk_tree_lh lh)
     665              : {
     666    747112325 :   tree stmt = *stmt_p;
     667              : 
     668    747112325 :   switch (TREE_CODE (stmt))
     669              :     {
     670      2060436 :     case FOR_STMT:
     671      2060436 :       genericize_for_stmt (stmt_p, walk_subtrees, data, func, lh);
     672      2060436 :       break;
     673              : 
     674       879844 :     case WHILE_STMT:
     675       879844 :       genericize_while_stmt (stmt_p, walk_subtrees, data, func, lh);
     676       879844 :       break;
     677              : 
     678      1709101 :     case DO_STMT:
     679      1709101 :       genericize_do_stmt (stmt_p, walk_subtrees, data, func, lh);
     680      1709101 :       break;
     681              : 
     682       648492 :     case SWITCH_STMT:
     683       648492 :       genericize_switch_stmt (stmt_p, walk_subtrees, data, func, lh);
     684       648492 :       break;
     685              : 
     686        17401 :     case CONTINUE_STMT:
     687        17401 :       genericize_continue_stmt (stmt_p);
     688        17401 :       break;
     689              : 
     690      2215818 :     case BREAK_STMT:
     691      2215818 :       genericize_break_stmt (stmt_p);
     692      2215818 :       break;
     693              : 
     694        42320 :     case OMP_FOR:
     695        42320 :     case OMP_SIMD:
     696        42320 :     case OMP_DISTRIBUTE:
     697        42320 :     case OMP_LOOP:
     698        42320 :     case OMP_TASKLOOP:
     699        42320 :     case OMP_TILE:
     700        42320 :     case OMP_UNROLL:
     701        42320 :     case OACC_LOOP:
     702        42320 :       genericize_omp_for_stmt (stmt_p, walk_subtrees, data, func, lh);
     703        42320 :       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     83292987 :     case STATEMENT_LIST:
     711     83292987 :       if (TREE_SIDE_EFFECTS (stmt))
     712              :         {
     713     80486498 :           tree_stmt_iterator i;
     714     80486498 :           int nondebug_stmts = 0;
     715     80486498 :           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     76842418 :           hash_set<tree> *pset = (c_dialect_cxx ()
     724     80486498 :                                   ? nullptr
     725              :                                   : static_cast<hash_set<tree> *>(data));
     726    395104818 :           for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i))
     727              :             {
     728    314618320 :               tree t = tsi_stmt (i);
     729    314618320 :               if (TREE_CODE (t) != DEBUG_BEGIN_STMT && nondebug_stmts < 2)
     730    135398430 :                 nondebug_stmts++;
     731    314618320 :               walk_tree_1 (tsi_stmt_ptr (i), func, data, pset, lh);
     732    314618320 :               if (TREE_CODE (t) != DEBUG_BEGIN_STMT
     733    314618320 :                   && (nondebug_stmts > 1 || TREE_SIDE_EFFECTS (tsi_stmt (i))))
     734              :                 clear_side_effects = false;
     735              :             }
     736     80486498 :           if (clear_side_effects)
     737          370 :             TREE_SIDE_EFFECTS (stmt) = 0;
     738     80486498 :           *walk_subtrees = 0;
     739              :         }
     740              :       break;
     741              : 
     742              :     default:
     743              :       break;
     744              :     }
     745              : 
     746    747112325 :   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    660634824 : c_genericize_control_r (tree *stmt_p, int *walk_subtrees, void *data)
     756              : {
     757    660634824 :   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    660634824 :   if (TREE_CODE (stmt) == MODIFY_EXPR
     762     37502565 :       && (TREE_CODE (TREE_OPERAND (stmt, 0)) == REALPART_EXPR
     763     37501493 :           || TREE_CODE (TREE_OPERAND (stmt, 0)) == IMAGPART_EXPR)
     764         2156 :       && !optimize
     765          138 :       && DECL_P (TREE_OPERAND (TREE_OPERAND (stmt, 0), 0))
     766    660634948 :       && 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    660634824 :   c_genericize_control_stmt (stmt_p, walk_subtrees, data,
     770              :                              c_genericize_control_r, NULL);
     771    660634824 :   return NULL;
     772              : }
     773              : 
     774              : /* Convert the tree representation of FNDECL from C frontend trees to
     775              :    GENERIC.  */
     776              : 
     777              : void
     778     91273449 : c_genericize (tree fndecl)
     779              : {
     780     91273449 :   dump_file_info *dfi;
     781     91273449 :   FILE *dump_orig;
     782     91273449 :   dump_flags_t local_dump_flags;
     783     91273449 :   struct cgraph_node *cgn;
     784              : 
     785     91273449 :   if (flag_sanitize & SANITIZE_BOUNDS)
     786              :     {
     787        67497 :       hash_set<tree> pset;
     788        67497 :       walk_tree (&DECL_SAVED_TREE (fndecl), ubsan_walk_array_refs_r, &pset,
     789              :                  &pset);
     790        67497 :     }
     791              : 
     792              :   /* Genericize loops and other structured control constructs.  The C++
     793              :      front end has already done this in lang-specific code.  */
     794     91273449 :   if (!c_dialect_cxx ())
     795              :     {
     796     36250308 :       bc_state_t save_state;
     797     36250308 :       push_cfun (DECL_STRUCT_FUNCTION (fndecl));
     798     36250308 :       save_bc_state (&save_state);
     799     36250308 :       hash_set<tree> pset;
     800     36250308 :       walk_tree (&DECL_SAVED_TREE (fndecl), c_genericize_control_r, &pset,
     801              :                  &pset);
     802     36250323 :       delete bc_hash_map;
     803     36250308 :       bc_hash_map = NULL;
     804     36250308 :       restore_bc_state (&save_state);
     805     36250308 :       pop_cfun ();
     806     36250308 :     }
     807              : 
     808     91273449 :   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     91273449 :   dfi = g->get_dumps ()->get_dump_file_info (TDI_original);
     814     91273449 :   dump_orig = dfi->pstream;
     815     91273449 :   local_dump_flags = dfi->pflags;
     816     91273449 :   if (dump_orig)
     817              :     {
     818         7419 :       fprintf (dump_orig, "\n;; Function %s",
     819         7419 :                lang_hooks.decl_printable_name (fndecl, 2));
     820         7419 :       fprintf (dump_orig, " (%s)\n",
     821         7419 :                (!DECL_ASSEMBLER_NAME_SET_P (fndecl) ? "null"
     822           90 :                 : IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl))));
     823         7419 :       fprintf (dump_orig, ";; enabled by -%s\n", dump_flag_name (TDI_original));
     824         7419 :       fprintf (dump_orig, "\n");
     825              : 
     826         7419 :       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         7418 :         print_c_tree (dump_orig, DECL_SAVED_TREE (fndecl), local_dump_flags);
     831         7419 :       fprintf (dump_orig, "\n");
     832              :     }
     833              : 
     834              :   /* Dump all nested functions now.  */
     835     91273449 :   cgn = cgraph_node::get_create (fndecl);
     836     91275032 :   for (cgn = first_nested_function (cgn);
     837     91275032 :        cgn; cgn = next_nested_function (cgn))
     838         1583 :     c_genericize (cgn->decl);
     839     91273449 : }
     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    185617572 : c_build_bind_expr (location_t loc, tree block, tree body)
     866              : {
     867    185617572 :   tree decls, bind;
     868              : 
     869    185617572 :   if (block == NULL_TREE)
     870              :     decls = NULL_TREE;
     871     71137315 :   else if (TREE_CODE (block) == BLOCK)
     872     71137315 :     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    185617572 :   if (!body)
     887            0 :     body = build_empty_stmt (loc);
     888    185617572 :   if (decls || block)
     889              :     {
     890     71137315 :       bind = build3 (BIND_EXPR, void_type_node, decls, body, block);
     891     71137315 :       TREE_SIDE_EFFECTS (bind) = 1;
     892     71137315 :       SET_EXPR_LOCATION (bind, loc);
     893              :     }
     894              :   else
     895              :     bind = body;
     896              : 
     897    185617572 :   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    262517496 : c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
     915              :                  gimple_seq *post_p ATTRIBUTE_UNUSED)
     916              : {
     917    262517496 :   enum tree_code code = TREE_CODE (*expr_p);
     918              : 
     919    262517496 :   switch (code)
     920              :     {
     921       338794 :     case LSHIFT_EXPR:
     922       338794 :     case RSHIFT_EXPR:
     923       338794 :     case LROTATE_EXPR:
     924       338794 :     case RROTATE_EXPR:
     925       338794 :       {
     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       338794 :         tree *op1_p = &TREE_OPERAND (*expr_p, 1);
     935       338794 :         if (!error_operand_p (*op1_p)
     936       338793 :             && !VECTOR_TYPE_P (TREE_TYPE (*op1_p))
     937       337076 :             && !types_compatible_p (TYPE_MAIN_VARIANT (TREE_TYPE (*op1_p)),
     938              :                                     unsigned_type_node)
     939       636909 :             && !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        13168 :           *op1_p = unshare_expr (convert (unsigned_type_node, *op1_p));
     944              :         break;
     945              :       }
     946              : 
     947      1141914 :     case PREINCREMENT_EXPR:
     948      1141914 :     case PREDECREMENT_EXPR:
     949      1141914 :     case POSTINCREMENT_EXPR:
     950      1141914 :     case POSTDECREMENT_EXPR:
     951      1141914 :       {
     952      1141914 :         tree type = TREE_TYPE (TREE_OPERAND (*expr_p, 0));
     953      1141914 :         if (INTEGRAL_TYPE_P (type) && c_promoting_integer_type_p (type))
     954              :           {
     955         5702 :             if (!TYPE_OVERFLOW_WRAPS (type))
     956         3311 :               type = unsigned_type_for (type);
     957         5702 :             return gimplify_self_mod_expr (expr_p, pre_p, post_p, 1, type);
     958              :           }
     959              :         break;
     960              :       }
     961              : 
     962      7705491 :     case PLUS_EXPR:
     963      7705491 :     case MINUS_EXPR:
     964      7705491 :       {
     965      7705491 :         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      7705491 :         if (SCALAR_FLOAT_TYPE_P (type)
     970       957248 :             && flag_fp_contract_mode == FP_CONTRACT_ON
     971           22 :             && cfun && !(cfun->curr_properties & PROP_gimple_any)
     972      7705513 :             && 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      3757363 :     case CALL_EXPR:
    1032      3757363 :       {
    1033      3757363 :         tree fndecl = get_callee_fndecl (*expr_p);
    1034      3757363 :         if (fndecl
    1035      3506340 :             && fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
    1036           74 :             && call_expr_nargs (*expr_p) == 2
    1037      3757437 :             && TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
    1038              :           {
    1039           74 :             tree a = CALL_EXPR_ARG (*expr_p, 0);
    1040           74 :             if (gimplify_expr (&a, pre_p, post_p, is_gimple_val, fb_rvalue)
    1041              :                 == GS_ERROR)
    1042              :               return GS_ERROR;
    1043           74 :             tree b = CALL_EXPR_ARG (*expr_p, 1);
    1044           74 :             if (gimplify_expr (&b, pre_p, post_p, is_gimple_val, fb_rvalue)
    1045              :                 == GS_ERROR)
    1046              :               return GS_ERROR;
    1047           74 :             tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
    1048              :                                           fndecl, 1, a);
    1049          148 :             *expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
    1050              :                                   integer_type_node,
    1051           74 :                                   build2_loc (EXPR_LOCATION (*expr_p),
    1052              :                                               NE_EXPR, boolean_type_node, a,
    1053           74 :                                               build_zero_cst (TREE_TYPE (a))),
    1054              :                                   c, b);
    1055           74 :             return GS_OK;
    1056              :           }
    1057              :         break;
    1058              :       }
    1059              : 
    1060              :     default:;
    1061              :     }
    1062              : 
    1063              :   return GS_UNHANDLED;
    1064              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.