LCOV - code coverage report
Current view: top level - gcc - ipa-icf-gimple.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.2 % 520 474
Test Date: 2026-09-19 16:22:48 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       127551 : 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              :                             hash_set<symtab_node *> *ignored_target_nodes)
      65       127551 :   : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
      66       127551 :     m_ignored_source_nodes (ignored_source_nodes),
      67       127551 :     m_ignored_target_nodes (ignored_target_nodes),
      68       127551 :     m_ignore_labels (ignore_labels), m_tbaa (tbaa),
      69       127551 :     m_total_scalarization_limit_known_p (false)
      70              : {
      71       127551 :   function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
      72       127551 :   function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
      73              : 
      74       127551 :   unsigned ssa_source = SSANAMES (source_func)->length ();
      75       127551 :   unsigned ssa_target = SSANAMES (target_func)->length ();
      76              : 
      77       127551 :   m_source_ssa_names.create (ssa_source);
      78       127551 :   m_target_ssa_names.create (ssa_target);
      79              : 
      80      1245160 :   for (unsigned i = 0; i < ssa_source; i++)
      81       990058 :     m_source_ssa_names.safe_push (-1);
      82              : 
      83      1117222 :   for (unsigned i = 0; i < ssa_target; i++)
      84       989671 :     m_target_ssa_names.safe_push (-1);
      85       127551 : }
      86              : 
      87              : /* Memory release routine.  */
      88              : 
      89       514585 : func_checker::~func_checker ()
      90              : {
      91       387034 :   m_source_ssa_names.release();
      92       387034 :   m_target_ssa_names.release();
      93       514585 : }
      94              : 
      95              : /* Verifies that trees T1 and T2 are equivalent from perspective of ICF.  */
      96              : 
      97              : bool
      98      1059028 : func_checker::compare_ssa_name (const_tree t1, const_tree t2)
      99              : {
     100      1059028 :   gcc_assert (TREE_CODE (t1) == SSA_NAME);
     101      1059028 :   gcc_assert (TREE_CODE (t2) == SSA_NAME);
     102              : 
     103      1059028 :   unsigned i1 = SSA_NAME_VERSION (t1);
     104      1059028 :   unsigned i2 = SSA_NAME_VERSION (t2);
     105              : 
     106      1059028 :   if (SSA_NAME_IS_DEFAULT_DEF (t1) != SSA_NAME_IS_DEFAULT_DEF (t2))
     107              :     return false;
     108              : 
     109      1059028 :   if (m_source_ssa_names[i1] == -1)
     110       336116 :     m_source_ssa_names[i1] = i2;
     111       722912 :   else if (m_source_ssa_names[i1] != (int) i2)
     112              :     return false;
     113              : 
     114      1058835 :   if(m_target_ssa_names[i2] == -1)
     115       336112 :     m_target_ssa_names[i2] = i1;
     116       722723 :   else if (m_target_ssa_names[i2] != (int) i1)
     117              :     return false;
     118              : 
     119      1058831 :   if (SSA_NAME_IS_DEFAULT_DEF (t1))
     120              :     {
     121       214714 :       tree b1 = SSA_NAME_VAR (t1);
     122       214714 :       tree b2 = SSA_NAME_VAR (t2);
     123              : 
     124       214714 :       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       464595 : func_checker::compare_edge (edge e1, edge e2)
     134              : {
     135       464595 :   if (e1->flags != e2->flags)
     136              :     return false;
     137              : 
     138       464595 :   bool existed_p;
     139              : 
     140       464595 :   edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
     141       464595 :   if (existed_p)
     142       206339 :     return return_with_debug (slot == e2);
     143              :   else
     144       258256 :     slot = e2;
     145              : 
     146              :   /* TODO: filter edge probabilities for profile feedback match.  */
     147              : 
     148       258256 :   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       422391 : func_checker::compare_decl (const_tree t1, const_tree t2)
     156              : {
     157       422391 :   if (!auto_var_in_fn_p (t1, m_source_func_decl)
     158       422391 :       || !auto_var_in_fn_p (t2, m_target_func_decl))
     159            8 :     return return_with_debug (t1 == t2);
     160              : 
     161       422383 :   tree_code t = TREE_CODE (t1);
     162       422383 :   if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
     163       422383 :       && 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 conventions).  */
     170       422383 :   if (t != VAR_DECL)
     171              :     {
     172       393439 :       if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     173            0 :         return return_false ();
     174              :     }
     175              :   else
     176              :     {
     177        28944 :       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       422383 :   bool existed_p;
     183       422383 :   const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
     184       422383 :   if (existed_p)
     185       244457 :     return return_with_debug (slot == t2);
     186              :   else
     187       177926 :     slot = t2;
     188              : 
     189       177926 :   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        15188 : func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
     198              :                                               bool compare_ptr)
     199              : {
     200        15188 :   gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
     201              : 
     202              :   /* Pointer types generally give no information.  */
     203        15188 :   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        15188 :   bool c1 = contains_polymorphic_type_p (t1);
     214        15188 :   bool c2 = contains_polymorphic_type_p (t2);
     215        15188 :   if (!c1 && !c2)
     216              :     return true;
     217          768 :   if (!c1 || !c2)
     218            0 :     return return_false_with_msg ("one type is not polymorphic");
     219          768 :   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      4356289 : func_checker::compatible_types_p (tree t1, tree t2)
     227              : {
     228      4356289 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     229       132169 :     return return_false_with_msg ("different tree types");
     230              : 
     231      4224120 :   if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
     232          134 :     return return_false_with_msg ("restrict flags are different");
     233              : 
     234      4223986 :   if (!types_compatible_p (t1, t2))
     235       960695 :     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 access type is OP_NORMAL.  */
     242              : 
     243              : void
     244    134622140 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     245              :                             unsigned int flags)
     246              : {
     247    139575584 :   if (arg == NULL_TREE)
     248              :     {
     249     15917805 :       hstate.merge_hash (0);
     250     15917805 :       return;
     251              :     }
     252              : 
     253    123657779 :   switch (TREE_CODE (arg))
     254              :     {
     255      5523793 :     case PARM_DECL:
     256      5523793 :       {
     257      5523793 :         unsigned int index = 0;
     258      5523793 :         if (DECL_CONTEXT (arg))
     259      5523793 :           for (tree p = DECL_ARGUMENTS (DECL_CONTEXT (arg));
     260     11146464 :                p && index < 32; p = DECL_CHAIN (p), index++)
     261     11137172 :             if (p == arg)
     262              :               break;
     263      5523793 :         hstate.add_int (PARM_DECL);
     264      5523793 :         hstate.add_int (index);
     265              :       }
     266      5523793 :       return;
     267     14787394 :     case FUNCTION_DECL:
     268     14787394 :     case VAR_DECL:
     269     14787394 :     case LABEL_DECL:
     270     14787394 :     case RESULT_DECL:
     271     14787394 :     case CONST_DECL:
     272     14787394 :       hstate.add_int (TREE_CODE (arg));
     273     14787394 :       return;
     274     33795429 :     case SSA_NAME:
     275     33795429 :       hstate.add_int (SSA_NAME);
     276     33795429 :       if (SSA_NAME_IS_DEFAULT_DEF (arg))
     277      4953444 :         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     69550926 :     default:
     284     69550926 :       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     69550926 :   if (TREE_CLOBBER_P (arg))
     290              :     {
     291      1230055 :       hstate.add_int (0xc10bbe5);
     292      1230055 :       return;
     293              :     }
     294     68320871 :   gcc_assert (!DECL_P (arg));
     295     68320871 :   gcc_assert (!TYPE_P (arg));
     296              : 
     297     68320871 :   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     67312549 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     305              :                             unsigned int flags, operand_access_type access)
     306              : {
     307     67312549 :   if (access == OP_MEMORY)
     308              :     {
     309      8447130 :       ao_ref ref;
     310      8447130 :       ao_ref_init (&ref, const_cast <tree> (arg));
     311      8447130 :       return hash_ao_ref (&ref, lto_streaming_expected_p (), m_tbaa, hstate);
     312              :     }
     313              :   else
     314     58865419 :     return hash_operand (arg, hstate, flags);
     315              : }
     316              : 
     317              : bool
     318      4020978 : func_checker::operand_equal_p (const_tree t1, const_tree t2,
     319              :                                unsigned int flags)
     320              : {
     321      4020978 :   bool r;
     322      4020978 :   if (verify_hash_value (t1, t2, flags, &r))
     323      1740251 :     return r;
     324              : 
     325      2280727 :   if (t1 == t2)
     326              :     return true;
     327      1726969 :   else if (!t1 || !t2)
     328              :     return false;
     329              : 
     330      1726969 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     331            3 :     return return_false ();
     332              : 
     333      1726966 :   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        28968 :     case VAR_DECL:
     340        28968 :       return return_with_debug (compare_variable_decl (t1, t2));
     341         1276 :     case LABEL_DECL:
     342         1276 :       {
     343         1276 :         int *bb1 = m_label_bb_map.get (t1);
     344         1276 :         int *bb2 = m_label_bb_map.get (t2);
     345              :         /* Labels can point to another function (non-local GOTOs).  */
     346         1281 :         return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
     347              :       }
     348              : 
     349       228035 :     case PARM_DECL:
     350       228035 :     case RESULT_DECL:
     351       228035 :     case CONST_DECL:
     352       228035 :       return compare_decl (t1, t2);
     353      1059028 :     case SSA_NAME:
     354      1059028 :       return compare_ssa_name (t1, t2);
     355       398472 :     default:
     356       398472 :       break;
     357              :     }
     358              :   /* In gimple all clobbers can be considered equal.  We match the left hand
     359              :      memory accesses.  */
     360       398472 :   if (TREE_CLOBBER_P (t1) || TREE_CLOBBER_P (t2))
     361         4955 :     return TREE_CLOBBER_P (t1) == TREE_CLOBBER_P (t2);
     362              : 
     363       393517 :   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       101396 : func_checker::safe_for_total_scalarization_p (tree t1, tree t2)
     371              : {
     372       101396 :   tree type1 = TREE_TYPE (t1);
     373       101396 :   tree type2 = TREE_TYPE (t2);
     374              : 
     375       101396 :   if (!AGGREGATE_TYPE_P (type1)
     376        13789 :       || !AGGREGATE_TYPE_P (type2)
     377        13789 :       || !tree_fits_uhwi_p (TYPE_SIZE (type1))
     378       115185 :       || !tree_fits_uhwi_p (TYPE_SIZE (type2)))
     379              :     return true;
     380              : 
     381        13789 :   if (!m_total_scalarization_limit_known_p)
     382              :     {
     383         3984 :       push_cfun (DECL_STRUCT_FUNCTION (m_target_func_decl));
     384         3984 :       m_total_scalarization_limit = sra_get_max_scalarization_size ();
     385         3984 :       pop_cfun ();
     386         3984 :       m_total_scalarization_limit_known_p = true;
     387              :     }
     388              : 
     389        13789 :   unsigned HOST_WIDE_INT sz = tree_to_uhwi (TYPE_SIZE (type1));
     390        13789 :   gcc_assert (sz == tree_to_uhwi (TYPE_SIZE (type2)));
     391        13789 :   if (sz > m_total_scalarization_limit)
     392              :     return true;
     393        13647 :   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      2072445 : func_checker::compare_operand (tree t1, tree t2, operand_access_type access)
     403              : {
     404      2072445 :   if (!t1 && !t2)
     405              :     return true;
     406      1709180 :   else if (!t1 || !t2)
     407              :     return false;
     408      1709180 :   if (access == OP_MEMORY)
     409              :     {
     410       103599 :       ao_ref ref1, ref2;
     411       103599 :       ao_ref_init (&ref1, const_cast <tree> (t1));
     412       103599 :       ao_ref_init (&ref2, const_cast <tree> (t2));
     413       103599 :       int flags = compare_ao_refs (&ref1, &ref2,
     414              :                                    lto_streaming_expected_p (), m_tbaa);
     415              : 
     416       103599 :       if (!flags)
     417              :         {
     418       101396 :           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         2203 :       if (flags & SEMANTICS)
     424          396 :         return return_false_with_msg
     425              :                 ("compare_ao_refs failed (semantic difference)");
     426         1807 :       if (flags & BASE_ALIAS_SET)
     427           22 :         return return_false_with_msg
     428              :                 ("compare_ao_refs failed (base alias set difference)");
     429         1785 :       if (flags & REF_ALIAS_SET)
     430            0 :         return return_false_with_msg
     431              :                  ("compare_ao_refs failed (ref alias set difference)");
     432         1785 :       if (flags & ACCESS_PATH)
     433         1706 :         return return_false_with_msg
     434              :                  ("compare_ao_refs failed (access path difference)");
     435           79 :       if (flags & DEPENDENCE_CLIQUE)
     436           79 :         return return_false_with_msg
     437              :                  ("compare_ao_refs failed (dependence clique difference)");
     438            0 :       gcc_unreachable ();
     439              :     }
     440              :   else
     441              :     {
     442      1605581 :       if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS
     443              :                                        | OEP_ADDRESS_OF_SAME_FIELD))
     444              :         return true;
     445         3058 :       return return_false_with_msg
     446              :                  ("operand_equal_p failed");
     447              :     }
     448              : }
     449              : 
     450              : bool
     451          915 : func_checker::compare_asm_inputs_outputs (tree t1, tree t2,
     452              :                                           operand_access_type_map *map)
     453              : {
     454          915 :   gcc_assert (TREE_CODE (t1) == TREE_LIST);
     455          915 :   gcc_assert (TREE_CODE (t2) == TREE_LIST);
     456              : 
     457         1801 :   for (; t1; t1 = TREE_CHAIN (t1))
     458              :     {
     459          915 :       if (!t2)
     460              :         return false;
     461              : 
     462          915 :       if (!compare_operand (TREE_VALUE (t1), TREE_VALUE (t2),
     463              :                             get_operand_access_type (map, t1))
     464         1826 :           || !types_compatible_p (TREE_TYPE (TREE_VALUE (t1)),
     465          911 :                                   TREE_TYPE (TREE_VALUE (t2))))
     466            6 :         return return_false ();
     467              : 
     468          909 :       tree p1 = TREE_PURPOSE (t1);
     469          909 :       tree p2 = TREE_PURPOSE (t2);
     470              : 
     471          909 :       gcc_assert (TREE_CODE (p1) == TREE_LIST);
     472          909 :       gcc_assert (TREE_CODE (p2) == TREE_LIST);
     473              : 
     474          909 :       if (strcmp (TREE_STRING_POINTER (TREE_VALUE (p1)),
     475          909 :                   TREE_STRING_POINTER (TREE_VALUE (p2))) != 0)
     476           23 :         return return_false ();
     477              : 
     478          886 :       t2 = TREE_CHAIN (t2);
     479              :     }
     480              : 
     481          886 :   if (t2)
     482            0 :     return return_false ();
     483              : 
     484              :   return true;
     485              : }
     486              : 
     487              : /* Verifies that trees T1 and T2 do correspond.  */
     488              : 
     489              : bool
     490       376355 : func_checker::compare_variable_decl (const_tree t1, const_tree t2)
     491              : {
     492       376355 :   bool ret = false;
     493              : 
     494       376355 :   if (t1 == t2)
     495              :     return true;
     496              : 
     497        28976 :   if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
     498            6 :     return return_false_with_msg ("alignments are different");
     499              : 
     500        28970 :   if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
     501            0 :     return return_false_with_msg ("DECL_HARD_REGISTER are different");
     502              : 
     503        28970 :   if (DECL_HARD_REGISTER (t1)
     504        28970 :       && DECL_ASSEMBLER_NAME_RAW (t1) != DECL_ASSEMBLER_NAME_RAW (t2))
     505            8 :     return return_false_with_msg ("HARD REGISTERS are different");
     506              : 
     507              :   /* Symbol table variables are known to match before we start comparing
     508              :      bodies.  */
     509        28962 :   if (decl_in_symtab_p (t1))
     510           18 :     return decl_in_symtab_p (t2);
     511        28944 :   ret = compare_decl (t1, t2);
     512              : 
     513        28944 :   return return_with_debug (ret);
     514              : }
     515              : 
     516              : /* Compare loop information for basic blocks BB1 and BB2.  */
     517              : 
     518              : bool
     519       347554 : func_checker::compare_loops (basic_block bb1, basic_block bb2)
     520              : {
     521       347554 :   if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
     522            0 :     return return_false ();
     523              : 
     524       347554 :   class loop *l1 = bb1->loop_father;
     525       347554 :   class loop *l2 = bb2->loop_father;
     526       347554 :   if (l1 == NULL)
     527              :     return true;
     528              : 
     529       347554 :   if ((bb1 == l1->header) != (bb2 == l2->header))
     530            0 :     return return_false_with_msg ("header");
     531       347554 :   if ((bb1 == l1->latch) != (bb2 == l2->latch))
     532            0 :     return return_false_with_msg ("latch");
     533       347554 :   if (l1->simdlen != l2->simdlen)
     534            5 :     return return_false_with_msg ("simdlen");
     535       347549 :   if (l1->safelen != l2->safelen)
     536           10 :     return return_false_with_msg ("safelen");
     537       347539 :   if (l1->can_be_parallel != l2->can_be_parallel)
     538            0 :     return return_false_with_msg ("can_be_parallel");
     539       347539 :   if (l1->dont_vectorize != l2->dont_vectorize)
     540          149 :     return return_false_with_msg ("dont_vectorize");
     541       347390 :   if (l1->force_vectorize != l2->force_vectorize)
     542            0 :     return return_false_with_msg ("force_vectorize");
     543       347390 :   if (l1->finite_p != l2->finite_p)
     544            3 :     return return_false_with_msg ("finite_p");
     545       347387 :   if (l1->unroll != l2->unroll)
     546            0 :     return return_false_with_msg ("unroll");
     547       347387 :   if (!compare_variable_decl (l1->simduid, l2->simduid))
     548            0 :     return return_false_with_msg ("simduid");
     549       347387 :   if ((l1->any_upper_bound != l2->any_upper_bound)
     550       347387 :       || (l1->any_upper_bound
     551         5516 :           && (l1->nb_iterations_upper_bound != l2->nb_iterations_upper_bound)))
     552            8 :     return return_false_with_msg ("nb_iterations_upper_bound");
     553              : 
     554              :   return true;
     555              : }
     556              : 
     557              : /* Function visits all gimple labels and creates corresponding
     558              :    mapping between basic blocks and labels.  */
     559              : 
     560              : void
     561      1195068 : func_checker::parse_labels (sem_bb *bb)
     562              : {
     563      7721576 :   for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
     564      5331440 :        gsi_next (&gsi))
     565              :     {
     566      5331440 :       gimple *stmt = gsi_stmt (gsi);
     567              : 
     568      5363434 :       if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
     569              :         {
     570        31994 :           const_tree t = gimple_label_label (label_stmt);
     571        31994 :           gcc_assert (TREE_CODE (t) == LABEL_DECL);
     572              : 
     573        31994 :           m_label_bb_map.put (t, bb->bb->index);
     574              :         }
     575              :     }
     576      1195068 : }
     577              : 
     578              : /* Basic block equivalence comparison function that returns true if
     579              :    basic blocks BB1 and BB2 (from functions FUNC1 and FUNC2) correspond.
     580              : 
     581              :    In general, a collection of equivalence dictionaries is built for types
     582              :    like SSA names, declarations (VAR_DECL, PARM_DECL, ..). This infrastructure
     583              :    is utilized by every statement-by-statement comparison function.  */
     584              : 
     585              : bool
     586       395228 : func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
     587              : {
     588       395228 :   gimple_stmt_iterator gsi1, gsi2;
     589       395228 :   gimple *s1, *s2;
     590              : 
     591       395228 :   gsi1 = gsi_start_nondebug_bb (bb1->bb);
     592       395228 :   gsi2 = gsi_start_nondebug_bb (bb2->bb);
     593              : 
     594      1134858 :   while (!gsi_end_p (gsi1))
     595              :     {
     596       787304 :       if (gsi_end_p (gsi2))
     597            0 :         return return_false ();
     598              : 
     599       787304 :       s1 = gsi_stmt (gsi1);
     600       787304 :       s2 = gsi_stmt (gsi2);
     601              : 
     602       787304 :       int eh1 = lookup_stmt_eh_lp_fn
     603       787304 :                 (DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
     604       787304 :       int eh2 = lookup_stmt_eh_lp_fn
     605       787304 :                 (DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
     606              : 
     607       787304 :       if (eh1 != eh2)
     608            0 :         return return_false_with_msg ("EH regions are different");
     609              : 
     610       787304 :       if (gimple_code (s1) != gimple_code (s2))
     611            0 :         return return_false_with_msg ("gimple codes are different");
     612              : 
     613       787304 :       switch (gimple_code (s1))
     614              :         {
     615       215041 :         case GIMPLE_CALL:
     616       215041 :           if (!compare_gimple_call (as_a <gcall *> (s1),
     617              :                                     as_a <gcall *> (s2)))
     618        38695 :             return return_different_stmts (s1, s2, "GIMPLE_CALL");
     619              :           break;
     620       326789 :         case GIMPLE_ASSIGN:
     621       326789 :           if (!compare_gimple_assign (s1, s2))
     622         6383 :             return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
     623              :           break;
     624       105428 :         case GIMPLE_COND:
     625       105428 :           if (!compare_gimple_cond (s1, s2))
     626         2465 :             return return_different_stmts (s1, s2, "GIMPLE_COND");
     627              :           break;
     628          228 :         case GIMPLE_SWITCH:
     629          228 :           if (!compare_gimple_switch (as_a <gswitch *> (s1),
     630          228 :                                       as_a <gswitch *> (s2)))
     631            2 :             return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
     632              :           break;
     633              :         case GIMPLE_DEBUG:
     634              :           break;
     635          148 :         case GIMPLE_EH_DISPATCH:
     636          148 :           if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
     637          148 :               != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
     638            0 :             return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
     639              :           break;
     640          785 :         case GIMPLE_RESX:
     641          785 :           if (!compare_gimple_resx (as_a <gresx *> (s1),
     642          785 :                                     as_a <gresx *> (s2)))
     643            0 :             return return_different_stmts (s1, s2, "GIMPLE_RESX");
     644              :           break;
     645         3259 :         case GIMPLE_LABEL:
     646         3259 :           if (!compare_gimple_label (as_a <glabel *> (s1),
     647         3259 :                                      as_a <glabel *> (s2)))
     648           10 :             return return_different_stmts (s1, s2, "GIMPLE_LABEL");
     649              :           break;
     650       134648 :         case GIMPLE_RETURN:
     651       134648 :           if (!compare_gimple_return (as_a <greturn *> (s1),
     652       134648 :                                       as_a <greturn *> (s2)))
     653           60 :             return return_different_stmts (s1, s2, "GIMPLE_RETURN");
     654              :           break;
     655            0 :         case GIMPLE_GOTO:
     656            0 :           if (!compare_gimple_goto (s1, s2))
     657            0 :             return return_different_stmts (s1, s2, "GIMPLE_GOTO");
     658              :           break;
     659          453 :         case GIMPLE_ASM:
     660          453 :           if (!compare_gimple_asm (as_a <gasm *> (s1),
     661          453 :                                    as_a <gasm *> (s2)))
     662           59 :             return return_different_stmts (s1, s2, "GIMPLE_ASM");
     663              :           break;
     664              :         case GIMPLE_PREDICT:
     665              :         case GIMPLE_NOP:
     666              :           break;
     667            0 :         default:
     668            0 :           return return_false_with_msg ("Unknown GIMPLE code reached");
     669              :         }
     670              : 
     671       739630 :       gsi_next_nondebug (&gsi1);
     672       739630 :       gsi_next_nondebug (&gsi2);
     673              :     }
     674              : 
     675       347554 :   if (!gsi_end_p (gsi2))
     676            0 :     return return_false ();
     677              : 
     678       347554 :   if (!compare_loops (bb1->bb, bb2->bb))
     679          175 :     return return_false ();
     680              : 
     681              :   return true;
     682              : }
     683              : 
     684              : /* Verifies for given GIMPLEs S1 and S2 that
     685              :    call statements are semantically equivalent.  */
     686              : 
     687              : bool
     688       215041 : func_checker::compare_gimple_call (gcall *s1, gcall *s2)
     689              : {
     690       215041 :   unsigned i;
     691       215041 :   tree t1, t2;
     692              : 
     693       215041 :   if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
     694              :     return false;
     695              : 
     696       215041 :   operand_access_type_map map (5);
     697       215041 :   classify_operands (s1, &map);
     698              : 
     699       215041 :   t1 = gimple_call_fn (s1);
     700       215041 :   t2 = gimple_call_fn (s2);
     701       215041 :   if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     702            0 :     return return_false ();
     703              : 
     704              :   /* Compare flags.  */
     705       215041 :   if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
     706       215041 :       || gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
     707       215041 :       || gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
     708       215041 :       || gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
     709       215041 :       || gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
     710       215041 :       || gimple_call_from_new_or_delete (s1) != gimple_call_from_new_or_delete (s2)
     711       215041 :       || gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
     712       215041 :       || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2)
     713       430082 :       || gimple_call_must_tail_p (s1) != gimple_call_must_tail_p (s2))
     714              :     return false;
     715              : 
     716       215033 :   unsigned check_arg_types_from = 0;
     717       215033 :   if (gimple_call_internal_p (s1))
     718              :     {
     719        86186 :       if (gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
     720              :         return false;
     721              :     }
     722              :   else
     723              :     {
     724       128847 :       tree fntype1 = gimple_call_fntype (s1);
     725       128847 :       tree fntype2 = gimple_call_fntype (s2);
     726       128847 :       if (!types_compatible_p (fntype1, fntype2))
     727         1089 :         return return_false_with_msg ("call function types are not compatible");
     728              : 
     729       127758 :       if (comp_type_attributes (fntype1, fntype2) != 1)
     730            0 :         return return_false_with_msg ("different fntype attributes");
     731              : 
     732       127758 :       check_arg_types_from = gimple_call_num_args (s1);
     733       127758 :       if (!prototype_p (fntype1) || !prototype_p (fntype2))
     734              :         check_arg_types_from = 0;
     735       127375 :       else if (stdarg_p (fntype1))
     736              :         {
     737         1067 :           check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype1));
     738         1067 :           if (stdarg_p (fntype2))
     739              :             {
     740         1067 :               unsigned n = list_length (TYPE_ARG_TYPES (fntype2));
     741         1067 :               check_arg_types_from = MIN (check_arg_types_from, n);
     742              :             }
     743              :         }
     744       126308 :       else if (stdarg_p (fntype2))
     745            0 :         check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype2));
     746              :     }
     747              : 
     748       186036 :   tree chain1 = gimple_call_chain (s1);
     749       186036 :   tree chain2 = gimple_call_chain (s2);
     750       186036 :   if ((chain1 && !chain2)
     751       186036 :       || (!chain1 && chain2)
     752       186036 :       || !compare_operand (chain1, chain2,
     753              :                            get_operand_access_type (&map, chain1)))
     754            0 :     return return_false_with_msg ("static call chains are different");
     755              : 
     756              :   /* Checking of argument.  */
     757       412957 :   for (i = 0; i < gimple_call_num_args (s1); ++i)
     758              :     {
     759       227919 :       t1 = gimple_call_arg (s1, i);
     760       227919 :       t2 = gimple_call_arg (s2, i);
     761              : 
     762       227919 :       if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     763          161 :         return return_false_with_msg ("GIMPLE call operands are different");
     764       227758 :       if (i >= check_arg_types_from
     765       227758 :           && !types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     766          837 :         return return_false_with_msg ("GIMPLE call operand types are "
     767              :                                       "different");
     768              :     }
     769              : 
     770              :   /* Return value checking.  */
     771       185038 :   t1 = gimple_get_lhs (s1);
     772       185038 :   t2 = gimple_get_lhs (s2);
     773              : 
     774              :   /* For internal calls, lhs types need to be verified, as neither fntype nor
     775              :      callee comparisons can catch that.  */
     776       185038 :   if (gimple_call_internal_p (s1)
     777        57658 :       && t1
     778        57658 :       && t2
     779       242551 :       && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     780         2610 :     return return_false_with_msg ("GIMPLE internal call LHS type mismatch");
     781              : 
     782       182428 :   if (!gimple_call_internal_p (s1))
     783              :     {
     784       127380 :       cgraph_edge *e1 = cgraph_node::get (m_source_func_decl)->get_edge (s1);
     785       127380 :       cgraph_edge *e2 = cgraph_node::get (m_target_func_decl)->get_edge (s2);
     786       127380 :       class ipa_edge_args *args1 = ipa_edge_args_sum->get (e1);
     787       127380 :       class ipa_edge_args *args2 = ipa_edge_args_sum->get (e2);
     788       127380 :       if ((args1 != nullptr) != (args2 != nullptr))
     789            0 :         return return_false_with_msg ("ipa_edge_args mismatch");
     790       127380 :       if (args1)
     791              :         {
     792        80666 :           int n1 = ipa_get_cs_argument_count (args1);
     793        80666 :           int n2 = ipa_get_cs_argument_count (args2);
     794        80666 :           if (n1 != n2)
     795            0 :             return return_false_with_msg ("ipa_edge_args nargs mismatch");
     796       142057 :           for (int i = 0; i < n1; i++)
     797              :             {
     798        67467 :               struct ipa_jump_func *jf1 = ipa_get_ith_jump_func (args1, i);
     799        67467 :               struct ipa_jump_func *jf2 = ipa_get_ith_jump_func (args2, i);
     800        67467 :               if (((jf1 != nullptr) != (jf2 != nullptr))
     801        67467 :                   || (jf1 && !ipa_jump_functions_equivalent_p (jf1, jf2)))
     802         6076 :                 return return_false_with_msg ("jump function mismatch");
     803              :             }
     804              :         }
     805              :     }
     806              : 
     807       176352 :   return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     808       215041 : }
     809              : 
     810              : 
     811              : /* Verifies for given GIMPLEs S1 and S2 that
     812              :    assignment statements are semantically equivalent.  */
     813              : 
     814              : bool
     815       326789 : func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
     816              : {
     817       326789 :   tree arg1, arg2;
     818       326789 :   tree_code code1, code2;
     819       326789 :   unsigned i;
     820              : 
     821       326789 :   code1 = gimple_assign_rhs_code (s1);
     822       326789 :   code2 = gimple_assign_rhs_code (s2);
     823              : 
     824       326789 :   if (code1 != code2)
     825              :     return false;
     826              : 
     827       326789 :   operand_access_type_map map (5);
     828       326789 :   classify_operands (s1, &map);
     829              : 
     830      1368890 :   for (i = 0; i < gimple_num_ops (s1); i++)
     831              :     {
     832       721695 :       arg1 = gimple_op (s1, i);
     833       721695 :       arg2 = gimple_op (s2, i);
     834              : 
     835              :       /* Compare types for LHS.  */
     836       721695 :       if (i == 0 && !gimple_store_p (s1))
     837              :         {
     838       282497 :           if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
     839         1390 :             return return_false_with_msg ("GIMPLE LHS type mismatch");
     840              :         }
     841              : 
     842       720305 :       if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1)))
     843         4993 :         return return_false_with_msg ("GIMPLE assignment operands "
     844              :                                       "are different");
     845              :     }
     846              : 
     847              : 
     848              :   return true;
     849       326789 : }
     850              : 
     851              : /* Verifies for given GIMPLEs S1 and S2 that
     852              :    condition statements are semantically equivalent.  */
     853              : 
     854              : bool
     855       105428 : func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
     856              : {
     857       105428 :   tree t1, t2;
     858       105428 :   tree_code code1, code2;
     859              : 
     860       105428 :   code1 = gimple_cond_code (s1);
     861       105428 :   code2 = gimple_cond_code (s2);
     862              : 
     863       105428 :   if (code1 != code2)
     864              :     return false;
     865              : 
     866       102970 :   t1 = gimple_cond_lhs (s1);
     867       102970 :   t2 = gimple_cond_lhs (s2);
     868              : 
     869       102970 :   if (!compare_operand (t1, t2, OP_NORMAL))
     870              :     return false;
     871              : 
     872       102963 :   t1 = gimple_cond_rhs (s1);
     873       102963 :   t2 = gimple_cond_rhs (s2);
     874              : 
     875       102963 :   return compare_operand (t1, t2, OP_NORMAL);
     876              : }
     877              : 
     878              : /* Verifies for given GIMPLE_LABEL stmts S1 and S2 that
     879              :    label statements are semantically equivalent.  */
     880              : 
     881              : bool
     882         3259 : func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
     883              : {
     884         3259 :   if (m_ignore_labels)
     885              :     return true;
     886              : 
     887         3259 :   tree t1 = gimple_label_label (g1);
     888         3259 :   tree t2 = gimple_label_label (g2);
     889              : 
     890         6508 :   if (FORCED_LABEL (t1) || FORCED_LABEL (t2))
     891           10 :     return return_false_with_msg ("FORCED_LABEL");
     892              : 
     893              :   /* As the pass build BB to label mapping, no further check is needed.  */
     894              :   return true;
     895              : }
     896              : 
     897              : /* Verifies for given GIMPLE_SWITCH stmts S1 and S2 that
     898              :    switch statements are semantically equivalent.  */
     899              : 
     900              : bool
     901          228 : func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
     902              : {
     903          228 :   unsigned lsize1, lsize2, i;
     904              : 
     905          228 :   lsize1 = gimple_switch_num_labels (g1);
     906          228 :   lsize2 = gimple_switch_num_labels (g2);
     907              : 
     908          228 :   if (lsize1 != lsize2)
     909              :     return false;
     910              : 
     911          227 :   tree t1 = gimple_switch_index (g1);
     912          227 :   tree t2 = gimple_switch_index (g2);
     913              : 
     914          227 :   if (!compare_operand (t1, t2, OP_NORMAL))
     915              :     return false;
     916              : 
     917         1494 :   for (i = 0; i < lsize1; i++)
     918              :     {
     919         1268 :       tree label1 = gimple_switch_label (g1, i);
     920         1268 :       tree label2 = gimple_switch_label (g2, i);
     921              : 
     922              :       /* Label LOW and HIGH comparison.  */
     923         1268 :       tree low1 = CASE_LOW (label1);
     924         1268 :       tree low2 = CASE_LOW (label2);
     925              : 
     926         1268 :       if (!tree_int_cst_equal (low1, low2))
     927            1 :         return return_false_with_msg ("case low values are different");
     928              : 
     929         1267 :       tree high1 = CASE_HIGH (label1);
     930         1267 :       tree high2 = CASE_HIGH (label2);
     931              : 
     932         1267 :       if (!tree_int_cst_equal (high1, high2))
     933            0 :         return return_false_with_msg ("case high values are different");
     934              : 
     935         1267 :       if (!compare_operand (CASE_LABEL (label1), CASE_LABEL (label2), OP_NORMAL))
     936            0 :         return return_false_with_msg ("switch label_exprs are different");
     937              :     }
     938              : 
     939              :   return true;
     940              : }
     941              : 
     942              : /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
     943              :    return statements are semantically equivalent.  */
     944              : 
     945              : bool
     946       134648 : func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
     947              : {
     948       134648 :   tree t1, t2;
     949              : 
     950       134648 :   t1 = gimple_return_retval (g1);
     951       134648 :   t2 = gimple_return_retval (g2);
     952              : 
     953              :   /* Void return type.  */
     954       134648 :   if (t1 == NULL && t2 == NULL)
     955              :     return true;
     956              :   else
     957              :     {
     958        74113 :       operand_access_type_map map (3);
     959        74113 :       return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     960        74113 :     }
     961              : }
     962              : 
     963              : /* Verifies for given GIMPLEs S1 and S2 that
     964              :    goto statements are semantically equivalent.  */
     965              : 
     966              : bool
     967            0 : func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
     968              : {
     969            0 :   tree dest1, dest2;
     970              : 
     971            0 :   dest1 = gimple_goto_dest (g1);
     972            0 :   dest2 = gimple_goto_dest (g2);
     973              : 
     974            0 :   if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
     975              :     return false;
     976              : 
     977            0 :   return compare_operand (dest1, dest2, OP_NORMAL);
     978              : }
     979              : 
     980              : /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
     981              :    resx statements are semantically equivalent.  */
     982              : 
     983              : bool
     984          785 : func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
     985              : {
     986          785 :   return gimple_resx_region (g1) == gimple_resx_region (g2);
     987              : }
     988              : 
     989              : /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
     990              :    For the beginning, the pass only supports equality for
     991              :    '__asm__ __volatile__ ("", "", "", "memory")'.  */
     992              : 
     993              : bool
     994          453 : func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
     995              : {
     996          453 :   if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
     997              :     return false;
     998              : 
     999          453 :   if (gimple_asm_basic_p (g1) != gimple_asm_basic_p (g2))
    1000              :     return false;
    1001              : 
    1002          453 :   if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
    1003              :     return false;
    1004              : 
    1005          453 :   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
    1006              :     return false;
    1007              : 
    1008          452 :   if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
    1009              :     return false;
    1010              : 
    1011              :   /* We do not support goto ASM statement comparison.  */
    1012          452 :   if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
    1013              :     return false;
    1014              : 
    1015          428 :   if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
    1016              :     return false;
    1017              : 
    1018          428 :   if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
    1019            5 :     return return_false_with_msg ("ASM strings are different");
    1020              : 
    1021          423 :   operand_access_type_map map (5);
    1022          423 :   classify_operands (g1, &map);
    1023              : 
    1024         1232 :   for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
    1025              :     {
    1026          413 :       tree input1 = gimple_asm_input_op (g1, i);
    1027          413 :       tree input2 = gimple_asm_input_op (g2, i);
    1028              : 
    1029          413 :       if (!compare_asm_inputs_outputs (input1, input2, &map))
    1030           27 :         return return_false_with_msg ("ASM input is different");
    1031              :     }
    1032              : 
    1033          896 :   for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
    1034              :     {
    1035          502 :       tree output1 = gimple_asm_output_op (g1, i);
    1036          502 :       tree output2 = gimple_asm_output_op (g2, i);
    1037              : 
    1038          502 :       if (!compare_asm_inputs_outputs (output1, output2, &map))
    1039            2 :         return return_false_with_msg ("ASM output is different");
    1040              :     }
    1041              : 
    1042          468 :   for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
    1043              :     {
    1044           74 :       tree clobber1 = gimple_asm_clobber_op (g1, i);
    1045           74 :       tree clobber2 = gimple_asm_clobber_op (g2, i);
    1046              : 
    1047           74 :       if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
    1048              :                             OEP_ONLY_CONST))
    1049            0 :         return return_false_with_msg ("ASM clobber is different");
    1050              :     }
    1051              : 
    1052              :   return true;
    1053          423 : }
    1054              : 
    1055              : /* Helper for func_checker::classify_operands.  Record that T is a load.  */
    1056              : 
    1057              : static bool
    1058      8563911 : visit_load_store (gimple *, tree, tree t, void *data)
    1059              : {
    1060      8563911 :   func_checker::operand_access_type_map *map =
    1061              :     (func_checker::operand_access_type_map *) data;
    1062      8563911 :   map->add (t);
    1063      8563911 :   return false;
    1064              : }
    1065              : 
    1066              : /* Compute hash map determining access types of operands.  */
    1067              : 
    1068              : void
    1069     21760941 : func_checker::classify_operands (const gimple *stmt,
    1070              :                                  operand_access_type_map *map)
    1071              : {
    1072     21760941 :   walk_stmt_load_store_ops (const_cast <gimple *> (stmt),
    1073              :                             (void *)map, visit_load_store, visit_load_store);
    1074     21760941 : }
    1075              : 
    1076              : /* Return access type of a given operand.  */
    1077              : 
    1078              : func_checker::operand_access_type
    1079     65115806 : func_checker::get_operand_access_type (operand_access_type_map *map, tree t)
    1080              : {
    1081     65115806 :   if (map->contains (t))
    1082      8550729 :     return OP_MEMORY;
    1083              :   return OP_NORMAL;
    1084              : }
    1085              : 
    1086              : } // 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.