LCOV - code coverage report
Current view: top level - gcc - ipa-icf-gimple.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.4 % 522 477
Test Date: 2026-05-30 15:37:04 Functions: 96.7 % 30 29
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Interprocedural Identical Code Folding pass
       2              :    Copyright (C) 2014-2026 Free Software Foundation, Inc.
       3              : 
       4              :    Contributed by Jan Hubicka <hubicka@ucw.cz> and Martin Liska <mliska@suse.cz>
       5              : 
       6              : This file is part of GCC.
       7              : 
       8              : GCC is free software; you can redistribute it and/or modify it under
       9              : the terms of the GNU General Public License as published by the Free
      10              : Software Foundation; either version 3, or (at your option) any later
      11              : version.
      12              : 
      13              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      14              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      15              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      16              : for more details.
      17              : 
      18              : You should have received a copy of the GNU General Public License
      19              : along with GCC; see the file COPYING3.  If not see
      20              : <http://www.gnu.org/licenses/>.  */
      21              : 
      22              : #include "config.h"
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "backend.h"
      26              : #include "rtl.h"
      27              : #include "tree.h"
      28              : #include "gimple.h"
      29              : #include "tree-pass.h"
      30              : #include "ssa.h"
      31              : #include "cgraph.h"
      32              : #include "data-streamer.h"
      33              : #include "gimple-pretty-print.h"
      34              : #include "fold-const.h"
      35              : #include "gimple-iterator.h"
      36              : #include "ipa-utils.h"
      37              : #include "tree-eh.h"
      38              : #include "builtins.h"
      39              : #include "cfgloop.h"
      40              : #include "attribs.h"
      41              : #include "gimple-walk.h"
      42              : #include "tree-sra.h"
      43              : 
      44              : #include "tree-ssa-alias-compare.h"
      45              : #include "alloc-pool.h"
      46              : #include "symbol-summary.h"
      47              : #include "ipa-icf-gimple.h"
      48              : #include "sreal.h"
      49              : #include "ipa-cp.h"
      50              : #include "ipa-prop.h"
      51              : 
      52              : namespace ipa_icf_gimple {
      53              : 
      54              : /* Initialize internal structures for a given SOURCE_FUNC_DECL and
      55              :    TARGET_FUNC_DECL. Strict polymorphic comparison is processed if
      56              :    an option COMPARE_POLYMORPHIC is true. For special cases, one can
      57              :    set IGNORE_LABELS to skip label comparison.
      58              :    Similarly, IGNORE_SOURCE_DECLS and IGNORE_TARGET_DECLS are sets
      59              :    of declarations that can be skipped.  */
      60              : 
      61       123654 : func_checker::func_checker (tree source_func_decl, tree target_func_decl,
      62              :                             bool ignore_labels, bool tbaa,
      63              :                             hash_set<symtab_node *> *ignored_source_nodes,
      64       123654 :                             hash_set<symtab_node *> *ignored_target_nodes)
      65       123654 :   : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
      66       123654 :     m_ignored_source_nodes (ignored_source_nodes),
      67       123654 :     m_ignored_target_nodes (ignored_target_nodes),
      68       123654 :     m_ignore_labels (ignore_labels), m_tbaa (tbaa),
      69       123654 :     m_total_scalarization_limit_known_p (false)
      70              : {
      71       123654 :   function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
      72       123654 :   function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
      73              : 
      74       123654 :   unsigned ssa_source = SSANAMES (source_func)->length ();
      75       123654 :   unsigned ssa_target = SSANAMES (target_func)->length ();
      76              : 
      77       123654 :   m_source_ssa_names.create (ssa_source);
      78       123654 :   m_target_ssa_names.create (ssa_target);
      79              : 
      80      1082045 :   for (unsigned i = 0; i < ssa_source; i++)
      81       958391 :     m_source_ssa_names.safe_push (-1);
      82              : 
      83      1081649 :   for (unsigned i = 0; i < ssa_target; i++)
      84       957995 :     m_target_ssa_names.safe_push (-1);
      85       123654 : }
      86              : 
      87              : /* Memory release routine.  */
      88              : 
      89       501751 : func_checker::~func_checker ()
      90              : {
      91       378097 :   m_source_ssa_names.release();
      92       378097 :   m_target_ssa_names.release();
      93       501751 : }
      94              : 
      95              : /* Verifies that trees T1 and T2 are equivalent from perspective of ICF.  */
      96              : 
      97              : bool
      98      1276090 : func_checker::compare_ssa_name (const_tree t1, const_tree t2)
      99              : {
     100      1276090 :   gcc_assert (TREE_CODE (t1) == SSA_NAME);
     101      1276090 :   gcc_assert (TREE_CODE (t2) == SSA_NAME);
     102              : 
     103      1276090 :   unsigned i1 = SSA_NAME_VERSION (t1);
     104      1276090 :   unsigned i2 = SSA_NAME_VERSION (t2);
     105              : 
     106      1276090 :   if (SSA_NAME_IS_DEFAULT_DEF (t1) != SSA_NAME_IS_DEFAULT_DEF (t2))
     107              :     return false;
     108              : 
     109      1276090 :   if (m_source_ssa_names[i1] == -1)
     110       366691 :     m_source_ssa_names[i1] = i2;
     111       909399 :   else if (m_source_ssa_names[i1] != (int) i2)
     112              :     return false;
     113              : 
     114      1275901 :   if(m_target_ssa_names[i2] == -1)
     115       366687 :     m_target_ssa_names[i2] = i1;
     116       909214 :   else if (m_target_ssa_names[i2] != (int) i1)
     117              :     return false;
     118              : 
     119      1275897 :   if (SSA_NAME_IS_DEFAULT_DEF (t1))
     120              :     {
     121       249578 :       tree b1 = SSA_NAME_VAR (t1);
     122       249578 :       tree b2 = SSA_NAME_VAR (t2);
     123              : 
     124       249578 :       return compare_operand (b1, b2, OP_NORMAL);
     125              :     }
     126              : 
     127              :   return true;
     128              : }
     129              : 
     130              : /* Verification function for edges E1 and E2.  */
     131              : 
     132              : bool
     133       541582 : func_checker::compare_edge (edge e1, edge e2)
     134              : {
     135       541582 :   if (e1->flags != e2->flags)
     136              :     return false;
     137              : 
     138       541582 :   bool existed_p;
     139              : 
     140       541582 :   edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
     141       541582 :   if (existed_p)
     142       253394 :     return return_with_debug (slot == e2);
     143              :   else
     144       288188 :     slot = e2;
     145              : 
     146              :   /* TODO: filter edge probabilities for profile feedback match.  */
     147              : 
     148       288188 :   return true;
     149              : }
     150              : 
     151              : /* Verification function for declaration trees T1 and T2 that
     152              :    come from functions FUNC1 and FUNC2.  */
     153              : 
     154              : bool
     155       504774 : func_checker::compare_decl (const_tree t1, const_tree t2)
     156              : {
     157       504774 :   if (!auto_var_in_fn_p (t1, m_source_func_decl)
     158       504774 :       || !auto_var_in_fn_p (t2, m_target_func_decl))
     159            6 :     return return_with_debug (t1 == t2);
     160              : 
     161       504768 :   tree_code t = TREE_CODE (t1);
     162       504768 :   if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
     163       504768 :       && DECL_BY_REFERENCE (t1) != DECL_BY_REFERENCE (t2))
     164            0 :     return return_false_with_msg ("DECL_BY_REFERENCE flags are different");
     165              : 
     166              :   /* We do not really need to check types of variables, since they are just
     167              :      blocks of memory and we verify types of the accesses to them.
     168              :      However do compare types of other kinds of decls
     169              :      (parm decls and result decl types may affect ABI convetions).  */
     170       504768 :   if (t != VAR_DECL)
     171              :     {
     172       427825 :       if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     173            0 :         return return_false ();
     174              :     }
     175              :   else
     176              :     {
     177        76943 :       if (!operand_equal_p (DECL_SIZE (t1), DECL_SIZE (t2),
     178              :                             OEP_MATCH_SIDE_EFFECTS))
     179            0 :         return return_false_with_msg ("DECL_SIZEs are different");
     180              :     }
     181              : 
     182       504768 :   bool existed_p;
     183       504768 :   const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
     184       504768 :   if (existed_p)
     185       328600 :     return return_with_debug (slot == t2);
     186              :   else
     187       176168 :     slot = t2;
     188              : 
     189       176168 :   return true;
     190              : }
     191              : 
     192              : /* Return true if T1 and T2 are same for purposes of ipa-polymorphic-call
     193              :    analysis.  COMPARE_PTR indicates if types of pointers needs to be
     194              :    considered.  */
     195              : 
     196              : bool
     197        14282 : func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
     198              :                                               bool compare_ptr)
     199              : {
     200        14282 :   gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
     201              : 
     202              :   /* Pointer types generally give no information.  */
     203        14282 :   if (POINTER_TYPE_P (t1))
     204              :     {
     205            0 :       if (!compare_ptr)
     206              :         return true;
     207            0 :       return func_checker::compatible_polymorphic_types_p (TREE_TYPE (t1),
     208            0 :                                                            TREE_TYPE (t2),
     209            0 :                                                            false);
     210              :     }
     211              : 
     212              :   /* If types contain a polymorphic types, match them.  */
     213        14282 :   bool c1 = contains_polymorphic_type_p (t1);
     214        14282 :   bool c2 = contains_polymorphic_type_p (t2);
     215        14282 :   if (!c1 && !c2)
     216              :     return true;
     217          760 :   if (!c1 || !c2)
     218            0 :     return return_false_with_msg ("one type is not polymorphic");
     219          760 :   if (!types_must_be_same_for_odr (t1, t2))
     220            0 :     return return_false_with_msg ("types are not same for ODR");
     221              :   return true;
     222              : }
     223              : 
     224              : /* Return true if types are compatible from perspective of ICF.  */
     225              : bool
     226      4372579 : func_checker::compatible_types_p (tree t1, tree t2)
     227              : {
     228      4372579 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     229       137900 :     return return_false_with_msg ("different tree types");
     230              : 
     231      4234679 :   if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
     232          114 :     return return_false_with_msg ("restrict flags are different");
     233              : 
     234      4234565 :   if (!types_compatible_p (t1, t2))
     235       945256 :     return return_false_with_msg ("types are not compatible");
     236              : 
     237              :   return true;
     238              : }
     239              : 
     240              : /* Add hash of ARG to HSTATE. FLAGS have same meaning
     241              :    as for operand_equal_p.  Works only if operand acces type is OP_NORMAL.  */
     242              : 
     243              : void
     244    131979012 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     245              :                             unsigned int flags)
     246              : {
     247    136864781 :   if (arg == NULL_TREE)
     248              :     {
     249     15390324 :       hstate.merge_hash (0);
     250     15390324 :       return;
     251              :     }
     252              : 
     253    121474457 :   switch (TREE_CODE (arg))
     254              :     {
     255      5500393 :     case PARM_DECL:
     256      5500393 :       {
     257      5500393 :         unsigned int index = 0;
     258      5500393 :         if (DECL_CONTEXT (arg))
     259      5500393 :           for (tree p = DECL_ARGUMENTS (DECL_CONTEXT (arg));
     260     11113556 :                p && index < 32; p = DECL_CHAIN (p), index++)
     261     11104623 :             if (p == arg)
     262              :               break;
     263      5500393 :         hstate.add_int (PARM_DECL);
     264      5500393 :         hstate.add_int (index);
     265              :       }
     266      5500393 :       return;
     267     14427550 :     case FUNCTION_DECL:
     268     14427550 :     case VAR_DECL:
     269     14427550 :     case LABEL_DECL:
     270     14427550 :     case RESULT_DECL:
     271     14427550 :     case CONST_DECL:
     272     14427550 :       hstate.add_int (TREE_CODE (arg));
     273     14427550 :       return;
     274     33195341 :     case SSA_NAME:
     275     33195341 :       hstate.add_int (SSA_NAME);
     276     33195341 :       if (SSA_NAME_IS_DEFAULT_DEF (arg))
     277      4885769 :         hash_operand (SSA_NAME_VAR (arg), hstate, flags);
     278              :       return;
     279          237 :     case FIELD_DECL:
     280          237 :       inchash::add_expr (DECL_FIELD_OFFSET (arg), hstate, flags);
     281          237 :       inchash::add_expr (DECL_FIELD_BIT_OFFSET (arg), hstate, flags);
     282          237 :       return;
     283     68350936 :     default:
     284     68350936 :       break;
     285              :     }
     286              : 
     287              :   /* In gimple all clobbers can be considered equal: while comparaing two
     288              :      gimple clobbers we match the left hand memory accesses.  */
     289     68350936 :   if (TREE_CLOBBER_P (arg))
     290              :     {
     291      1188777 :       hstate.add_int (0xc10bbe5);
     292      1188777 :       return;
     293              :     }
     294     67162159 :   gcc_assert (!DECL_P (arg));
     295     67162159 :   gcc_assert (!TYPE_P (arg));
     296              : 
     297     67162159 :   return operand_compare::hash_operand (arg, hstate, flags);
     298              : }
     299              : 
     300              : /* Add hash of ARG accesses according to ACCESS to HSTATE.
     301              :    FLAGS have same meaning as for operand_equal_p.  */
     302              : 
     303              : void
     304     64876180 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     305              :                             unsigned int flags, operand_access_type access)
     306              : {
     307     64876180 :   if (access == OP_MEMORY)
     308              :     {
     309      8044752 :       ao_ref ref;
     310      8044752 :       ao_ref_init (&ref, const_cast <tree> (arg));
     311      8044752 :       return hash_ao_ref (&ref, lto_streaming_expected_p (), m_tbaa, hstate);
     312              :     }
     313              :   else
     314     56831428 :     return hash_operand (arg, hstate, flags);
     315              : }
     316              : 
     317              : bool
     318      5056477 : func_checker::operand_equal_p (const_tree t1, const_tree t2,
     319              :                                unsigned int flags)
     320              : {
     321      5056477 :   bool r;
     322      5056477 :   if (verify_hash_value (t1, t2, flags, &r))
     323      2192243 :     return r;
     324              : 
     325      2864234 :   if (t1 == t2)
     326              :     return true;
     327      2150767 :   else if (!t1 || !t2)
     328              :     return false;
     329              : 
     330      2150767 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     331            1 :     return return_false ();
     332              : 
     333      2150766 :   switch (TREE_CODE (t1))
     334              :     {
     335              :     case FUNCTION_DECL:
     336              :       /* All function decls are in the symbol table and known to match
     337              :          before we start comparing bodies.  */
     338              :       return true;
     339        76967 :     case VAR_DECL:
     340        76967 :       return return_with_debug (compare_variable_decl (t1, t2));
     341         3792 :     case LABEL_DECL:
     342         3792 :       {
     343         3792 :         int *bb1 = m_label_bb_map.get (t1);
     344         3792 :         int *bb2 = m_label_bb_map.get (t2);
     345              :         /* Labels can point to another function (non-local GOTOs).  */
     346         3797 :         return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
     347              :       }
     348              : 
     349       264804 :     case PARM_DECL:
     350       264804 :     case RESULT_DECL:
     351       264804 :     case CONST_DECL:
     352       264804 :       return compare_decl (t1, t2);
     353      1276090 :     case SSA_NAME:
     354      1276090 :       return compare_ssa_name (t1, t2);
     355       516875 :     default:
     356       516875 :       break;
     357              :     }
     358              :   /* In gimple all clobbers can be considered equal.  We match the left hand
     359              :      memory accesses.  */
     360       516875 :   if (TREE_CLOBBER_P (t1) || TREE_CLOBBER_P (t2))
     361        24076 :     return TREE_CLOBBER_P (t1) == TREE_CLOBBER_P (t2);
     362              : 
     363       492799 :   return operand_compare::operand_equal_p (t1, t2, flags);
     364              : }
     365              : 
     366              : /* Return true if either T1 and T2 cannot be totally scalarized or if doing
     367              :    so would result in copying the same memory.  Otherwise return false.  */
     368              : 
     369              : bool
     370       173502 : func_checker::safe_for_total_scalarization_p (tree t1, tree t2)
     371              : {
     372       173502 :   tree type1 = TREE_TYPE (t1);
     373       173502 :   tree type2 = TREE_TYPE (t2);
     374              : 
     375       173502 :   if (!AGGREGATE_TYPE_P (type1)
     376        40861 :       || !AGGREGATE_TYPE_P (type2)
     377        40861 :       || !tree_fits_uhwi_p (TYPE_SIZE (type1))
     378       214363 :       || !tree_fits_uhwi_p (TYPE_SIZE (type2)))
     379              :     return true;
     380              : 
     381        40861 :   if (!m_total_scalarization_limit_known_p)
     382              :     {
     383         6900 :       push_cfun (DECL_STRUCT_FUNCTION (m_target_func_decl));
     384         6900 :       m_total_scalarization_limit = sra_get_max_scalarization_size ();
     385         6900 :       pop_cfun ();
     386         6900 :       m_total_scalarization_limit_known_p = true;
     387              :     }
     388              : 
     389        40861 :   unsigned HOST_WIDE_INT sz = tree_to_uhwi (TYPE_SIZE (type1));
     390        40861 :   gcc_assert (sz == tree_to_uhwi (TYPE_SIZE (type2)));
     391        40861 :   if (sz > m_total_scalarization_limit)
     392              :     return true;
     393        40644 :   return sra_total_scalarization_would_copy_same_data_p (type1, type2);
     394              : }
     395              : 
     396              : /* Function responsible for comparison of various operands T1 and T2
     397              :    which are accessed as ACCESS.
     398              :    If these components, from functions FUNC1 and FUNC2, are equal, true
     399              :    is returned.  */
     400              : 
     401              : bool
     402      2516709 : func_checker::compare_operand (tree t1, tree t2, operand_access_type access)
     403              : {
     404      2516709 :   if (!t1 && !t2)
     405              :     return true;
     406      2099001 :   else if (!t1 || !t2)
     407              :     return false;
     408      2099001 :   if (access == OP_MEMORY)
     409              :     {
     410       175663 :       ao_ref ref1, ref2;
     411       175663 :       ao_ref_init (&ref1, const_cast <tree> (t1));
     412       175663 :       ao_ref_init (&ref2, const_cast <tree> (t2));
     413       351326 :       int flags = compare_ao_refs (&ref1, &ref2,
     414       175663 :                                    lto_streaming_expected_p (), m_tbaa);
     415              : 
     416       175663 :       if (!flags)
     417              :         {
     418       173502 :           if (!safe_for_total_scalarization_p (t1, t2))
     419            3 :             return return_false_with_msg
     420              :               ("total scalarization may not be equivalent");
     421              :           return true;
     422              :         }
     423         2161 :       if (flags & SEMANTICS)
     424          423 :         return return_false_with_msg
     425              :                 ("compare_ao_refs failed (semantic difference)");
     426         1738 :       if (flags & BASE_ALIAS_SET)
     427           22 :         return return_false_with_msg
     428              :                 ("compare_ao_refs failed (base alias set difference)");
     429         1716 :       if (flags & REF_ALIAS_SET)
     430            0 :         return return_false_with_msg
     431              :                  ("compare_ao_refs failed (ref alias set difference)");
     432         1716 :       if (flags & ACCESS_PATH)
     433         1636 :         return return_false_with_msg
     434              :                  ("compare_ao_refs failed (access path difference)");
     435           80 :       if (flags & DEPENDENCE_CLIQUE)
     436           80 :         return return_false_with_msg
     437              :                  ("compare_ao_refs failed (dependence clique difference)");
     438            0 :       gcc_unreachable ();
     439              :     }
     440              :   else
     441              :     {
     442      1923338 :       if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
     443              :         return true;
     444          288 :       return return_false_with_msg
     445              :                  ("operand_equal_p failed");
     446              :     }
     447              : }
     448              : 
     449              : bool
     450          919 : func_checker::compare_asm_inputs_outputs (tree t1, tree t2,
     451              :                                           operand_access_type_map *map)
     452              : {
     453          919 :   gcc_assert (TREE_CODE (t1) == TREE_LIST);
     454          919 :   gcc_assert (TREE_CODE (t2) == TREE_LIST);
     455              : 
     456         1809 :   for (; t1; t1 = TREE_CHAIN (t1))
     457              :     {
     458          919 :       if (!t2)
     459              :         return false;
     460              : 
     461          919 :       if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2),
     462              :                             get_operand_access_type (map, t1))
     463         1834 :           || !types_compatible_p (TREE_TYPE (TREE_VALUE (t1)),
     464          915 :                                   TREE_TYPE (TREE_VALUE (t2))))
     465            6 :         return return_false ();
     466              : 
     467          913 :       tree p1 = TREE_PURPOSE (t1);
     468          913 :       tree p2 = TREE_PURPOSE (t2);
     469              : 
     470          913 :       gcc_assert (TREE_CODE (p1) == TREE_LIST);
     471          913 :       gcc_assert (TREE_CODE (p2) == TREE_LIST);
     472              : 
     473          913 :       if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1)),
     474          913 :                   TREE_STRING_POINTER (TREE_VALUE (p2))) != 0)
     475           23 :         return return_false ();
     476              : 
     477          890 :       t2 = TREE_CHAIN (t2);
     478              :     }
     479              : 
     480          890 :   if (t2)
     481            0 :     return return_false ();
     482              : 
     483              :   return true;
     484              : }
     485              : 
     486              : /* Verifies that trees T1 and T2 do correspond.  */
     487              : 
     488              : bool
     489       468445 : func_checker::compare_variable_decl (const_tree t1, const_tree t2)
     490              : {
     491       468445 :   bool ret = false;
     492              : 
     493       468445 :   if (t1 == t2)
     494              :     return true;
     495              : 
     496        76975 :   if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
     497            6 :     return return_false_with_msg ("alignments are different");
     498              : 
     499        76969 :   if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
     500            0 :     return return_false_with_msg ("DECL_HARD_REGISTER are different");
     501              : 
     502        76969 :   if (DECL_HARD_REGISTER (t1)
     503        76969 :       && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2))
     504            8 :     return return_false_with_msg ("HARD REGISTERS are different");
     505              : 
     506              :   /* Symbol table variables are known to match before we start comparing
     507              :      bodies.  */
     508        76961 :   if (decl_in_symtab_p (t1))
     509           18 :     return decl_in_symtab_p (t2);
     510        76943 :   ret = compare_decl (t1, t2);
     511              : 
     512        76943 :   return return_with_debug (ret);
     513              : }
     514              : 
     515              : /* Compare loop information for basic blocks BB1 and BB2.  */
     516              : 
     517              : bool
     518       391645 : func_checker::compare_loops (basic_block bb1, basic_block bb2)
     519              : {
     520       391645 :   if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
     521            0 :     return return_false ();
     522              : 
     523       391645 :   class loop *l1 = bb1->loop_father;
     524       391645 :   class loop *l2 = bb2->loop_father;
     525       391645 :   if (l1 == NULL)
     526              :     return true;
     527              : 
     528       391645 :   if ((bb1 == l1->header) != (bb2 == l2->header))
     529            0 :     return return_false_with_msg ("header");
     530       391645 :   if ((bb1 == l1->latch) != (bb2 == l2->latch))
     531            0 :     return return_false_with_msg ("latch");
     532       391645 :   if (l1->simdlen != l2->simdlen)
     533            5 :     return return_false_with_msg ("simdlen");
     534       391640 :   if (l1->safelen != l2->safelen)
     535           10 :     return return_false_with_msg ("safelen");
     536       391630 :   if (l1->can_be_parallel != l2->can_be_parallel)
     537            0 :     return return_false_with_msg ("can_be_parallel");
     538       391630 :   if (l1->dont_vectorize != l2->dont_vectorize)
     539          149 :     return return_false_with_msg ("dont_vectorize");
     540       391481 :   if (l1->force_vectorize != l2->force_vectorize)
     541            0 :     return return_false_with_msg ("force_vectorize");
     542       391481 :   if (l1->finite_p != l2->finite_p)
     543            3 :     return return_false_with_msg ("finite_p");
     544       391478 :   if (l1->unroll != l2->unroll)
     545            0 :     return return_false_with_msg ("unroll");
     546       391478 :   if (!compare_variable_decl (l1->simduid, l2->simduid))
     547            0 :     return return_false_with_msg ("simduid");
     548       391478 :   if ((l1->any_upper_bound != l2->any_upper_bound)
     549       391478 :       || (l1->any_upper_bound
     550         8701 :           && (l1->nb_iterations_upper_bound != l2->nb_iterations_upper_bound)))
     551           13 :     return return_false_with_msg ("nb_iterations_upper_bound");
     552              : 
     553              :   return true;
     554              : }
     555              : 
     556              : /* Function visits all gimple labels and creates corresponding
     557              :    mapping between basic blocks and labels.  */
     558              : 
     559              : void
     560      1148098 : func_checker::parse_labels (sem_bb *bb)
     561              : {
     562      6817826 :   for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
     563      4521630 :        gsi_next (&gsi))
     564              :     {
     565      4521630 :       gimple *stmt = gsi_stmt (gsi);
     566              : 
     567      4542476 :       if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
     568              :         {
     569        20846 :           const_tree t = gimple_label_label (label_stmt);
     570        20846 :           gcc_assert (TREE_CODE (t) == LABEL_DECL);
     571              : 
     572        20846 :           m_label_bb_map.put (t, bb->bb->index);
     573              :         }
     574              :     }
     575      1148098 : }
     576              : 
     577              : /* Basic block equivalence comparison function that returns true if
     578              :    basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
     579              : 
     580              :    In general, a collection of equivalence dictionaries is built for types
     581              :    like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
     582              :    is utilized by every statement-by-statement comparison function.  */
     583              : 
     584              : bool
     585       430256 : func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
     586              : {
     587       430256 :   gimple_stmt_iterator gsi1, gsi2;
     588       430256 :   gimple *s1, *s2;
     589              : 
     590       430256 :   gsi1 = gsi_start_nondebug_bb (bb1->bb);
     591       430256 :   gsi2 = gsi_start_nondebug_bb (bb2->bb);
     592              : 
     593      1337782 :   while (!gsi_end_p (gsi1))
     594              :     {
     595       946137 :       if (gsi_end_p (gsi2))
     596            0 :         return return_false ();
     597              : 
     598       946137 :       s1 = gsi_stmt (gsi1);
     599       946137 :       s2 = gsi_stmt (gsi2);
     600              : 
     601       946137 :       int eh1 = lookup_stmt_eh_lp_fn
     602       946137 :                 (DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
     603       946137 :       int eh2 = lookup_stmt_eh_lp_fn
     604       946137 :                 (DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
     605              : 
     606       946137 :       if (eh1 != eh2)
     607            3 :         return return_false_with_msg ("EH regions are different");
     608              : 
     609       946134 :       if (gimple_code (s1) != gimple_code (s2))
     610            0 :         return return_false_with_msg ("gimple codes are different");
     611              : 
     612       946134 :       switch (gimple_code (s1))
     613              :         {
     614       247310 :         case GIMPLE_CALL:
     615       247310 :           if (!compare_gimple_call (as_a <gcall *> (s1),
     616              :                                     as_a <gcall *> (s2)))
     617        32538 :             return return_different_stmts (s1, s2, "GIMPLE_CALL");
     618              :           break;
     619       417014 :         case GIMPLE_ASSIGN:
     620       417014 :           if (!compare_gimple_assign (s1, s2))
     621         3571 :             return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
     622              :           break;
     623       116263 :         case GIMPLE_COND:
     624       116263 :           if (!compare_gimple_cond (s1, s2))
     625         2392 :             return return_different_stmts (s1, s2, "GIMPLE_COND");
     626              :           break;
     627          428 :         case GIMPLE_SWITCH:
     628          428 :           if (!compare_gimple_switch (as_a <gswitch *> (s1),
     629          428 :                                       as_a <gswitch *> (s2)))
     630            2 :             return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
     631              :           break;
     632              :         case GIMPLE_DEBUG:
     633              :           break;
     634          395 :         case GIMPLE_EH_DISPATCH:
     635          395 :           if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
     636          395 :               != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
     637            0 :             return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
     638              :           break;
     639         4185 :         case GIMPLE_RESX:
     640         4185 :           if (!compare_gimple_resx (as_a <gresx *> (s1),
     641         4185 :                                     as_a <gresx *> (s2)))
     642            0 :             return return_different_stmts (s1, s2, "GIMPLE_RESX");
     643              :           break;
     644         9084 :         case GIMPLE_LABEL:
     645         9084 :           if (!compare_gimple_label (as_a <glabel *> (s1),
     646         9084 :                                      as_a <glabel *> (s2)))
     647           10 :             return return_different_stmts (s1, s2, "GIMPLE_LABEL");
     648              :           break;
     649       145503 :         case GIMPLE_RETURN:
     650       145503 :           if (!compare_gimple_return (as_a <greturn *> (s1),
     651       145503 :                                       as_a <greturn *> (s2)))
     652           36 :             return return_different_stmts (s1, s2, "GIMPLE_RETURN");
     653              :           break;
     654            0 :         case GIMPLE_GOTO:
     655            0 :           if (!compare_gimple_goto (s1, s2))
     656            0 :             return return_different_stmts (s1, s2, "GIMPLE_GOTO");
     657              :           break;
     658         5409 :         case GIMPLE_ASM:
     659         5409 :           if (!compare_gimple_asm (as_a <gasm *> (s1),
     660         5409 :                                    as_a <gasm *> (s2)))
     661           59 :             return return_different_stmts (s1, s2, "GIMPLE_ASM");
     662              :           break;
     663              :         case GIMPLE_PREDICT:
     664              :         case GIMPLE_NOP:
     665              :           break;
     666            0 :         default:
     667            0 :           return return_false_with_msg ("Unknown GIMPLE code reached");
     668              :         }
     669              : 
     670       907526 :       gsi_next_nondebug (&gsi1);
     671       907526 :       gsi_next_nondebug (&gsi2);
     672              :     }
     673              : 
     674       391645 :   if (!gsi_end_p (gsi2))
     675            0 :     return return_false ();
     676              : 
     677       391645 :   if (!compare_loops (bb1->bb, bb2->bb))
     678          180 :     return return_false ();
     679              : 
     680              :   return true;
     681              : }
     682              : 
     683              : /* Verifies for given GIMPLEs S1 and S2 that
     684              :    call statements are semantically equivalent.  */
     685              : 
     686              : bool
     687       247310 : func_checker::compare_gimple_call (gcall *s1, gcall *s2)
     688              : {
     689       247310 :   unsigned i;
     690       247310 :   tree t1, t2;
     691              : 
     692       247310 :   if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
     693              :     return false;
     694              : 
     695       247310 :   operand_access_type_map map (5);
     696       247310 :   classify_operands (s1, &map);
     697              : 
     698       247310 :   t1 = gimple_call_fn (s1);
     699       247310 :   t2 = gimple_call_fn (s2);
     700       247310 :   if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     701            0 :     return return_false ();
     702              : 
     703              :   /* Compare flags.  */
     704       247310 :   if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
     705       247310 :       || gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
     706       247310 :       || gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
     707       247310 :       || gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
     708       247310 :       || gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
     709       247310 :       || gimple_call_from_new_or_delete (s1) != gimple_call_from_new_or_delete (s2)
     710       247310 :       || gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
     711       247310 :       || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2)
     712       494620 :       || gimple_call_must_tail_p (s1) != gimple_call_must_tail_p (s2))
     713              :     return false;
     714              : 
     715       247302 :   unsigned check_arg_types_from = 0;
     716       247302 :   if (gimple_call_internal_p (s1))
     717              :     {
     718        86479 :       if (gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
     719              :         return false;
     720              :     }
     721              :   else
     722              :     {
     723       160823 :       tree fntype1 = gimple_call_fntype (s1);
     724       160823 :       tree fntype2 = gimple_call_fntype (s2);
     725       160823 :       if (!types_compatible_p (fntype1, fntype2))
     726         1041 :         return return_false_with_msg ("call function types are not compatible");
     727              : 
     728       159782 :       if (comp_type_attributes (fntype1, fntype2) != 1)
     729            0 :         return return_false_with_msg ("different fntype attributes");
     730              : 
     731       159782 :       check_arg_types_from = gimple_call_num_args (s1);
     732       159782 :       if (!prototype_p (fntype1) || !prototype_p (fntype2))
     733              :         check_arg_types_from = 0;
     734       159427 :       else if (stdarg_p (fntype1))
     735              :         {
     736         3138 :           check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype1));
     737         3138 :           if (stdarg_p (fntype2))
     738              :             {
     739         3138 :               unsigned n = list_length (TYPE_ARG_TYPES (fntype2));
     740         3138 :               check_arg_types_from = MIN (check_arg_types_from, n);
     741              :             }
     742              :         }
     743       156289 :       else if (stdarg_p (fntype2))
     744            0 :         check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype2));
     745              :     }
     746              : 
     747       218394 :   tree chain1 = gimple_call_chain (s1);
     748       218394 :   tree chain2 = gimple_call_chain (s2);
     749       218394 :   if ((chain1 && !chain2)
     750       218394 :       || (!chain1 && chain2)
     751       218394 :       || !compare_operand (chain1, chain2,
     752              :                            get_operand_access_type (&map, chain1)))
     753            0 :     return return_false_with_msg ("static call chains are different");
     754              : 
     755              :   /* Checking of argument.  */
     756       497468 :   for (i = 0; i < gimple_call_num_args (s1); ++i)
     757              :     {
     758       280064 :       t1 = gimple_call_arg (s1, i);
     759       280064 :       t2 = gimple_call_arg (s2, i);
     760              : 
     761       280064 :       if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     762          153 :         return return_false_with_msg ("GIMPLE call operands are different");
     763       279911 :       if (i >= check_arg_types_from
     764       279911 :           && !types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     765          837 :         return return_false_with_msg ("GIMPLE call operand types are "
     766              :                                       "different");
     767              :     }
     768              : 
     769              :   /* Return value checking.  */
     770       217404 :   t1 = gimple_get_lhs (s1);
     771       217404 :   t2 = gimple_get_lhs (s2);
     772              : 
     773              :   /* For internal calls, lhs types need to be verified, as neither fntype nor
     774              :      callee comparisons can catch that.  */
     775       217404 :   if (gimple_call_internal_p (s1)
     776        57992 :       && t1
     777        57992 :       && t2
     778       275063 :       && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     779         2610 :     return return_false_with_msg ("GIMPLE internal call LHS type mismatch");
     780              : 
     781       214794 :   if (!gimple_call_internal_p (s1))
     782              :     {
     783       159412 :       cgraph_edge *e1 = cgraph_node::get (m_source_func_decl)->get_edge (s1);
     784       159412 :       cgraph_edge *e2 = cgraph_node::get (m_target_func_decl)->get_edge (s2);
     785       159412 :       class ipa_edge_args *args1 = ipa_edge_args_sum->get (e1);
     786       159412 :       class ipa_edge_args *args2 = ipa_edge_args_sum->get (e2);
     787       159412 :       if ((args1 != nullptr) != (args2 != nullptr))
     788            0 :         return return_false_with_msg ("ipa_edge_args mismatch");
     789       159412 :       if (args1)
     790              :         {
     791       106303 :           int n1 = ipa_get_cs_argument_count (args1);
     792       106303 :           int n2 = ipa_get_cs_argument_count (args2);
     793       106303 :           if (n1 != n2)
     794            0 :             return return_false_with_msg ("ipa_edge_args nargs mismatch");
     795       226181 :           for (int i = 0; i < n1; i++)
     796              :             {
     797       119894 :               struct ipa_jump_func *jf1 = ipa_get_ith_jump_func (args1, i);
     798       119894 :               struct ipa_jump_func *jf2 = ipa_get_ith_jump_func (args2, i);
     799       119894 :               if (((jf1 != nullptr) != (jf2 != nullptr))
     800       119894 :                   || (jf1 && !ipa_jump_functions_equivalent_p (jf1, jf2)))
     801           16 :                 return return_false_with_msg ("jump function mismatch");
     802              :             }
     803              :         }
     804              :     }
     805              : 
     806       214778 :   return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     807       247310 : }
     808              : 
     809              : 
     810              : /* Verifies for given GIMPLEs S1 and S2 that
     811              :    assignment statements are semantically equivalent.  */
     812              : 
     813              : bool
     814       417014 : func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
     815              : {
     816       417014 :   tree arg1, arg2;
     817       417014 :   tree_code code1, code2;
     818       417014 :   unsigned i;
     819              : 
     820       417014 :   code1 = gimple_assign_rhs_code (s1);
     821       417014 :   code2 = gimple_assign_rhs_code (s2);
     822              : 
     823       417014 :   if (code1 != code2)
     824              :     return false;
     825              : 
     826       417014 :   operand_access_type_map map (5);
     827       417014 :   classify_operands (s1, &map);
     828              : 
     829      1749766 :   for (i = 0; i < gimple_num_ops (s1); i++)
     830              :     {
     831       919309 :       arg1 = gimple_op (s1, i);
     832       919309 :       arg2 = gimple_op (s2, i);
     833              : 
     834              :       /* Compare types for LHS.  */
     835       919309 :       if (i == 0 && !gimple_store_p (s1))
     836              :         {
     837       335066 :           if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
     838         1358 :             return return_false_with_msg ("GIMPLE LHS type mismatch");
     839              :         }
     840              : 
     841       917951 :       if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1)))
     842         2213 :         return return_false_with_msg ("GIMPLE assignment operands "
     843              :                                       "are different");
     844              :     }
     845              : 
     846              : 
     847              :   return true;
     848       417014 : }
     849              : 
     850              : /* Verifies for given GIMPLEs S1 and S2 that
     851              :    condition statements are semantically equivalent.  */
     852              : 
     853              : bool
     854       116263 : func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
     855              : {
     856       116263 :   tree t1, t2;
     857       116263 :   tree_code code1, code2;
     858              : 
     859       116263 :   code1 = gimple_cond_code (s1);
     860       116263 :   code2 = gimple_cond_code (s2);
     861              : 
     862       116263 :   if (code1 != code2)
     863              :     return false;
     864              : 
     865       113878 :   t1 = gimple_cond_lhs (s1);
     866       113878 :   t2 = gimple_cond_lhs (s2);
     867              : 
     868       113878 :   if (!compare_operand (t1, t2, OP_NORMAL))
     869              :     return false;
     870              : 
     871       113871 :   t1 = gimple_cond_rhs (s1);
     872       113871 :   t2 = gimple_cond_rhs (s2);
     873              : 
     874       113871 :   return compare_operand (t1, t2, OP_NORMAL);
     875              : }
     876              : 
     877              : /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
     878              :    label statements are semantically equivalent.  */
     879              : 
     880              : bool
     881         9084 : func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
     882              : {
     883         9084 :   if (m_ignore_labels)
     884              :     return true;
     885              : 
     886         9084 :   tree t1 = gimple_label_label (g1);
     887         9084 :   tree t2 = gimple_label_label (g2);
     888              : 
     889        18158 :   if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
     890           10 :     return return_false_with_msg ("FORCED_LABEL");
     891              : 
     892              :   /* As the pass build BB to label mapping, no further check is needed.  */
     893              :   return true;
     894              : }
     895              : 
     896              : /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
     897              :    switch statements are semantically equivalent.  */
     898              : 
     899              : bool
     900          428 : func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
     901              : {
     902          428 :   unsigned lsize1, lsize2, i;
     903              : 
     904          428 :   lsize1 = gimple_switch_num_labels (g1);
     905          428 :   lsize2 = gimple_switch_num_labels (g2);
     906              : 
     907          428 :   if (lsize1 != lsize2)
     908              :     return false;
     909              : 
     910          427 :   tree t1 = gimple_switch_index (g1);
     911          427 :   tree t2 = gimple_switch_index (g2);
     912              : 
     913          427 :   if (!compare_operand (t1, t2, OP_NORMAL))
     914              :     return false;
     915              : 
     916         4210 :   for (i = 0; i < lsize1; i++)
     917              :     {
     918         3784 :       tree label1 = gimple_switch_label (g1, i);
     919         3784 :       tree label2 = gimple_switch_label (g2, i);
     920              : 
     921              :       /* Label LOW and HIGH comparison.  */
     922         3784 :       tree low1 = CASE_LOW (label1);
     923         3784 :       tree low2 = CASE_LOW (label2);
     924              : 
     925         3784 :       if (!tree_int_cst_equal (low1, low2))
     926            1 :         return return_false_with_msg ("case low values are different");
     927              : 
     928         3783 :       tree high1 = CASE_HIGH (label1);
     929         3783 :       tree high2 = CASE_HIGH (label2);
     930              : 
     931         3783 :       if (!tree_int_cst_equal (high1, high2))
     932            0 :         return return_false_with_msg ("case high values are different");
     933              : 
     934         3783 :       if (!compare_operand (CASE_LABEL (label1), CASE_LABEL (label2), OP_NORMAL))
     935            0 :         return return_false_with_msg ("switch label_exprs are different");
     936              :     }
     937              : 
     938              :   return true;
     939              : }
     940              : 
     941              : /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
     942              :    return statements are semantically equivalent.  */
     943              : 
     944              : bool
     945       145503 : func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
     946              : {
     947       145503 :   tree t1, t2;
     948              : 
     949       145503 :   t1 = gimple_return_retval (g1);
     950       145503 :   t2 = gimple_return_retval (g2);
     951              : 
     952              :   /* Void return type.  */
     953       145503 :   if (t1 == NULL && t2 == NULL)
     954              :     return true;
     955              :   else
     956              :     {
     957        81391 :       operand_access_type_map map (3);
     958        81391 :       return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     959        81391 :     }
     960              : }
     961              : 
     962              : /* Verifies for given GIMPLEs S1 and S2 that
     963              :    goto statements are semantically equivalent.  */
     964              : 
     965              : bool
     966            0 : func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
     967              : {
     968            0 :   tree dest1, dest2;
     969              : 
     970            0 :   dest1 = gimple_goto_dest (g1);
     971            0 :   dest2 = gimple_goto_dest (g2);
     972              : 
     973            0 :   if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
     974              :     return false;
     975              : 
     976            0 :   return compare_operand (dest1, dest2, OP_NORMAL);
     977              : }
     978              : 
     979              : /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
     980              :    resx statements are semantically equivalent.  */
     981              : 
     982              : bool
     983         4185 : func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
     984              : {
     985         4185 :   return gimple_resx_region (g1) == gimple_resx_region (g2);
     986              : }
     987              : 
     988              : /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
     989              :    For the beginning, the pass only supports equality for
     990              :    '__asm__ __volatile__ ("", "", "", "memory")'.  */
     991              : 
     992              : bool
     993         5409 : func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
     994              : {
     995         5409 :   if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
     996              :     return false;
     997              : 
     998         5409 :   if (gimple_asm_basic_p (g1) != gimple_asm_basic_p (g2))
     999              :     return false;
    1000              : 
    1001         5409 :   if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
    1002              :     return false;
    1003              : 
    1004         5409 :   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
    1005              :     return false;
    1006              : 
    1007         5408 :   if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
    1008              :     return false;
    1009              : 
    1010              :   /* We do not suppport goto ASM statement comparison.  */
    1011         5408 :   if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
    1012              :     return false;
    1013              : 
    1014         5384 :   if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
    1015              :     return false;
    1016              : 
    1017         5384 :   if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
    1018            5 :     return return_false_with_msg ("ASM strings are different");
    1019              : 
    1020         5379 :   operand_access_type_map map (5);
    1021         5379 :   classify_operands (g1, &map);
    1022              : 
    1023         5765 :   for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
    1024              :     {
    1025          413 :       tree input1 = gimple_asm_input_op (g1, i);
    1026          413 :       tree input2 = gimple_asm_input_op (g2, i);
    1027              : 
    1028          413 :       if (!compare_asm_inputs_outputs (input1, input2, &map))
    1029           27 :         return return_false_with_msg ("ASM input is different");
    1030              :     }
    1031              : 
    1032         5856 :   for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
    1033              :     {
    1034          506 :       tree output1 = gimple_asm_output_op (g1, i);
    1035          506 :       tree output2 = gimple_asm_output_op (g2, i);
    1036              : 
    1037          506 :       if (!compare_asm_inputs_outputs (output1, output2, &map))
    1038            2 :         return return_false_with_msg ("ASM output is different");
    1039              :     }
    1040              : 
    1041        18224 :   for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
    1042              :     {
    1043        12874 :       tree clobber1 = gimple_asm_clobber_op (g1, i);
    1044        12874 :       tree clobber2 = gimple_asm_clobber_op (g2, i);
    1045              : 
    1046        12874 :       if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
    1047              :                             OEP_ONLY_CONST))
    1048            0 :         return return_false_with_msg ("ASM clobber is different");
    1049              :     }
    1050              : 
    1051              :   return true;
    1052         5379 : }
    1053              : 
    1054              : /* Helper for func_checker::classify_operands.  Record that T is a load.  */
    1055              : 
    1056              : static bool
    1057      8231535 : visit_load_store (gimple *, tree, tree t, void *data)
    1058              : {
    1059      8231535 :   func_checker::operand_access_type_map *map =
    1060              :     (func_checker::operand_access_type_map *) data;
    1061      8231535 :   map->add (t);
    1062      8231535 :   return false;
    1063              : }
    1064              : 
    1065              : /* Compute hash map determining access types of operands.  */
    1066              : 
    1067              : void
    1068     21099029 : func_checker::classify_operands (const gimple *stmt,
    1069              :                                  operand_access_type_map *map)
    1070              : {
    1071     21099029 :   walk_stmt_load_store_ops (const_cast <gimple *> (stmt),
    1072              :                             (void *)map, visit_load_store, visit_load_store);
    1073     21099029 : }
    1074              : 
    1075              : /* Return access type of a given operand.  */
    1076              : 
    1077              : func_checker::operand_access_type
    1078     63140260 : func_checker::get_operand_access_type (operand_access_type_map *map, tree t)
    1079              : {
    1080     63140260 :   if (map->contains (t))
    1081      8220415 :     return OP_MEMORY;
    1082              :   return OP_NORMAL;
    1083              : }
    1084              : 
    1085              : } // ipa_icf_gimple namespace
        

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.