LCOV - code coverage report
Current view: top level - gcc - gimplify-me.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.6 % 135 121
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 5 5
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Tree lowering to gimple for middle end use only.
       2              :    This converts the GENERIC functions-as-trees tree representation into
       3              :    the GIMPLE form.
       4              :    Copyright (C) 2013-2026 Free Software Foundation, Inc.
       5              :    Major work done by Sebastian Pop <s.pop@laposte.net>,
       6              :    Diego Novillo <dnovillo@redhat.com> and Jason Merrill <jason@redhat.com>.
       7              : 
       8              : This file is part of GCC.
       9              : 
      10              : GCC is free software; you can redistribute it and/or modify it under
      11              : the terms of the GNU General Public License as published by the Free
      12              : Software Foundation; either version 3, or (at your option) any later
      13              : version.
      14              : 
      15              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      16              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      17              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      18              : for more details.
      19              : 
      20              : You should have received a copy of the GNU General Public License
      21              : along with GCC; see the file COPYING3.  If not see
      22              : <http://www.gnu.org/licenses/>.  */
      23              : 
      24              : #include "config.h"
      25              : #include "system.h"
      26              : #include "coretypes.h"
      27              : #include "backend.h"
      28              : #include "tree.h"
      29              : #include "gimple.h"
      30              : #include "ssa.h"
      31              : #include "stmt.h"
      32              : #include "stor-layout.h"
      33              : #include "tree-eh.h"
      34              : #include "gimple-iterator.h"
      35              : #include "gimplify.h"
      36              : #include "gimplify-me.h"
      37              : 
      38              : 
      39              : /* Expand EXPR to list of gimple statements STMTS.  GIMPLE_TEST_F specifies
      40              :    the predicate that will hold for the result.  If VAR is not NULL, make the
      41              :    base variable of the final destination be VAR if suitable.  */
      42              : 
      43              : tree
      44      8254109 : force_gimple_operand_1 (tree expr, gimple_seq *stmts,
      45              :                         gimple_predicate gimple_test_f, tree var)
      46              : {
      47      8254109 :   enum gimplify_status ret;
      48      8254109 :   location_t saved_location;
      49              : 
      50      8254109 :   *stmts = NULL;
      51              : 
      52              :   /* gimple_test_f might be more strict than is_gimple_val, make
      53              :      sure we pass both.  Just checking gimple_test_f doesn't work
      54              :      because most gimple predicates do not work recursively.  */
      55      8254109 :   if (is_gimple_val (expr)
      56      8254109 :       && (*gimple_test_f) (expr))
      57      5061013 :     return expr;
      58              : 
      59      6386192 :   push_gimplify_context (gimple_in_ssa_p (cfun), true);
      60      3193096 :   saved_location = input_location;
      61      3193096 :   input_location = UNKNOWN_LOCATION;
      62              : 
      63      3193096 :   if (var)
      64              :     {
      65      1121370 :       if (gimple_in_ssa_p (cfun) && is_gimple_reg (var))
      66       560685 :         var = make_ssa_name (var);
      67       560685 :       expr = build2 (MODIFY_EXPR, TREE_TYPE (var), var, expr);
      68              :     }
      69              : 
      70      3193096 :   if (TREE_CODE (expr) != MODIFY_EXPR
      71      3193096 :       && TREE_TYPE (expr) == void_type_node)
      72              :     {
      73        36852 :       gimplify_and_add (expr, stmts);
      74        36852 :       expr = NULL_TREE;
      75              :     }
      76              :   else
      77              :     {
      78      3156244 :       ret = gimplify_expr (&expr, stmts, NULL, gimple_test_f, fb_rvalue);
      79      3156244 :       gcc_assert (ret != GS_ERROR);
      80              :     }
      81              : 
      82      3193096 :   input_location = saved_location;
      83      3193096 :   pop_gimplify_context (NULL);
      84              : 
      85      3193096 :   return expr;
      86              : }
      87              : 
      88              : /* Expand EXPR to list of gimple statements STMTS.  If SIMPLE is true,
      89              :    force the result to be either ssa_name or an invariant, otherwise
      90              :    just force it to be a rhs expression.  If VAR is not NULL, make the
      91              :    base variable of the final destination be VAR if suitable.  */
      92              : 
      93              : tree
      94      5080195 : force_gimple_operand (tree expr, gimple_seq *stmts, bool simple, tree var)
      95              : {
      96      5680838 :   return force_gimple_operand_1 (expr, stmts,
      97              :                                  simple ? is_gimple_val : is_gimple_reg_rhs,
      98      5080195 :                                  var);
      99              : }
     100              : 
     101              : /* Invoke force_gimple_operand_1 for EXPR with parameters GIMPLE_TEST_F
     102              :    and VAR.  If some statements are produced, emits them at GSI.
     103              :    If BEFORE is true.  the statements are appended before GSI, otherwise
     104              :    they are appended after it.  M specifies the way GSI moves after
     105              :    insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING are the usual values).  */
     106              : 
     107              : tree
     108      3004539 : force_gimple_operand_gsi_1 (gimple_stmt_iterator *gsi, tree expr,
     109              :                             gimple_predicate gimple_test_f,
     110              :                             tree var, bool before,
     111              :                             enum gsi_iterator_update m)
     112              : {
     113      3004539 :   gimple_seq stmts;
     114              : 
     115      3004539 :   expr = force_gimple_operand_1 (expr, &stmts, gimple_test_f, var);
     116              : 
     117      3004539 :   if (!gimple_seq_empty_p (stmts))
     118              :     {
     119      1145658 :       if (before)
     120      1053030 :         gsi_insert_seq_before (gsi, stmts, m);
     121              :       else
     122        92628 :         gsi_insert_seq_after (gsi, stmts, m);
     123              :     }
     124              : 
     125      3004539 :   return expr;
     126              : }
     127              : 
     128              : /* Invoke force_gimple_operand_1 for EXPR with parameter VAR.
     129              :    If SIMPLE is true, force the result to be either ssa_name or an invariant,
     130              :    otherwise just force it to be a rhs expression.  If some statements are
     131              :    produced, emits them at GSI.  If BEFORE is true, the statements are
     132              :    appended before GSI, otherwise they are appended after it.  M specifies
     133              :    the way GSI moves after insertion (GSI_SAME_STMT or GSI_CONTINUE_LINKING
     134              :    are the usual values).  */
     135              : 
     136              : tree
     137      2122750 : force_gimple_operand_gsi (gimple_stmt_iterator *gsi, tree expr,
     138              :                           bool simple_p, tree var, bool before,
     139              :                           enum gsi_iterator_update m)
     140              : {
     141      2336502 :   return force_gimple_operand_gsi_1 (gsi, expr,
     142              :                                      simple_p
     143              :                                      ? is_gimple_val : is_gimple_reg_rhs,
     144      2122750 :                                      var, before, m);
     145              : }
     146              : 
     147              : /* Some transformations like inlining may invalidate the GIMPLE form
     148              :    for operands.  This function traverses all the operands in STMT and
     149              :    gimplifies anything that is not a valid gimple operand.  Any new
     150              :    GIMPLE statements are inserted before *GSI_P.  */
     151              : 
     152              : void
     153       552826 : gimple_regimplify_operands (gimple *stmt, gimple_stmt_iterator *gsi_p)
     154              : {
     155       552826 :   size_t i, num_ops;
     156       552826 :   tree lhs;
     157       552826 :   gimple_seq pre = NULL;
     158       552826 :   gimple *post_stmt = NULL;
     159              : 
     160      1105652 :   push_gimplify_context (gimple_in_ssa_p (cfun));
     161              : 
     162       552826 :   switch (gimple_code (stmt))
     163              :     {
     164         1263 :     case GIMPLE_COND:
     165         1263 :       {
     166         1263 :         gcond *cond_stmt = as_a <gcond *> (stmt);
     167         1263 :         gimplify_expr (gimple_cond_lhs_ptr (cond_stmt), &pre, NULL,
     168              :                        is_gimple_val, fb_rvalue);
     169         1263 :         gimplify_expr (gimple_cond_rhs_ptr (cond_stmt), &pre, NULL,
     170              :                        is_gimple_val, fb_rvalue);
     171              :       }
     172         1263 :       break;
     173            0 :     case GIMPLE_SWITCH:
     174            0 :       gimplify_expr (gimple_switch_index_ptr (as_a <gswitch *> (stmt)),
     175              :                      &pre, NULL, is_gimple_val, fb_rvalue);
     176            0 :       break;
     177         1425 :     case GIMPLE_OMP_ATOMIC_LOAD:
     178         1425 :       gimplify_expr (gimple_omp_atomic_load_rhs_ptr (
     179              :                        as_a <gomp_atomic_load *> (stmt)),
     180              :                      &pre, NULL, is_gimple_val, fb_rvalue);
     181         1425 :       break;
     182           14 :     case GIMPLE_ASM:
     183           14 :       {
     184           14 :         gasm *asm_stmt = as_a <gasm *> (stmt);
     185           14 :         size_t i, noutputs = gimple_asm_noutputs (asm_stmt);
     186           14 :         const char *constraint, **oconstraints;
     187           14 :         bool allows_mem, allows_reg, is_inout;
     188              : 
     189           14 :         oconstraints
     190           14 :           = (const char **) alloca ((noutputs) * sizeof (const char *));
     191           32 :         for (i = 0; i < noutputs; i++)
     192              :           {
     193           18 :             tree op = gimple_asm_output_op (asm_stmt, i);
     194           18 :             constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
     195           18 :             oconstraints[i] = constraint;
     196           18 :             parse_output_constraint (&constraint, i, 0, 0, &allows_mem,
     197              :                                      &allows_reg, &is_inout, nullptr);
     198           36 :             gimplify_expr (&TREE_VALUE (op), &pre, NULL,
     199              :                            is_inout ? is_gimple_min_lval : is_gimple_lvalue,
     200              :                            fb_lvalue | fb_mayfail);
     201              :           }
     202           37 :         for (i = 0; i < gimple_asm_ninputs (asm_stmt); i++)
     203              :           {
     204           23 :             tree op = gimple_asm_input_op (asm_stmt, i);
     205           23 :             constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (op)));
     206           23 :             parse_input_constraint (&constraint, 0, 0, noutputs, 0,
     207              :                                     oconstraints, &allows_mem, &allows_reg,
     208              :                                     nullptr);
     209           23 :             if (TREE_ADDRESSABLE (TREE_TYPE (TREE_VALUE (op))) && allows_mem)
     210            0 :               allows_reg = 0;
     211           23 :             if (!allows_reg && allows_mem)
     212            1 :               gimplify_expr (&TREE_VALUE (op), &pre, NULL,
     213              :                              is_gimple_lvalue, fb_lvalue | fb_mayfail);
     214              :             else
     215           22 :               gimplify_expr (&TREE_VALUE (op), &pre, NULL,
     216              :                              is_gimple_asm_val, fb_rvalue);
     217              :           }
     218              :       }
     219           14 :       break;
     220       550124 :     default:
     221              :       /* NOTE: We start gimplifying operands from last to first to
     222              :          make sure that side-effects on the RHS of calls, assignments
     223              :          and ASMs are executed before the LHS.  The ordering is not
     224              :          important for other statements.  */
     225       550124 :       num_ops = gimple_num_ops (stmt);
     226      1675447 :       for (i = num_ops; i > 0; i--)
     227              :         {
     228      1125323 :           tree op = gimple_op (stmt, i - 1);
     229      1125323 :           if (op == NULL_TREE)
     230         5738 :             continue;
     231      1119588 :           if (i == 1 && (is_gimple_call (stmt) || is_gimple_assign (stmt)))
     232       548042 :             gimplify_expr (&op, &pre, NULL, is_gimple_lvalue, fb_lvalue);
     233       571546 :           else if (i == 2
     234       550100 :                    && gimple_assign_single_p (stmt)
     235      1101465 :                    && num_ops == 2)
     236              :             {
     237       529919 :               if (gimple_clobber_p (stmt))
     238            3 :                 continue;
     239       529916 :               gimplify_expr (&op, &pre, NULL,
     240              :                              rhs_predicate_for (gimple_assign_lhs (stmt)),
     241              :                              fb_rvalue);
     242              :             }
     243        41627 :           else if (i == 2 && is_gimple_call (stmt))
     244              :             {
     245         3673 :               if (TREE_CODE (op) == FUNCTION_DECL)
     246            0 :                 continue;
     247         3673 :               gimplify_expr (&op, &pre, NULL, is_gimple_call_addr, fb_rvalue);
     248              :             }
     249              :           else
     250        37954 :             gimplify_expr (&op, &pre, NULL, is_gimple_val, fb_rvalue);
     251      1119585 :           gimple_set_op (stmt, i - 1, op);
     252              :         }
     253              : 
     254       550124 :       lhs = gimple_get_lhs (stmt);
     255              :       /* If the LHS changed it in a way that requires a simple RHS,
     256              :          create temporary.  */
     257       550124 :       if (lhs && !is_gimple_reg (lhs))
     258              :         {
     259       385271 :           bool need_temp = false;
     260              : 
     261       385271 :           if (gimple_clobber_p (stmt))
     262              :             ;
     263       385268 :           else if (gimple_assign_single_p (stmt) && num_ops == 2)
     264       376836 :             gimplify_expr (gimple_assign_rhs1_ptr (stmt), &pre, NULL,
     265              :                            rhs_predicate_for (gimple_assign_lhs (stmt)),
     266              :                            fb_rvalue);
     267         8432 :           else if (is_gimple_reg (lhs))
     268              :             {
     269            0 :               if (is_gimple_reg_type (TREE_TYPE (lhs)))
     270              :                 {
     271            0 :                   if (is_gimple_call (stmt))
     272              :                     {
     273            0 :                       i = gimple_call_flags (stmt);
     274            0 :                       if ((i & ECF_LOOPING_CONST_OR_PURE)
     275            0 :                           || !(i & (ECF_CONST | ECF_PURE)))
     276            0 :                         need_temp = true;
     277              :                     }
     278            0 :                   if (stmt_can_throw_internal (cfun, stmt))
     279              :                     need_temp = true;
     280              :                 }
     281              :             }
     282              :           else
     283              :             {
     284         8432 :               if (is_gimple_reg_type (TREE_TYPE (lhs)))
     285              :                 need_temp = true;
     286          274 :               else if (TYPE_MODE (TREE_TYPE (lhs)) != BLKmode)
     287              :                 {
     288          129 :                   if (is_gimple_call (stmt))
     289              :                     {
     290          129 :                       tree fndecl = gimple_call_fndecl (stmt);
     291              : 
     292          129 :                       if (!aggregate_value_p (TREE_TYPE (lhs), fndecl)
     293          257 :                           && !(fndecl && DECL_RESULT (fndecl)
     294          128 :                                && DECL_BY_REFERENCE (DECL_RESULT (fndecl))))
     295              :                         need_temp = true;
     296              :                     }
     297              :                   else
     298              :                     need_temp = true;
     299              :                 }
     300              :             }
     301       376836 :           if (need_temp)
     302              :             {
     303         8287 :               tree temp = create_tmp_reg (TREE_TYPE (lhs));
     304         8287 :               if (gimple_in_ssa_p (cfun)
     305            0 :                   && is_gimple_reg_type (TREE_TYPE (lhs)))
     306            0 :                 temp = make_ssa_name (temp);
     307         8287 :               gimple_set_lhs (stmt, temp);
     308         8287 :               post_stmt = gimple_build_assign (lhs, temp);
     309              :             }
     310              :         }
     311              :       break;
     312              :     }
     313              : 
     314       552826 :   if (!gimple_seq_empty_p (pre))
     315        77744 :     gsi_insert_seq_before (gsi_p, pre, GSI_SAME_STMT);
     316       552826 :   if (post_stmt)
     317         8287 :     gsi_insert_after (gsi_p, post_stmt, GSI_NEW_STMT);
     318              : 
     319       552826 :   pop_gimplify_context (NULL);
     320              : 
     321       552826 :   update_stmt (stmt);
     322       552826 : }
     323              : 
     324              : 
        

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.