LCOV - code coverage report
Current view: top level - gcc - ipa-icf-gimple.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.1 % 528 481
Test Date: 2026-02-28 14:20:25 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       124068 : 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       124068 :                             hash_set<symtab_node *> *ignored_target_nodes)
      65       124068 :   : m_source_func_decl (source_func_decl), m_target_func_decl (target_func_decl),
      66       124068 :     m_ignored_source_nodes (ignored_source_nodes),
      67       124068 :     m_ignored_target_nodes (ignored_target_nodes),
      68       124068 :     m_ignore_labels (ignore_labels), m_tbaa (tbaa),
      69       124068 :     m_total_scalarization_limit_known_p (false)
      70              : {
      71       124068 :   function *source_func = DECL_STRUCT_FUNCTION (source_func_decl);
      72       124068 :   function *target_func = DECL_STRUCT_FUNCTION (target_func_decl);
      73              : 
      74       124068 :   unsigned ssa_source = SSANAMES (source_func)->length ();
      75       124068 :   unsigned ssa_target = SSANAMES (target_func)->length ();
      76              : 
      77       124068 :   m_source_ssa_names.create (ssa_source);
      78       124068 :   m_target_ssa_names.create (ssa_target);
      79              : 
      80      1086028 :   for (unsigned i = 0; i < ssa_source; i++)
      81       961960 :     m_source_ssa_names.safe_push (-1);
      82              : 
      83      1085632 :   for (unsigned i = 0; i < ssa_target; i++)
      84       961564 :     m_target_ssa_names.safe_push (-1);
      85       124068 : }
      86              : 
      87              : /* Memory release routine.  */
      88              : 
      89       500477 : func_checker::~func_checker ()
      90              : {
      91       376409 :   m_source_ssa_names.release();
      92       376409 :   m_target_ssa_names.release();
      93       500477 : }
      94              : 
      95              : /* Verifies that trees T1 and T2 are equivalent from perspective of ICF.  */
      96              : 
      97              : bool
      98      1281363 : func_checker::compare_ssa_name (const_tree t1, const_tree t2)
      99              : {
     100      1281363 :   gcc_assert (TREE_CODE (t1) == SSA_NAME);
     101      1281363 :   gcc_assert (TREE_CODE (t2) == SSA_NAME);
     102              : 
     103      1281363 :   unsigned i1 = SSA_NAME_VERSION (t1);
     104      1281363 :   unsigned i2 = SSA_NAME_VERSION (t2);
     105              : 
     106      1281363 :   if (SSA_NAME_IS_DEFAULT_DEF (t1) != SSA_NAME_IS_DEFAULT_DEF (t2))
     107              :     return false;
     108              : 
     109      1281363 :   if (m_source_ssa_names[i1] == -1)
     110       367721 :     m_source_ssa_names[i1] = i2;
     111       913642 :   else if (m_source_ssa_names[i1] != (int) i2)
     112              :     return false;
     113              : 
     114      1281180 :   if(m_target_ssa_names[i2] == -1)
     115       367717 :     m_target_ssa_names[i2] = i1;
     116       913463 :   else if (m_target_ssa_names[i2] != (int) i1)
     117              :     return false;
     118              : 
     119      1281176 :   if (SSA_NAME_IS_DEFAULT_DEF (t1))
     120              :     {
     121       253890 :       tree b1 = SSA_NAME_VAR (t1);
     122       253890 :       tree b2 = SSA_NAME_VAR (t2);
     123              : 
     124       253890 :       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       542822 : func_checker::compare_edge (edge e1, edge e2)
     134              : {
     135       542822 :   if (e1->flags != e2->flags)
     136              :     return false;
     137              : 
     138       542822 :   bool existed_p;
     139              : 
     140       542822 :   edge &slot = m_edge_map.get_or_insert (e1, &existed_p);
     141       542822 :   if (existed_p)
     142       253061 :     return return_with_debug (slot == e2);
     143              :   else
     144       289761 :     slot = e2;
     145              : 
     146              :   /* TODO: filter edge probabilities for profile feedback match.  */
     147              : 
     148       289761 :   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       504281 : func_checker::compare_decl (const_tree t1, const_tree t2)
     156              : {
     157       504281 :   if (!auto_var_in_fn_p (t1, m_source_func_decl)
     158       504281 :       || !auto_var_in_fn_p (t2, m_target_func_decl))
     159            6 :     return return_with_debug (t1 == t2);
     160              : 
     161       504275 :   tree_code t = TREE_CODE (t1);
     162       504275 :   if ((t == VAR_DECL || t == PARM_DECL || t == RESULT_DECL)
     163       504275 :       && 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       504275 :   if (t != VAR_DECL)
     171              :     {
     172       432715 :       if (!compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     173            0 :         return return_false ();
     174              :     }
     175              :   else
     176              :     {
     177        71560 :       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       504275 :   bool existed_p;
     183       504275 :   const_tree &slot = m_decl_map.get_or_insert (t1, &existed_p);
     184       504275 :   if (existed_p)
     185       328010 :     return return_with_debug (slot == t2);
     186              :   else
     187       176265 :     slot = t2;
     188              : 
     189       176265 :   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        14028 : func_checker::compatible_polymorphic_types_p (tree t1, tree t2,
     198              :                                               bool compare_ptr)
     199              : {
     200        14028 :   gcc_assert (TREE_CODE (t1) != FUNCTION_TYPE && TREE_CODE (t1) != METHOD_TYPE);
     201              : 
     202              :   /* Pointer types generally give no information.  */
     203        14028 :   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        14028 :   bool c1 = contains_polymorphic_type_p (t1);
     214        14028 :   bool c2 = contains_polymorphic_type_p (t2);
     215        14028 :   if (!c1 && !c2)
     216              :     return true;
     217          785 :   if (!c1 || !c2)
     218            0 :     return return_false_with_msg ("one type is not polymorphic");
     219          785 :   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      4374562 : func_checker::compatible_types_p (tree t1, tree t2)
     227              : {
     228      4374562 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     229       137912 :     return return_false_with_msg ("different tree types");
     230              : 
     231      4236650 :   if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
     232          114 :     return return_false_with_msg ("restrict flags are different");
     233              : 
     234      4236536 :   if (!types_compatible_p (t1, t2))
     235       944597 :     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    131449293 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     245              :                             unsigned int flags)
     246              : {
     247    136320419 :   if (arg == NULL_TREE)
     248              :     {
     249     15294880 :       hstate.merge_hash (0);
     250     15294880 :       return;
     251              :     }
     252              : 
     253    121025539 :   switch (TREE_CODE (arg))
     254              :     {
     255      5506287 :     case PARM_DECL:
     256      5506287 :       {
     257      5506287 :         unsigned int index = 0;
     258      5506287 :         if (DECL_CONTEXT (arg))
     259      5506287 :           for (tree p = DECL_ARGUMENTS (DECL_CONTEXT (arg));
     260     11095035 :                p && index < 32; p = DECL_CHAIN (p), index++)
     261     11086117 :             if (p == arg)
     262              :               break;
     263      5506287 :         hstate.add_int (PARM_DECL);
     264      5506287 :         hstate.add_int (index);
     265              :       }
     266      5506287 :       return;
     267     14247503 :     case FUNCTION_DECL:
     268     14247503 :     case VAR_DECL:
     269     14247503 :     case LABEL_DECL:
     270     14247503 :     case RESULT_DECL:
     271     14247503 :     case CONST_DECL:
     272     14247503 :       hstate.add_int (TREE_CODE (arg));
     273     14247503 :       return;
     274     33122716 :     case SSA_NAME:
     275     33122716 :       hstate.add_int (SSA_NAME);
     276     33122716 :       if (SSA_NAME_IS_DEFAULT_DEF (arg))
     277      4871126 :         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     68148796 :     default:
     284     68148796 :       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     68148796 :   if (TREE_CLOBBER_P (arg))
     290              :     {
     291      1149674 :       hstate.add_int (0xc10bbe5);
     292      1149674 :       return;
     293              :     }
     294     66999122 :   gcc_assert (!DECL_P (arg));
     295     66999122 :   gcc_assert (!TYPE_P (arg));
     296              : 
     297     66999122 :   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     64483777 : func_checker::hash_operand (const_tree arg, inchash::hash &hstate,
     305              :                             unsigned int flags, operand_access_type access)
     306              : {
     307     64483777 :   if (access == OP_MEMORY)
     308              :     {
     309      7954601 :       ao_ref ref;
     310      7954601 :       ao_ref_init (&ref, const_cast <tree> (arg));
     311      7954601 :       return hash_ao_ref (&ref, lto_streaming_expected_p (), m_tbaa, hstate);
     312              :     }
     313              :   else
     314     56529176 :     return hash_operand (arg, hstate, flags);
     315              : }
     316              : 
     317              : bool
     318      5046323 : func_checker::operand_equal_p (const_tree t1, const_tree t2,
     319              :                                unsigned int flags)
     320              : {
     321      5046323 :   bool r;
     322      5046323 :   if (verify_hash_value (t1, t2, flags, &r))
     323      2189243 :     return r;
     324              : 
     325      2857080 :   if (t1 == t2)
     326              :     return true;
     327      2149427 :   else if (!t1 || !t2)
     328              :     return false;
     329              : 
     330      2149427 :   if (TREE_CODE (t1) != TREE_CODE (t2))
     331            1 :     return return_false ();
     332              : 
     333      2149426 :   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        71584 :     case VAR_DECL:
     340        71584 :       return return_with_debug (compare_variable_decl (t1, t2));
     341         3638 :     case LABEL_DECL:
     342         3638 :       {
     343         3638 :         int *bb1 = m_label_bb_map.get (t1);
     344         3638 :         int *bb2 = m_label_bb_map.get (t2);
     345              :         /* Labels can point to another function (non-local GOTOs).  */
     346         3643 :         return return_with_debug (bb1 != NULL && bb2 != NULL && *bb1 == *bb2);
     347              :       }
     348              : 
     349       268988 :     case PARM_DECL:
     350       268988 :     case RESULT_DECL:
     351       268988 :     case CONST_DECL:
     352       268988 :       return compare_decl (t1, t2);
     353      1281363 :     case SSA_NAME:
     354      1281363 :       return compare_ssa_name (t1, t2);
     355       512059 :     default:
     356       512059 :       break;
     357              :     }
     358              :   /* In gimple all clobbers can be considered equal.  We match the left hand
     359              :      memory accesses.  */
     360       512059 :   if (TREE_CLOBBER_P (t1) || TREE_CLOBBER_P (t2))
     361        21950 :     return TREE_CLOBBER_P (t1) == TREE_CLOBBER_P (t2);
     362              : 
     363       490109 :   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       169315 : func_checker::safe_for_total_scalarization_p (tree t1, tree t2)
     371              : {
     372       169315 :   tree type1 = TREE_TYPE (t1);
     373       169315 :   tree type2 = TREE_TYPE (t2);
     374              : 
     375       169315 :   if (!AGGREGATE_TYPE_P (type1)
     376        37502 :       || !AGGREGATE_TYPE_P (type2)
     377        37502 :       || !tree_fits_uhwi_p (TYPE_SIZE (type1))
     378       206817 :       || !tree_fits_uhwi_p (TYPE_SIZE (type2)))
     379              :     return true;
     380              : 
     381        37502 :   if (!m_total_scalarization_limit_known_p)
     382              :     {
     383         6903 :       push_cfun (DECL_STRUCT_FUNCTION (m_target_func_decl));
     384         6903 :       m_total_scalarization_limit = sra_get_max_scalarization_size ();
     385         6903 :       pop_cfun ();
     386         6903 :       m_total_scalarization_limit_known_p = true;
     387              :     }
     388              : 
     389        37502 :   unsigned HOST_WIDE_INT sz = tree_to_uhwi (TYPE_SIZE (type1));
     390        37502 :   gcc_assert (sz == tree_to_uhwi (TYPE_SIZE (type2)));
     391        37502 :   if (sz > m_total_scalarization_limit)
     392              :     return true;
     393        37285 :   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      2517754 : func_checker::compare_operand (tree t1, tree t2, operand_access_type access)
     403              : {
     404      2517754 :   if (!t1 && !t2)
     405              :     return true;
     406      2101024 :   else if (!t1 || !t2)
     407              :     return false;
     408      2101024 :   if (access == OP_MEMORY)
     409              :     {
     410       171558 :       ao_ref ref1, ref2;
     411       171558 :       ao_ref_init (&ref1, const_cast <tree> (t1));
     412       171558 :       ao_ref_init (&ref2, const_cast <tree> (t2));
     413       343116 :       int flags = compare_ao_refs (&ref1, &ref2,
     414       171558 :                                    lto_streaming_expected_p (), m_tbaa);
     415              : 
     416       171558 :       if (!flags)
     417              :         {
     418       169315 :           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         2243 :       if (flags & SEMANTICS)
     424          430 :         return return_false_with_msg
     425              :                 ("compare_ao_refs failed (semantic difference)");
     426         1813 :       if (flags & BASE_ALIAS_SET)
     427           22 :         return return_false_with_msg
     428              :                 ("compare_ao_refs failed (base alias set difference)");
     429         1791 :       if (flags & REF_ALIAS_SET)
     430            0 :         return return_false_with_msg
     431              :                  ("compare_ao_refs failed (ref alias set difference)");
     432         1791 :       if (flags & ACCESS_PATH)
     433         1710 :         return return_false_with_msg
     434              :                  ("compare_ao_refs failed (access path difference)");
     435           81 :       if (flags & DEPENDENCE_CLIQUE)
     436           81 :         return return_false_with_msg
     437              :                  ("compare_ao_refs failed (dependence clique difference)");
     438            0 :       gcc_unreachable ();
     439              :     }
     440              :   else
     441              :     {
     442      1929466 :       if (operand_equal_p (t1, t2, OEP_MATCH_SIDE_EFFECTS))
     443              :         return true;
     444          282 :       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       465921 : func_checker::compare_variable_decl (const_tree t1, const_tree t2)
     490              : {
     491       465921 :   bool ret = false;
     492              : 
     493       465921 :   if (t1 == t2)
     494              :     return true;
     495              : 
     496        71592 :   if (DECL_ALIGN (t1) != DECL_ALIGN (t2))
     497            6 :     return return_false_with_msg ("alignments are different");
     498              : 
     499        71586 :   if (DECL_HARD_REGISTER (t1) != DECL_HARD_REGISTER (t2))
     500            0 :     return return_false_with_msg ("DECL_HARD_REGISTER are different");
     501              : 
     502        71586 :   if (DECL_HARD_REGISTER (t1)
     503        71586 :       && 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        71578 :   if (decl_in_symtab_p (t1))
     509           18 :     return decl_in_symtab_p (t2);
     510        71560 :   ret = compare_decl (t1, t2);
     511              : 
     512        71560 :   return return_with_debug (ret);
     513              : }
     514              : 
     515              : /* Compare loop information for basic blocks BB1 and BB2.  */
     516              : 
     517              : bool
     518       394504 : func_checker::compare_loops (basic_block bb1, basic_block bb2)
     519              : {
     520       394504 :   if ((bb1->loop_father == NULL) != (bb2->loop_father == NULL))
     521            0 :     return return_false ();
     522              : 
     523       394504 :   class loop *l1 = bb1->loop_father;
     524       394504 :   class loop *l2 = bb2->loop_father;
     525       394504 :   if (l1 == NULL)
     526              :     return true;
     527              : 
     528       394504 :   if ((bb1 == l1->header) != (bb2 == l2->header))
     529            0 :     return return_false_with_msg ("header");
     530       394504 :   if ((bb1 == l1->latch) != (bb2 == l2->latch))
     531            0 :     return return_false_with_msg ("latch");
     532       394504 :   if (l1->simdlen != l2->simdlen)
     533            5 :     return return_false_with_msg ("simdlen");
     534       394499 :   if (l1->safelen != l2->safelen)
     535           10 :     return return_false_with_msg ("safelen");
     536       394489 :   if (l1->can_be_parallel != l2->can_be_parallel)
     537            0 :     return return_false_with_msg ("can_be_parallel");
     538       394489 :   if (l1->dont_vectorize != l2->dont_vectorize)
     539          149 :     return return_false_with_msg ("dont_vectorize");
     540       394340 :   if (l1->force_vectorize != l2->force_vectorize)
     541            0 :     return return_false_with_msg ("force_vectorize");
     542       394340 :   if (l1->finite_p != l2->finite_p)
     543            3 :     return return_false_with_msg ("finite_p");
     544       394337 :   if (l1->unroll != l2->unroll)
     545            0 :     return return_false_with_msg ("unroll");
     546       394337 :   if (!compare_variable_decl (l1->simduid, l2->simduid))
     547            0 :     return return_false_with_msg ("simduid");
     548       394337 :   if ((l1->any_upper_bound != l2->any_upper_bound)
     549       394337 :       || (l1->any_upper_bound
     550         8413 :           && (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      1157864 : func_checker::parse_labels (sem_bb *bb)
     561              : {
     562      6864046 :   for (gimple_stmt_iterator gsi = gsi_start_bb (bb->bb); !gsi_end_p (gsi);
     563      4548318 :        gsi_next (&gsi))
     564              :     {
     565      4548318 :       gimple *stmt = gsi_stmt (gsi);
     566              : 
     567      4569008 :       if (glabel *label_stmt = dyn_cast <glabel *> (stmt))
     568              :         {
     569        20690 :           const_tree t = gimple_label_label (label_stmt);
     570        20690 :           gcc_assert (TREE_CODE (t) == LABEL_DECL);
     571              : 
     572        20690 :           m_label_bb_map.put (t, bb->bb->index);
     573              :         }
     574              :     }
     575      1157864 : }
     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       433180 : func_checker::compare_bb (sem_bb *bb1, sem_bb *bb2)
     586              : {
     587       433180 :   gimple_stmt_iterator gsi1, gsi2;
     588       433180 :   gimple *s1, *s2;
     589              : 
     590       433180 :   gsi1 = gsi_start_nondebug_bb (bb1->bb);
     591       433180 :   gsi2 = gsi_start_nondebug_bb (bb2->bb);
     592              : 
     593      1340924 :   while (!gsi_end_p (gsi1))
     594              :     {
     595       946420 :       if (gsi_end_p (gsi2))
     596            0 :         return return_false ();
     597              : 
     598       946420 :       s1 = gsi_stmt (gsi1);
     599       946420 :       s2 = gsi_stmt (gsi2);
     600              : 
     601       946420 :       int eh1 = lookup_stmt_eh_lp_fn
     602       946420 :                 (DECL_STRUCT_FUNCTION (m_source_func_decl), s1);
     603       946420 :       int eh2 = lookup_stmt_eh_lp_fn
     604       946420 :                 (DECL_STRUCT_FUNCTION (m_target_func_decl), s2);
     605              : 
     606       946420 :       if (eh1 != eh2)
     607            3 :         return return_false_with_msg ("EH regions are different");
     608              : 
     609       946417 :       if (gimple_code (s1) != gimple_code (s2))
     610            0 :         return return_false_with_msg ("gimple codes are different");
     611              : 
     612       946417 :       switch (gimple_code (s1))
     613              :         {
     614       246742 :         case GIMPLE_CALL:
     615       246742 :           if (!compare_gimple_call (as_a <gcall *> (s1),
     616              :                                     as_a <gcall *> (s2)))
     617        32533 :             return return_different_stmts (s1, s2, "GIMPLE_CALL");
     618              :           break;
     619       416431 :         case GIMPLE_ASSIGN:
     620       416431 :           if (!compare_gimple_assign (s1, s2))
     621         3646 :             return return_different_stmts (s1, s2, "GIMPLE_ASSIGN");
     622              :           break;
     623       116879 :         case GIMPLE_COND:
     624       116879 :           if (!compare_gimple_cond (s1, s2))
     625         2387 :             return return_different_stmts (s1, s2, "GIMPLE_COND");
     626              :           break;
     627          403 :         case GIMPLE_SWITCH:
     628          403 :           if (!compare_gimple_switch (as_a <gswitch *> (s1),
     629          403 :                                       as_a <gswitch *> (s2)))
     630            2 :             return return_different_stmts (s1, s2, "GIMPLE_SWITCH");
     631              :           break;
     632              :         case GIMPLE_DEBUG:
     633              :           break;
     634          389 :         case GIMPLE_EH_DISPATCH:
     635          389 :           if (gimple_eh_dispatch_region (as_a <geh_dispatch *> (s1))
     636          389 :               != gimple_eh_dispatch_region (as_a <geh_dispatch *> (s2)))
     637            0 :             return return_different_stmts (s1, s2, "GIMPLE_EH_DISPATCH");
     638              :           break;
     639         4161 :         case GIMPLE_RESX:
     640         4161 :           if (!compare_gimple_resx (as_a <gresx *> (s1),
     641         4161 :                                     as_a <gresx *> (s2)))
     642            0 :             return return_different_stmts (s1, s2, "GIMPLE_RESX");
     643              :           break;
     644         9036 :         case GIMPLE_LABEL:
     645         9036 :           if (!compare_gimple_label (as_a <glabel *> (s1),
     646         9036 :                                      as_a <glabel *> (s2)))
     647           10 :             return return_different_stmts (s1, s2, "GIMPLE_LABEL");
     648              :           break;
     649       146369 :         case GIMPLE_RETURN:
     650       146369 :           if (!compare_gimple_return (as_a <greturn *> (s1),
     651       146369 :                                       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       907744 :       gsi_next_nondebug (&gsi1);
     671       907744 :       gsi_next_nondebug (&gsi2);
     672              :     }
     673              : 
     674       394504 :   if (!gsi_end_p (gsi2))
     675            0 :     return return_false ();
     676              : 
     677       394504 :   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       246742 : func_checker::compare_gimple_call (gcall *s1, gcall *s2)
     688              : {
     689       246742 :   unsigned i;
     690       246742 :   tree t1, t2;
     691              : 
     692       246742 :   if (gimple_call_num_args (s1) != gimple_call_num_args (s2))
     693              :     return false;
     694              : 
     695       246742 :   operand_access_type_map map (5);
     696       246742 :   classify_operands (s1, &map);
     697              : 
     698       246742 :   t1 = gimple_call_fn (s1);
     699       246742 :   t2 = gimple_call_fn (s2);
     700       246742 :   if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     701            0 :     return return_false ();
     702              : 
     703              :   /* Compare flags.  */
     704       246742 :   if (gimple_call_internal_p (s1) != gimple_call_internal_p (s2)
     705       246742 :       || gimple_call_ctrl_altering_p (s1) != gimple_call_ctrl_altering_p (s2)
     706       246742 :       || gimple_call_tail_p (s1) != gimple_call_tail_p (s2)
     707       246742 :       || gimple_call_return_slot_opt_p (s1) != gimple_call_return_slot_opt_p (s2)
     708       246742 :       || gimple_call_from_thunk_p (s1) != gimple_call_from_thunk_p (s2)
     709       246742 :       || gimple_call_from_new_or_delete (s1) != gimple_call_from_new_or_delete (s2)
     710       246742 :       || gimple_call_va_arg_pack_p (s1) != gimple_call_va_arg_pack_p (s2)
     711       246742 :       || gimple_call_alloca_for_var_p (s1) != gimple_call_alloca_for_var_p (s2)
     712       493484 :       || gimple_call_must_tail_p (s1) != gimple_call_must_tail_p (s2))
     713              :     return false;
     714              : 
     715       246734 :   unsigned check_arg_types_from = 0;
     716       246734 :   if (gimple_call_internal_p (s1))
     717              :     {
     718        86378 :       if (gimple_call_internal_fn (s1) != gimple_call_internal_fn (s2))
     719              :         return false;
     720              :     }
     721              :   else
     722              :     {
     723       160356 :       tree fntype1 = gimple_call_fntype (s1);
     724       160356 :       tree fntype2 = gimple_call_fntype (s2);
     725       160356 :       if (!types_compatible_p (fntype1, fntype2))
     726         1033 :         return return_false_with_msg ("call function types are not compatible");
     727              : 
     728       159323 :       if (comp_type_attributes (fntype1, fntype2) != 1)
     729            0 :         return return_false_with_msg ("different fntype attributes");
     730              : 
     731       159323 :       check_arg_types_from = gimple_call_num_args (s1);
     732       159323 :       if (!prototype_p (fntype1) || !prototype_p (fntype2))
     733              :         check_arg_types_from = 0;
     734       158968 :       else if (stdarg_p (fntype1))
     735              :         {
     736         3134 :           check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype1));
     737         3134 :           if (stdarg_p (fntype2))
     738              :             {
     739         3134 :               unsigned n = list_length (TYPE_ARG_TYPES (fntype2));
     740         3134 :               check_arg_types_from = MIN (check_arg_types_from, n);
     741              :             }
     742              :         }
     743       155834 :       else if (stdarg_p (fntype2))
     744            0 :         check_arg_types_from = list_length (TYPE_ARG_TYPES (fntype2));
     745              :     }
     746              : 
     747       217837 :   tree chain1 = gimple_call_chain (s1);
     748       217837 :   tree chain2 = gimple_call_chain (s2);
     749       217837 :   if ((chain1 && !chain2)
     750       217837 :       || (!chain1 && chain2)
     751       217837 :       || !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       495490 :   for (i = 0; i < gimple_call_num_args (s1); ++i)
     757              :     {
     758       278650 :       t1 = gimple_call_arg (s1, i);
     759       278650 :       t2 = gimple_call_arg (s2, i);
     760              : 
     761       278650 :       if (!compare_operand (t1, t2, get_operand_access_type (&map, t1)))
     762          160 :         return return_false_with_msg ("GIMPLE call operands are different");
     763       278490 :       if (i >= check_arg_types_from
     764       278490 :           && !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       216840 :   t1 = gimple_get_lhs (s1);
     771       216840 :   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       216840 :   if (gimple_call_internal_p (s1)
     776        57894 :       && t1
     777        57894 :       && t2
     778       274399 :       && !compatible_types_p (TREE_TYPE (t1), TREE_TYPE (t2)))
     779         2610 :     return return_false_with_msg ("GIMPLE internal call LHS type mismatch");
     780              : 
     781       214230 :   if (!gimple_call_internal_p (s1))
     782              :     {
     783       158946 :       cgraph_edge *e1 = cgraph_node::get (m_source_func_decl)->get_edge (s1);
     784       158946 :       cgraph_edge *e2 = cgraph_node::get (m_target_func_decl)->get_edge (s2);
     785       158946 :       class ipa_edge_args *args1 = ipa_edge_args_sum->get (e1);
     786       158946 :       class ipa_edge_args *args2 = ipa_edge_args_sum->get (e2);
     787       158946 :       if ((args1 != nullptr) != (args2 != nullptr))
     788            0 :         return return_false_with_msg ("ipa_edge_args mismatch");
     789       158946 :       if (args1)
     790              :         {
     791       106141 :           int n1 = ipa_get_cs_argument_count (args1);
     792       106141 :           int n2 = ipa_get_cs_argument_count (args2);
     793       106141 :           if (n1 != n2)
     794            0 :             return return_false_with_msg ("ipa_edge_args nargs mismatch");
     795       225295 :           for (int i = 0; i < n1; i++)
     796              :             {
     797       119169 :               struct ipa_jump_func *jf1 = ipa_get_ith_jump_func (args1, i);
     798       119169 :               struct ipa_jump_func *jf2 = ipa_get_ith_jump_func (args2, i);
     799       119169 :               if (((jf1 != nullptr) != (jf2 != nullptr))
     800       119169 :                   || (jf1 && !ipa_jump_functions_equivalent_p (jf1, jf2)))
     801           15 :                 return return_false_with_msg ("jump function mismatch");
     802              :             }
     803              :         }
     804              :     }
     805              : 
     806       214215 :   return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     807       246742 : }
     808              : 
     809              : 
     810              : /* Verifies for given GIMPLEs S1 and S2 that
     811              :    assignment statements are semantically equivalent.  */
     812              : 
     813              : bool
     814       416431 : func_checker::compare_gimple_assign (gimple *s1, gimple *s2)
     815              : {
     816       416431 :   tree arg1, arg2;
     817       416431 :   tree_code code1, code2;
     818       416431 :   unsigned i;
     819              : 
     820       416431 :   code1 = gimple_assign_rhs_code (s1);
     821       416431 :   code2 = gimple_assign_rhs_code (s2);
     822              : 
     823       416431 :   if (code1 != code2)
     824              :     return false;
     825              : 
     826       416431 :   operand_access_type_map map (5);
     827       416431 :   classify_operands (s1, &map);
     828              : 
     829      1748747 :   for (i = 0; i < gimple_num_ops (s1); i++)
     830              :     {
     831       919531 :       arg1 = gimple_op (s1, i);
     832       919531 :       arg2 = gimple_op (s2, i);
     833              : 
     834              :       /* Compare types for LHS.  */
     835       919531 :       if (i == 0 && !gimple_store_p (s1))
     836              :         {
     837       335132 :           if (!compatible_types_p (TREE_TYPE (arg1), TREE_TYPE (arg2)))
     838         1358 :             return return_false_with_msg ("GIMPLE LHS type mismatch");
     839              :         }
     840              : 
     841       918173 :       if (!compare_operand (arg1, arg2, get_operand_access_type (&map, arg1)))
     842         2288 :         return return_false_with_msg ("GIMPLE assignment operands "
     843              :                                       "are different");
     844              :     }
     845              : 
     846              : 
     847              :   return true;
     848       416431 : }
     849              : 
     850              : /* Verifies for given GIMPLEs S1 and S2 that
     851              :    condition statements are semantically equivalent.  */
     852              : 
     853              : bool
     854       116879 : func_checker::compare_gimple_cond (gimple *s1, gimple *s2)
     855              : {
     856       116879 :   tree t1, t2;
     857       116879 :   tree_code code1, code2;
     858              : 
     859       116879 :   code1 = gimple_cond_code (s1);
     860       116879 :   code2 = gimple_cond_code (s2);
     861              : 
     862       116879 :   if (code1 != code2)
     863              :     return false;
     864              : 
     865       114493 :   t1 = gimple_cond_lhs (s1);
     866       114493 :   t2 = gimple_cond_lhs (s2);
     867              : 
     868       114493 :   if (!compare_operand (t1, t2, OP_NORMAL))
     869              :     return false;
     870              : 
     871       114492 :   t1 = gimple_cond_rhs (s1);
     872       114492 :   t2 = gimple_cond_rhs (s2);
     873              : 
     874       114492 :   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         9036 : func_checker::compare_gimple_label (const glabel *g1, const glabel *g2)
     882              : {
     883         9036 :   if (m_ignore_labels)
     884              :     return true;
     885              : 
     886         9036 :   tree t1 = gimple_label_label (g1);
     887         9036 :   tree t2 = gimple_label_label (g2);
     888              : 
     889        18062 :   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          403 : func_checker::compare_gimple_switch (const gswitch *g1, const gswitch *g2)
     901              : {
     902          403 :   unsigned lsize1, lsize2, i;
     903              : 
     904          403 :   lsize1 = gimple_switch_num_labels (g1);
     905          403 :   lsize2 = gimple_switch_num_labels (g2);
     906              : 
     907          403 :   if (lsize1 != lsize2)
     908              :     return false;
     909              : 
     910          402 :   tree t1 = gimple_switch_index (g1);
     911          402 :   tree t2 = gimple_switch_index (g2);
     912              : 
     913          402 :   if (!compare_operand (t1, t2, OP_NORMAL))
     914              :     return false;
     915              : 
     916         4031 :   for (i = 0; i < lsize1; i++)
     917              :     {
     918         3630 :       tree label1 = gimple_switch_label (g1, i);
     919         3630 :       tree label2 = gimple_switch_label (g2, i);
     920              : 
     921              :       /* Label LOW and HIGH comparison.  */
     922         3630 :       tree low1 = CASE_LOW (label1);
     923         3630 :       tree low2 = CASE_LOW (label2);
     924              : 
     925         3630 :       if (!tree_int_cst_equal (low1, low2))
     926            1 :         return return_false_with_msg ("case low values are different");
     927              : 
     928         3629 :       tree high1 = CASE_HIGH (label1);
     929         3629 :       tree high2 = CASE_HIGH (label2);
     930              : 
     931         3629 :       if (!tree_int_cst_equal (high1, high2))
     932            0 :         return return_false_with_msg ("case high values are different");
     933              : 
     934         3629 :       if (TREE_CODE (label1) == CASE_LABEL_EXPR
     935         3629 :           && TREE_CODE (label2) == CASE_LABEL_EXPR)
     936              :         {
     937         3629 :           label1 = CASE_LABEL (label1);
     938         3629 :           label2 = CASE_LABEL (label2);
     939              : 
     940         3629 :           if (!compare_operand (label1, label2, OP_NORMAL))
     941            0 :             return return_false_with_msg ("switch label_exprs are different");
     942              :         }
     943            0 :       else if (!tree_int_cst_equal (label1, label2))
     944            0 :         return return_false_with_msg ("switch labels are different");
     945              :     }
     946              : 
     947              :   return true;
     948              : }
     949              : 
     950              : /* Verifies for given GIMPLE_RETURN stmts S1 and S2 that
     951              :    return statements are semantically equivalent.  */
     952              : 
     953              : bool
     954       146369 : func_checker::compare_gimple_return (const greturn *g1, const greturn *g2)
     955              : {
     956       146369 :   tree t1, t2;
     957              : 
     958       146369 :   t1 = gimple_return_retval (g1);
     959       146369 :   t2 = gimple_return_retval (g2);
     960              : 
     961              :   /* Void return type.  */
     962       146369 :   if (t1 == NULL && t2 == NULL)
     963              :     return true;
     964              :   else
     965              :     {
     966        82291 :       operand_access_type_map map (3);
     967        82291 :       return compare_operand (t1, t2, get_operand_access_type (&map, t1));
     968        82291 :     }
     969              : }
     970              : 
     971              : /* Verifies for given GIMPLEs S1 and S2 that
     972              :    goto statements are semantically equivalent.  */
     973              : 
     974              : bool
     975            0 : func_checker::compare_gimple_goto (gimple *g1, gimple *g2)
     976              : {
     977            0 :   tree dest1, dest2;
     978              : 
     979            0 :   dest1 = gimple_goto_dest (g1);
     980            0 :   dest2 = gimple_goto_dest (g2);
     981              : 
     982            0 :   if (TREE_CODE (dest1) != TREE_CODE (dest2) || TREE_CODE (dest1) != SSA_NAME)
     983              :     return false;
     984              : 
     985            0 :   return compare_operand (dest1, dest2, OP_NORMAL);
     986              : }
     987              : 
     988              : /* Verifies for given GIMPLE_RESX stmts S1 and S2 that
     989              :    resx statements are semantically equivalent.  */
     990              : 
     991              : bool
     992         4161 : func_checker::compare_gimple_resx (const gresx *g1, const gresx *g2)
     993              : {
     994         4161 :   return gimple_resx_region (g1) == gimple_resx_region (g2);
     995              : }
     996              : 
     997              : /* Verifies for given GIMPLEs S1 and S2 that ASM statements are equivalent.
     998              :    For the beginning, the pass only supports equality for
     999              :    '__asm__ __volatile__ ("", "", "", "memory")'.  */
    1000              : 
    1001              : bool
    1002         5409 : func_checker::compare_gimple_asm (const gasm *g1, const gasm *g2)
    1003              : {
    1004         5409 :   if (gimple_asm_volatile_p (g1) != gimple_asm_volatile_p (g2))
    1005              :     return false;
    1006              : 
    1007         5409 :   if (gimple_asm_basic_p (g1) != gimple_asm_basic_p (g2))
    1008              :     return false;
    1009              : 
    1010         5409 :   if (gimple_asm_inline_p (g1) != gimple_asm_inline_p (g2))
    1011              :     return false;
    1012              : 
    1013         5409 :   if (gimple_asm_ninputs (g1) != gimple_asm_ninputs (g2))
    1014              :     return false;
    1015              : 
    1016         5408 :   if (gimple_asm_noutputs (g1) != gimple_asm_noutputs (g2))
    1017              :     return false;
    1018              : 
    1019              :   /* We do not suppport goto ASM statement comparison.  */
    1020         5408 :   if (gimple_asm_nlabels (g1) || gimple_asm_nlabels (g2))
    1021              :     return false;
    1022              : 
    1023         5384 :   if (gimple_asm_nclobbers (g1) != gimple_asm_nclobbers (g2))
    1024              :     return false;
    1025              : 
    1026         5384 :   if (strcmp (gimple_asm_string (g1), gimple_asm_string (g2)) != 0)
    1027            5 :     return return_false_with_msg ("ASM strings are different");
    1028              : 
    1029         5379 :   operand_access_type_map map (5);
    1030         5379 :   classify_operands (g1, &map);
    1031              : 
    1032         5765 :   for (unsigned i = 0; i < gimple_asm_ninputs (g1); i++)
    1033              :     {
    1034          413 :       tree input1 = gimple_asm_input_op (g1, i);
    1035          413 :       tree input2 = gimple_asm_input_op (g2, i);
    1036              : 
    1037          413 :       if (!compare_asm_inputs_outputs (input1, input2, &map))
    1038           27 :         return return_false_with_msg ("ASM input is different");
    1039              :     }
    1040              : 
    1041         5856 :   for (unsigned i = 0; i < gimple_asm_noutputs (g1); i++)
    1042              :     {
    1043          506 :       tree output1 = gimple_asm_output_op (g1, i);
    1044          506 :       tree output2 = gimple_asm_output_op (g2, i);
    1045              : 
    1046          506 :       if (!compare_asm_inputs_outputs (output1, output2, &map))
    1047            2 :         return return_false_with_msg ("ASM output is different");
    1048              :     }
    1049              : 
    1050        18224 :   for (unsigned i = 0; i < gimple_asm_nclobbers (g1); i++)
    1051              :     {
    1052        12874 :       tree clobber1 = gimple_asm_clobber_op (g1, i);
    1053        12874 :       tree clobber2 = gimple_asm_clobber_op (g2, i);
    1054              : 
    1055        12874 :       if (!operand_equal_p (TREE_VALUE (clobber1), TREE_VALUE (clobber2),
    1056              :                             OEP_ONLY_CONST))
    1057            0 :         return return_false_with_msg ("ASM clobber is different");
    1058              :     }
    1059              : 
    1060              :   return true;
    1061         5379 : }
    1062              : 
    1063              : /* Helper for func_checker::classify_operands.  Record that T is a load.  */
    1064              : 
    1065              : static bool
    1066      8136069 : visit_load_store (gimple *, tree, tree t, void *data)
    1067              : {
    1068      8136069 :   func_checker::operand_access_type_map *map =
    1069              :     (func_checker::operand_access_type_map *) data;
    1070      8136069 :   map->add (t);
    1071      8136069 :   return false;
    1072              : }
    1073              : 
    1074              : /* Compute hash map determining access types of operands.  */
    1075              : 
    1076              : void
    1077     20950837 : func_checker::classify_operands (const gimple *stmt,
    1078              :                                  operand_access_type_map *map)
    1079              : {
    1080     20950837 :   walk_stmt_load_store_ops (const_cast <gimple *> (stmt),
    1081              :                             (void *)map, visit_load_store, visit_load_store);
    1082     20950837 : }
    1083              : 
    1084              : /* Return access type of a given operand.  */
    1085              : 
    1086              : func_checker::operand_access_type
    1087     62712964 : func_checker::get_operand_access_type (operand_access_type_map *map, tree t)
    1088              : {
    1089     62712964 :   if (map->contains (t))
    1090      8126159 :     return OP_MEMORY;
    1091              :   return OP_NORMAL;
    1092              : }
    1093              : 
    1094              : } // 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.