LCOV - code coverage report
Current view: top level - gcc - trans-mem.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.7 % 2306 2183
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 124 124
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Passes for transactional memory support.
       2              :    Copyright (C) 2008-2026 Free Software Foundation, Inc.
       3              :    Contributed by Richard Henderson <rth@redhat.com>
       4              :    and Aldy Hernandez <aldyh@redhat.com>.
       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 "target.h"
      27              : #include "rtl.h"
      28              : #include "tree.h"
      29              : #include "gimple.h"
      30              : #include "cfghooks.h"
      31              : #include "tree-pass.h"
      32              : #include "ssa.h"
      33              : #include "cgraph.h"
      34              : #include "gimple-pretty-print.h"
      35              : #include "diagnostic-core.h"
      36              : #include "fold-const.h"
      37              : #include "tree-eh.h"
      38              : #include "calls.h"
      39              : #include "gimplify.h"
      40              : #include "gimple-iterator.h"
      41              : #include "gimplify-me.h"
      42              : #include "gimple-walk.h"
      43              : #include "tree-cfg.h"
      44              : #include "tree-into-ssa.h"
      45              : #include "tree-inline.h"
      46              : #include "demangle.h"
      47              : #include "output.h"
      48              : #include "trans-mem.h"
      49              : #include "langhooks.h"
      50              : #include "cfgloop.h"
      51              : #include "tree-ssa-address.h"
      52              : #include "stringpool.h"
      53              : #include "attribs.h"
      54              : #include "alloc-pool.h"
      55              : #include "symbol-summary.h"
      56              : #include "symtab-thunks.h"
      57              : 
      58              : #define A_RUNINSTRUMENTEDCODE   0x0001
      59              : #define A_RUNUNINSTRUMENTEDCODE 0x0002
      60              : #define A_SAVELIVEVARIABLES     0x0004
      61              : #define A_RESTORELIVEVARIABLES  0x0008
      62              : #define A_ABORTTRANSACTION      0x0010
      63              : 
      64              : #define AR_USERABORT            0x0001
      65              : #define AR_USERRETRY            0x0002
      66              : #define AR_TMCONFLICT           0x0004
      67              : #define AR_EXCEPTIONBLOCKABORT  0x0008
      68              : #define AR_OUTERABORT           0x0010
      69              : 
      70              : #define MODE_SERIALIRREVOCABLE  0x0000
      71              : 
      72              : 
      73              : /* The representation of a transaction changes several times during the
      74              :    lowering process.  In the beginning, in the front-end we have the
      75              :    GENERIC tree TRANSACTION_EXPR.  For example,
      76              : 
      77              :         __transaction {
      78              :           local++;
      79              :           if (++global == 10)
      80              :             __tm_abort;
      81              :         }
      82              : 
      83              :   During initial gimplification (gimplify.cc) the TRANSACTION_EXPR node is
      84              :   trivially replaced with a GIMPLE_TRANSACTION node.
      85              : 
      86              :   During pass_lower_tm, we examine the body of transactions looking
      87              :   for aborts.  Transactions that do not contain an abort may be
      88              :   merged into an outer transaction.  We also add a TRY-FINALLY node
      89              :   to arrange for the transaction to be committed on any exit.
      90              : 
      91              :   [??? Think about how this arrangement affects throw-with-commit
      92              :   and throw-with-abort operations.  In this case we want the TRY to
      93              :   handle gotos, but not to catch any exceptions because the transaction
      94              :   will already be closed.]
      95              : 
      96              :         GIMPLE_TRANSACTION [label=NULL] {
      97              :           try {
      98              :             local = local + 1;
      99              :             t0 = global;
     100              :             t1 = t0 + 1;
     101              :             global = t1;
     102              :             if (t1 == 10)
     103              :               __builtin___tm_abort ();
     104              :           } finally {
     105              :             __builtin___tm_commit ();
     106              :           }
     107              :         }
     108              : 
     109              :   During pass_lower_eh, we create EH regions for the transactions,
     110              :   intermixed with the regular EH stuff.  This gives us a nice persistent
     111              :   mapping (all the way through rtl) from transactional memory operation
     112              :   back to the transaction, which allows us to get the abnormal edges
     113              :   correct to model transaction aborts and restarts:
     114              : 
     115              :         GIMPLE_TRANSACTION [label=over]
     116              :         local = local + 1;
     117              :         t0 = global;
     118              :         t1 = t0 + 1;
     119              :         global = t1;
     120              :         if (t1 == 10)
     121              :           __builtin___tm_abort ();
     122              :         __builtin___tm_commit ();
     123              :         over:
     124              : 
     125              :   This is the end of all_lowering_passes, and so is what is present
     126              :   during the IPA passes, and through all of the optimization passes.
     127              : 
     128              :   During pass_ipa_tm, we examine all GIMPLE_TRANSACTION blocks in all
     129              :   functions and mark functions for cloning.
     130              : 
     131              :   At the end of gimple optimization, before exiting SSA form,
     132              :   pass_tm_edges replaces statements that perform transactional
     133              :   memory operations with the appropriate TM builtins, and swap
     134              :   out function calls with their transactional clones.  At this
     135              :   point we introduce the abnormal transaction restart edges and
     136              :   complete lowering of the GIMPLE_TRANSACTION node.
     137              : 
     138              :         x = __builtin___tm_start (MAY_ABORT);
     139              :         eh_label:
     140              :         if (x & abort_transaction)
     141              :           goto over;
     142              :         local = local + 1;
     143              :         t0 = __builtin___tm_load (global);
     144              :         t1 = t0 + 1;
     145              :         __builtin___tm_store (&global, t1);
     146              :         if (t1 == 10)
     147              :           __builtin___tm_abort ();
     148              :         __builtin___tm_commit ();
     149              :         over:
     150              : */
     151              : 
     152              : static void *expand_regions (struct tm_region *,
     153              :                              void *(*callback)(struct tm_region *, void *),
     154              :                              void *, bool);
     155              : 
     156              : 
     157              : /* Return the attributes we want to examine for X, or NULL if it's not
     158              :    something we examine.  We look at function types, but allow pointers
     159              :    to function types and function decls and peek through.  */
     160              : 
     161              : static tree
     162        11823 : get_attrs_for (const_tree x)
     163              : {
     164        11823 :   if (x == NULL_TREE)
     165              :     return NULL_TREE;
     166              : 
     167        11823 :   switch (TREE_CODE (x))
     168              :     {
     169         7895 :     case FUNCTION_DECL:
     170         7895 :       return TYPE_ATTRIBUTES (TREE_TYPE (x));
     171              : 
     172         3904 :     default:
     173         3904 :       if (TYPE_P (x))
     174              :         return NULL_TREE;
     175         3904 :       x = TREE_TYPE (x);
     176         3904 :       if (TREE_CODE (x) != POINTER_TYPE)
     177              :         return NULL_TREE;
     178              :       /* FALLTHRU */
     179              : 
     180         3928 :     case POINTER_TYPE:
     181         3928 :       x = TREE_TYPE (x);
     182         3928 :       if (TREE_CODE (x) != FUNCTION_TYPE && TREE_CODE (x) != METHOD_TYPE)
     183              :         return NULL_TREE;
     184              :       /* FALLTHRU */
     185              : 
     186         3928 :     case FUNCTION_TYPE:
     187         3928 :     case METHOD_TYPE:
     188         3928 :       return TYPE_ATTRIBUTES (x);
     189              :     }
     190              : }
     191              : 
     192              : /* Return true if X has been marked TM_PURE.  */
     193              : 
     194              : bool
     195      9567394 : is_tm_pure (const_tree x)
     196              : {
     197      9567394 :   unsigned flags;
     198              : 
     199      9567394 :   switch (TREE_CODE (x))
     200              :     {
     201              :     case FUNCTION_DECL:
     202              :     case FUNCTION_TYPE:
     203              :     case METHOD_TYPE:
     204              :       break;
     205              : 
     206          238 :     default:
     207          238 :       if (TYPE_P (x))
     208              :         return false;
     209          238 :       x = TREE_TYPE (x);
     210          238 :       if (TREE_CODE (x) != POINTER_TYPE)
     211              :         return false;
     212              :       /* FALLTHRU */
     213              : 
     214          238 :     case POINTER_TYPE:
     215          238 :       x = TREE_TYPE (x);
     216          238 :       if (TREE_CODE (x) != FUNCTION_TYPE && TREE_CODE (x) != METHOD_TYPE)
     217              :         return false;
     218              :       break;
     219              :     }
     220              : 
     221      9567394 :   flags = flags_from_decl_or_type (x);
     222      9567394 :   return (flags & ECF_TM_PURE) != 0;
     223              : }
     224              : 
     225              : /* Return true if X has been marked TM_IRREVOCABLE.  */
     226              : 
     227              : static bool
     228         2005 : is_tm_irrevocable (tree x)
     229              : {
     230         2005 :   tree attrs = get_attrs_for (x);
     231              : 
     232         2005 :   if (attrs && lookup_attribute ("transaction_unsafe", attrs))
     233              :     return true;
     234              : 
     235              :   /* A call to the irrevocable builtin is by definition,
     236              :      irrevocable.  */
     237         1969 :   if (TREE_CODE (x) == ADDR_EXPR)
     238         1161 :     x = TREE_OPERAND (x, 0);
     239         1969 :   if (TREE_CODE (x) == FUNCTION_DECL
     240         1969 :       && fndecl_built_in_p (x, BUILT_IN_TM_IRREVOCABLE))
     241              :     return true;
     242              : 
     243              :   return false;
     244              : }
     245              : 
     246              : /* Return true if X has been marked TM_SAFE.  */
     247              : 
     248              : bool
     249         4054 : is_tm_safe (const_tree x)
     250              : {
     251         4054 :   if (flag_tm)
     252              :     {
     253         4054 :       tree attrs = get_attrs_for (x);
     254         4054 :       if (attrs)
     255              :         {
     256         1341 :           if (lookup_attribute ("transaction_safe", attrs))
     257              :             return true;
     258          515 :           if (lookup_attribute ("transaction_may_cancel_outer", attrs))
     259              :             return true;
     260              :         }
     261              :     }
     262              :   return false;
     263              : }
     264              : 
     265              : /* Return true if CALL is const, or tm_pure.  */
     266              : 
     267              : static bool
     268         5404 : is_tm_pure_call (gimple *call)
     269              : {
     270         1588 :   return (gimple_call_flags (call) & (ECF_CONST | ECF_TM_PURE)) != 0;
     271              : }
     272              : 
     273              : /* Return true if X has been marked TM_CALLABLE.  */
     274              : 
     275              : static bool
     276         2452 : is_tm_callable (tree x)
     277              : {
     278         2452 :   tree attrs = get_attrs_for (x);
     279         2452 :   if (attrs)
     280              :     {
     281          704 :       if (lookup_attribute ("transaction_callable", attrs))
     282              :         return true;
     283          573 :       if (lookup_attribute ("transaction_safe", attrs))
     284              :         return true;
     285          105 :       if (lookup_attribute ("transaction_may_cancel_outer", attrs))
     286              :         return true;
     287              :     }
     288              :   return false;
     289              : }
     290              : 
     291              : /* Return true if X has been marked TRANSACTION_MAY_CANCEL_OUTER.  */
     292              : 
     293              : bool
     294         3312 : is_tm_may_cancel_outer (tree x)
     295              : {
     296         3312 :   tree attrs = get_attrs_for (x);
     297         3312 :   if (attrs)
     298          866 :     return lookup_attribute ("transaction_may_cancel_outer", attrs) != NULL;
     299              :   return false;
     300              : }
     301              : 
     302              : /* Return true for built in functions that "end" a transaction.   */
     303              : 
     304              : bool
     305       433321 : is_tm_ending_fndecl (tree fndecl)
     306              : {
     307       433321 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     308       332294 :     switch (DECL_FUNCTION_CODE (fndecl))
     309              :       {
     310         2746 :       case BUILT_IN_TM_COMMIT:
     311         2746 :       case BUILT_IN_TM_COMMIT_EH:
     312         2746 :       case BUILT_IN_TM_ABORT:
     313         2746 :       case BUILT_IN_TM_IRREVOCABLE:
     314         2746 :         return true;
     315              :       default:
     316              :         break;
     317              :       }
     318              : 
     319              :   return false;
     320              : }
     321              : 
     322              : /* Return true if STMT is a built in function call that "ends" a
     323              :    transaction.  */
     324              : 
     325              : bool
     326       487082 : is_tm_ending (gimple *stmt)
     327              : {
     328       487082 :   tree fndecl;
     329              : 
     330       487082 :   if (gimple_code (stmt) != GIMPLE_CALL)
     331              :     return false;
     332              : 
     333       428943 :   fndecl = gimple_call_fndecl (stmt);
     334       428943 :   return (fndecl != NULL_TREE
     335       428943 :           && is_tm_ending_fndecl (fndecl));
     336              : }
     337              : 
     338              : /* Return true if STMT is a TM load.  */
     339              : 
     340              : static bool
     341         2531 : is_tm_load (gimple *stmt)
     342              : {
     343         2531 :   tree fndecl;
     344              : 
     345         2531 :   if (gimple_code (stmt) != GIMPLE_CALL)
     346              :     return false;
     347              : 
     348         1331 :   fndecl = gimple_call_fndecl (stmt);
     349         1331 :   return (fndecl
     350         1319 :           && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
     351         2555 :           && BUILTIN_TM_LOAD_P (DECL_FUNCTION_CODE (fndecl)));
     352              : }
     353              : 
     354              : /* Same as above, but for simple TM loads, that is, not the
     355              :    after-write, after-read, etc optimized variants.  */
     356              : 
     357              : static bool
     358         1967 : is_tm_simple_load (gimple *stmt)
     359              : {
     360         1967 :   tree fndecl;
     361              : 
     362         1967 :   if (gimple_code (stmt) != GIMPLE_CALL)
     363              :     return false;
     364              : 
     365          767 :   fndecl = gimple_call_fndecl (stmt);
     366          767 :   if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     367              :     {
     368          660 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
     369          660 :       return (fcode == BUILT_IN_TM_LOAD_1
     370          660 :               || fcode == BUILT_IN_TM_LOAD_2
     371              :               || fcode == BUILT_IN_TM_LOAD_4
     372              :               || fcode == BUILT_IN_TM_LOAD_8
     373              :               || fcode == BUILT_IN_TM_LOAD_FLOAT
     374              :               || fcode == BUILT_IN_TM_LOAD_DOUBLE
     375              :               || fcode == BUILT_IN_TM_LOAD_LDOUBLE
     376              :               || fcode == BUILT_IN_TM_LOAD_M64
     377          443 :               || fcode == BUILT_IN_TM_LOAD_M128
     378          660 :               || fcode == BUILT_IN_TM_LOAD_M256);
     379              :     }
     380              :   return false;
     381              : }
     382              : 
     383              : /* Return true if STMT is a TM store.  */
     384              : 
     385              : static bool
     386         2189 : is_tm_store (gimple *stmt)
     387              : {
     388         2189 :   tree fndecl;
     389              : 
     390         2189 :   if (gimple_code (stmt) != GIMPLE_CALL)
     391              :     return false;
     392              : 
     393          989 :   fndecl = gimple_call_fndecl (stmt);
     394          989 :   return (fndecl
     395          977 :           && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)
     396         1871 :           && BUILTIN_TM_STORE_P (DECL_FUNCTION_CODE (fndecl)));
     397              : }
     398              : 
     399              : /* Same as above, but for simple TM stores, that is, not the
     400              :    after-write, after-read, etc optimized variants.  */
     401              : 
     402              : static bool
     403         1746 : is_tm_simple_store (gimple *stmt)
     404              : {
     405         1746 :   tree fndecl;
     406              : 
     407         1746 :   if (gimple_code (stmt) != GIMPLE_CALL)
     408              :     return false;
     409              : 
     410          546 :   fndecl = gimple_call_fndecl (stmt);
     411          546 :   if (fndecl
     412          546 :       && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL))
     413              :     {
     414          439 :       enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
     415          439 :       return (fcode == BUILT_IN_TM_STORE_1
     416          439 :               || fcode == BUILT_IN_TM_STORE_2
     417              :               || fcode == BUILT_IN_TM_STORE_4
     418              :               || fcode == BUILT_IN_TM_STORE_8
     419              :               || fcode == BUILT_IN_TM_STORE_FLOAT
     420              :               || fcode == BUILT_IN_TM_STORE_DOUBLE
     421              :               || fcode == BUILT_IN_TM_STORE_LDOUBLE
     422              :               || fcode == BUILT_IN_TM_STORE_M64
     423          329 :               || fcode == BUILT_IN_TM_STORE_M128
     424          439 :               || fcode == BUILT_IN_TM_STORE_M256);
     425              :     }
     426              :   return false;
     427              : }
     428              : 
     429              : /* Return true if FNDECL is BUILT_IN_TM_ABORT.  */
     430              : 
     431              : static bool
     432         1099 : is_tm_abort (tree fndecl)
     433              : {
     434          467 :   return (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_TM_ABORT));
     435              : }
     436              : 
     437              : /* Build a GENERIC tree for a user abort.  This is called by front ends
     438              :    while transforming the __tm_abort statement.  */
     439              : 
     440              : tree
     441           32 : build_tm_abort_call (location_t loc, bool is_outer)
     442              : {
     443           32 :   return build_call_expr_loc (loc, builtin_decl_explicit (BUILT_IN_TM_ABORT), 1,
     444              :                               build_int_cst (integer_type_node,
     445              :                                              AR_USERABORT
     446           59 :                                              | (is_outer ? AR_OUTERABORT : 0)));
     447              : }
     448              : 
     449              : /* Map for arbitrary function replacement under TM, as created
     450              :    by the tm_wrap attribute.  */
     451              : 
     452              : struct tm_wrapper_hasher : ggc_cache_ptr_hash<tree_map>
     453              : {
     454          378 :   static inline hashval_t hash (tree_map *m) { return m->hash; }
     455              :   static inline bool
     456          954 :   equal (tree_map *a, tree_map *b)
     457              :   {
     458          954 :     return a->base.from == b->base.from;
     459              :   }
     460              : 
     461              :   static int
     462           10 :   keep_cache_entry (tree_map *&m)
     463              :   {
     464           10 :     return ggc_marked_p (m->base.from);
     465              :   }
     466              : };
     467              : 
     468              : static GTY((cache)) hash_table<tm_wrapper_hasher> *tm_wrap_map;
     469              : 
     470              : void
     471          116 : record_tm_replacement (tree from, tree to)
     472              : {
     473          116 :   struct tree_map **slot, *h;
     474              : 
     475              :   /* Do not inline wrapper functions that will get replaced in the TM
     476              :      pass.
     477              : 
     478              :      Suppose you have foo() that will get replaced into tmfoo().  Make
     479              :      sure the inliner doesn't try to outsmart us and inline foo()
     480              :      before we get a chance to do the TM replacement.  */
     481          116 :   DECL_UNINLINABLE (from) = 1;
     482              : 
     483          116 :   if (tm_wrap_map == NULL)
     484           50 :     tm_wrap_map = hash_table<tm_wrapper_hasher>::create_ggc (32);
     485              : 
     486          116 :   h = ggc_alloc<tree_map> ();
     487          116 :   h->hash = htab_hash_pointer (from);
     488          116 :   h->base.from = from;
     489          116 :   h->to = to;
     490              : 
     491          116 :   slot = tm_wrap_map->find_slot_with_hash (h, h->hash, INSERT);
     492          116 :   *slot = h;
     493          116 : }
     494              : 
     495              : /* Return a TM-aware replacement function for DECL.  */
     496              : 
     497              : static tree
     498         5010 : find_tm_replacement_function (tree fndecl)
     499              : {
     500         5010 :   if (tm_wrap_map)
     501              :     {
     502         1494 :       struct tree_map *h, in;
     503              : 
     504         1494 :       in.base.from = fndecl;
     505         1494 :       in.hash = htab_hash_pointer (fndecl);
     506         1494 :       h = tm_wrap_map->find_with_hash (&in, in.hash);
     507         1494 :       if (h)
     508          555 :         return h->to;
     509              :     }
     510              : 
     511              :   /* ??? We may well want TM versions of most of the common <string.h>
     512              :      functions.  For now, we've already these two defined.  */
     513              :   /* Adjust expand_call_tm() attributes as necessary for the cases
     514              :      handled here:  */
     515         4455 :   if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL)
     516          914 :     switch (DECL_FUNCTION_CODE (fndecl))
     517              :       {
     518           53 :       case BUILT_IN_MEMCPY:
     519           53 :         return builtin_decl_explicit (BUILT_IN_TM_MEMCPY);
     520           33 :       case BUILT_IN_MEMMOVE:
     521           33 :         return builtin_decl_explicit (BUILT_IN_TM_MEMMOVE);
     522           22 :       case BUILT_IN_MEMSET:
     523           22 :         return builtin_decl_explicit (BUILT_IN_TM_MEMSET);
     524              :       default:
     525              :         return NULL;
     526              :       }
     527              : 
     528              :   return NULL;
     529              : }
     530              : 
     531              : /* When appropriate, record TM replacement for memory allocation functions.
     532              : 
     533              :    FROM is the FNDECL to wrap.  */
     534              : void
     535         3982 : tm_malloc_replacement (tree from)
     536              : {
     537         3982 :   const char *str;
     538         3982 :   tree to;
     539              : 
     540         3982 :   if (TREE_CODE (from) != FUNCTION_DECL)
     541              :     return;
     542              : 
     543              :   /* If we have a previous replacement, the user must be explicitly
     544              :      wrapping malloc/calloc/free.  They better know what they're
     545              :      doing... */
     546         2402 :   if (find_tm_replacement_function (from))
     547              :     return;
     548              : 
     549         2299 :   str = IDENTIFIER_POINTER (DECL_NAME (from));
     550              : 
     551         2299 :   if (!strcmp (str, "malloc"))
     552           16 :     to = builtin_decl_explicit (BUILT_IN_TM_MALLOC);
     553         2283 :   else if (!strcmp (str, "calloc"))
     554            4 :     to = builtin_decl_explicit (BUILT_IN_TM_CALLOC);
     555         2279 :   else if (!strcmp (str, "free"))
     556            4 :     to = builtin_decl_explicit (BUILT_IN_TM_FREE);
     557              :   else
     558              :     return;
     559              : 
     560           24 :   TREE_NOTHROW (to) = 0;
     561              : 
     562           24 :   record_tm_replacement (from, to);
     563              : }
     564              : 
     565              : /* Diagnostics for tm_safe functions/regions.  Called by the front end
     566              :    once we've lowered the function to high-gimple.  */
     567              : 
     568              : /* Subroutine of diagnose_tm_safe_errors, called through walk_gimple_seq.
     569              :    Process exactly one statement.  WI->INFO is set to non-null when in
     570              :    the context of a tm_safe function, and null for a __transaction block.  */
     571              : 
     572              : #define DIAG_TM_OUTER           1
     573              : #define DIAG_TM_SAFE            2
     574              : #define DIAG_TM_RELAXED         4
     575              : 
     576              : struct diagnose_tm
     577              : {
     578              :   unsigned int summary_flags : 8;
     579              :   unsigned int block_flags : 8;
     580              :   unsigned int func_flags : 8;
     581              :   unsigned int saw_volatile : 1;
     582              :   gimple *stmt;
     583              : };
     584              : 
     585              : /* Return true if T is a volatile lvalue of some kind.  */
     586              : 
     587              : static bool
     588        25288 : volatile_lvalue_p (tree t)
     589              : {
     590        25288 :   return ((SSA_VAR_P (t) || REFERENCE_CLASS_P (t))
     591        13466 :           && TREE_THIS_VOLATILE (TREE_TYPE (t)));
     592              : }
     593              : 
     594              : /* Tree callback function for diagnose_tm pass.  */
     595              : 
     596              : static tree
     597        22447 : diagnose_tm_1_op (tree *tp, int *walk_subtrees, void *data)
     598              : {
     599        22447 :   struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
     600        22447 :   struct diagnose_tm *d = (struct diagnose_tm *) wi->info;
     601              : 
     602        22447 :   if (TYPE_P (*tp))
     603           36 :     *walk_subtrees = false;
     604        22411 :   else if (volatile_lvalue_p (*tp)
     605        22411 :            && !d->saw_volatile)
     606              :     {
     607           22 :       d->saw_volatile = 1;
     608           22 :       if (d->block_flags & DIAG_TM_SAFE)
     609            2 :         error_at (gimple_location (d->stmt),
     610              :                   "invalid use of volatile lvalue inside transaction");
     611           20 :       else if (d->func_flags & DIAG_TM_SAFE)
     612            4 :         error_at (gimple_location (d->stmt),
     613              :                   "invalid use of volatile lvalue inside %<transaction_safe%> "
     614              :                   "function");
     615              :     }
     616              : 
     617        22447 :   return NULL_TREE;
     618              : }
     619              : 
     620              : static inline bool
     621         1267 : is_tm_safe_or_pure (const_tree x)
     622              : {
     623         1267 :   return is_tm_safe (x) || is_tm_pure (x);
     624              : }
     625              : 
     626              : static tree
     627        11356 : diagnose_tm_1 (gimple_stmt_iterator *gsi, bool *handled_ops_p,
     628              :                     struct walk_stmt_info *wi)
     629              : {
     630        11356 :   gimple *stmt = gsi_stmt (*gsi);
     631        11356 :   struct diagnose_tm *d = (struct diagnose_tm *) wi->info;
     632              : 
     633              :   /* Save stmt for use in leaf analysis.  */
     634        11356 :   d->stmt = stmt;
     635              : 
     636        11356 :   switch (gimple_code (stmt))
     637              :     {
     638         2209 :     case GIMPLE_CALL:
     639         2209 :       {
     640         2209 :         if (gimple_call_internal_p (stmt))
     641              :           break;
     642              : 
     643         2165 :         tree fn = gimple_call_fn (stmt);
     644              : 
     645         2165 :         if ((d->summary_flags & DIAG_TM_OUTER) == 0
     646         2165 :             && is_tm_may_cancel_outer (fn))
     647           24 :           error_at (gimple_location (stmt),
     648              :                     "%<transaction_may_cancel_outer%> function call not within"
     649              :                     " outer transaction or %<transaction_may_cancel_outer%>");
     650              : 
     651         2165 :         if (d->summary_flags & DIAG_TM_SAFE)
     652              :           {
     653          624 :             bool is_safe, direct_call_p;
     654          624 :             tree replacement;
     655              : 
     656          624 :             if (TREE_CODE (fn) == ADDR_EXPR
     657          624 :                 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
     658              :               {
     659          570 :                 direct_call_p = true;
     660          570 :                 replacement = TREE_OPERAND (fn, 0);
     661          570 :                 replacement = find_tm_replacement_function (replacement);
     662          570 :                 if (replacement)
     663          158 :                   fn = replacement;
     664              :               }
     665              :             else
     666              :               {
     667              :                 direct_call_p = false;
     668              :                 replacement = NULL_TREE;
     669              :               }
     670              : 
     671          624 :             if (is_tm_safe_or_pure (fn))
     672              :               is_safe = true;
     673          190 :             else if (is_tm_callable (fn) || is_tm_irrevocable (fn))
     674              :               {
     675              :                 /* A function explicitly marked transaction_callable as
     676              :                    opposed to transaction_safe is being defined to be
     677              :                    unsafe as part of its ABI, regardless of its contents.  */
     678              :                 is_safe = false;
     679              :               }
     680          157 :             else if (direct_call_p)
     681              :               {
     682          144 :                 if (IS_TYPE_OR_DECL_P (fn)
     683          144 :                     && flags_from_decl_or_type (fn) & ECF_TM_BUILTIN)
     684              :                   is_safe = true;
     685          138 :                 else if (replacement)
     686              :                   {
     687              :                     /* ??? At present we've been considering replacements
     688              :                        merely transaction_callable, and therefore might
     689              :                        enter irrevocable.  The tm_wrap attribute has not
     690              :                        yet made it into the new language spec.  */
     691              :                     is_safe = false;
     692              :                   }
     693              :                 else
     694              :                   {
     695              :                     /* ??? Diagnostics for unmarked direct calls moved into
     696              :                        the IPA pass.  Section 3.2 of the spec details how
     697              :                        functions not marked should be considered "implicitly
     698              :                        safe" based on having examined the function body.  */
     699              :                     is_safe = true;
     700              :                   }
     701              :               }
     702              :             else
     703              :               {
     704              :                 /* An unmarked indirect call.  Consider it unsafe even
     705              :                    though optimization may yet figure out how to inline.  */
     706              :                 is_safe = false;
     707              :               }
     708              : 
     709              :             if (!is_safe)
     710              :               {
     711           46 :                 if (TREE_CODE (fn) == ADDR_EXPR)
     712           17 :                   fn = TREE_OPERAND (fn, 0);
     713           46 :                 if (d->block_flags & DIAG_TM_SAFE)
     714              :                   {
     715            1 :                     if (direct_call_p)
     716            1 :                       error_at (gimple_location (stmt),
     717              :                                 "unsafe function call %qD within "
     718              :                                 "atomic transaction", fn);
     719              :                     else
     720              :                       {
     721            0 :                         if ((!DECL_P (fn) || DECL_NAME (fn))
     722            0 :                             && TREE_CODE (fn) != SSA_NAME)
     723            0 :                           error_at (gimple_location (stmt),
     724              :                                     "unsafe function call %qE within "
     725              :                                     "atomic transaction", fn);
     726              :                         else
     727            0 :                           error_at (gimple_location (stmt),
     728              :                                     "unsafe indirect function call within "
     729              :                                     "atomic transaction");
     730              :                       }
     731              :                   }
     732              :                 else
     733              :                   {
     734           45 :                     if (direct_call_p)
     735           16 :                       error_at (gimple_location (stmt),
     736              :                                 "unsafe function call %qD within "
     737              :                                 "%<transaction_safe%> function", fn);
     738              :                     else
     739              :                       {
     740            0 :                         if ((!DECL_P (fn) || DECL_NAME (fn))
     741           29 :                             && TREE_CODE (fn) != SSA_NAME)
     742            3 :                           error_at (gimple_location (stmt),
     743              :                                     "unsafe function call %qE within "
     744              :                                     "%<transaction_safe%> function", fn);
     745              :                         else
     746           26 :                           error_at (gimple_location (stmt),
     747              :                                     "unsafe indirect function call within "
     748              :                                     "%<transaction_safe%> function");
     749              :                       }
     750              :                   }
     751              :               }
     752              :           }
     753              :       }
     754              :       break;
     755              : 
     756           52 :     case GIMPLE_ASM:
     757              :       /* ??? We ought to come up with a way to add attributes to
     758              :          asm statements, and then add "transaction_safe" to it.
     759              :          Either that or get the language spec to resurrect __tm_waiver.  */
     760           52 :       if (d->block_flags & DIAG_TM_SAFE)
     761            0 :         error_at (gimple_location (stmt),
     762              :                   "%<asm%> not allowed in atomic transaction");
     763           52 :       else if (d->func_flags & DIAG_TM_SAFE)
     764           16 :         error_at (gimple_location (stmt),
     765              :                   "%<asm%> not allowed in %<transaction_safe%> function");
     766              :       break;
     767              : 
     768          474 :     case GIMPLE_TRANSACTION:
     769          474 :       {
     770          474 :         gtransaction *trans_stmt = as_a <gtransaction *> (stmt);
     771          474 :         unsigned char inner_flags = DIAG_TM_SAFE;
     772              : 
     773          474 :         if (gimple_transaction_subcode (trans_stmt) & GTMA_IS_RELAXED)
     774              :           {
     775           79 :             if (d->block_flags & DIAG_TM_SAFE)
     776            0 :               error_at (gimple_location (stmt),
     777              :                         "relaxed transaction in atomic transaction");
     778           79 :             else if (d->func_flags & DIAG_TM_SAFE)
     779            0 :               error_at (gimple_location (stmt),
     780              :                         "relaxed transaction in %<transaction_safe%> function");
     781              :             inner_flags = DIAG_TM_RELAXED;
     782              :           }
     783          395 :         else if (gimple_transaction_subcode (trans_stmt) & GTMA_IS_OUTER)
     784              :           {
     785           31 :             if (d->block_flags)
     786            0 :               error_at (gimple_location (stmt),
     787              :                         "outer transaction in transaction");
     788           31 :             else if (d->func_flags & DIAG_TM_OUTER)
     789            4 :               error_at (gimple_location (stmt),
     790              :                         "outer transaction in "
     791              :                         "%<transaction_may_cancel_outer%> function");
     792           27 :             else if (d->func_flags & DIAG_TM_SAFE)
     793            0 :               error_at (gimple_location (stmt),
     794              :                         "outer transaction in %<transaction_safe%> function");
     795              :             inner_flags |= DIAG_TM_OUTER;
     796              :           }
     797              : 
     798          474 :         *handled_ops_p = true;
     799          474 :         if (gimple_transaction_body (trans_stmt))
     800              :           {
     801          474 :             struct walk_stmt_info wi_inner;
     802          474 :             struct diagnose_tm d_inner;
     803              : 
     804          474 :             memset (&d_inner, 0, sizeof (d_inner));
     805          474 :             d_inner.func_flags = d->func_flags;
     806          474 :             d_inner.block_flags = d->block_flags | inner_flags;
     807          474 :             d_inner.summary_flags = d_inner.func_flags | d_inner.block_flags;
     808              : 
     809          474 :             memset (&wi_inner, 0, sizeof (wi_inner));
     810          474 :             wi_inner.info = &d_inner;
     811              : 
     812          474 :             walk_gimple_seq (gimple_transaction_body (trans_stmt),
     813              :                              diagnose_tm_1, diagnose_tm_1_op, &wi_inner);
     814              :           }
     815              :       }
     816              :       break;
     817              : 
     818              :     default:
     819              :       break;
     820              :     }
     821              : 
     822        11356 :   return NULL_TREE;
     823              : }
     824              : 
     825              : static unsigned int
     826         1288 : diagnose_tm_blocks (void)
     827              : {
     828         1288 :   struct walk_stmt_info wi;
     829         1288 :   struct diagnose_tm d;
     830              : 
     831         1288 :   memset (&d, 0, sizeof (d));
     832         1288 :   if (is_tm_may_cancel_outer (current_function_decl))
     833           19 :     d.func_flags = DIAG_TM_OUTER | DIAG_TM_SAFE;
     834         1269 :   else if (is_tm_safe (current_function_decl))
     835          155 :     d.func_flags = DIAG_TM_SAFE;
     836         1288 :   d.summary_flags = d.func_flags;
     837              : 
     838         1288 :   memset (&wi, 0, sizeof (wi));
     839         1288 :   wi.info = &d;
     840              : 
     841         1288 :   walk_gimple_seq (gimple_body (current_function_decl),
     842              :                    diagnose_tm_1, diagnose_tm_1_op, &wi);
     843              : 
     844         1288 :   return 0;
     845              : }
     846              : 
     847              : namespace {
     848              : 
     849              : const pass_data pass_data_diagnose_tm_blocks =
     850              : {
     851              :   GIMPLE_PASS, /* type */
     852              :   "*diagnose_tm_blocks", /* name */
     853              :   OPTGROUP_NONE, /* optinfo_flags */
     854              :   TV_TRANS_MEM, /* tv_id */
     855              :   PROP_gimple_any, /* properties_required */
     856              :   0, /* properties_provided */
     857              :   0, /* properties_destroyed */
     858              :   0, /* todo_flags_start */
     859              :   0, /* todo_flags_finish */
     860              : };
     861              : 
     862              : class pass_diagnose_tm_blocks : public gimple_opt_pass
     863              : {
     864              : public:
     865       285722 :   pass_diagnose_tm_blocks (gcc::context *ctxt)
     866       571444 :     : gimple_opt_pass (pass_data_diagnose_tm_blocks, ctxt)
     867              :   {}
     868              : 
     869              :   /* opt_pass methods: */
     870      2869218 :   bool gate (function *) final override { return flag_tm; }
     871         1288 :   unsigned int execute (function *) final override
     872              :   {
     873         1288 :     return diagnose_tm_blocks ();
     874              :   }
     875              : 
     876              : }; // class pass_diagnose_tm_blocks
     877              : 
     878              : } // anon namespace
     879              : 
     880              : gimple_opt_pass *
     881       285722 : make_pass_diagnose_tm_blocks (gcc::context *ctxt)
     882              : {
     883       285722 :   return new pass_diagnose_tm_blocks (ctxt);
     884              : }
     885              : 
     886              : /* Instead of instrumenting thread private memory, we save the
     887              :    addresses in a log which we later use to save/restore the addresses
     888              :    upon transaction start/restart.
     889              : 
     890              :    The log is keyed by address, where each element contains individual
     891              :    statements among different code paths that perform the store.
     892              : 
     893              :    This log is later used to generate either plain save/restore of the
     894              :    addresses upon transaction start/restart, or calls to the ITM_L*
     895              :    logging functions.
     896              : 
     897              :    So for something like:
     898              : 
     899              :        struct large { int x[1000]; };
     900              :        struct large lala = { 0 };
     901              :        __transaction {
     902              :          lala.x[i] = 123;
     903              :          ...
     904              :        }
     905              : 
     906              :    We can either save/restore:
     907              : 
     908              :        lala = { 0 };
     909              :        trxn = _ITM_startTransaction ();
     910              :        if (trxn & a_saveLiveVariables)
     911              :          tmp_lala1 = lala.x[i];
     912              :        else if (a & a_restoreLiveVariables)
     913              :          lala.x[i] = tmp_lala1;
     914              : 
     915              :    or use the logging functions:
     916              : 
     917              :        lala = { 0 };
     918              :        trxn = _ITM_startTransaction ();
     919              :        _ITM_LU4 (&lala.x[i]);
     920              : 
     921              :    Obviously, if we use _ITM_L* to log, we prefer to call _ITM_L* as
     922              :    far up the dominator tree to shadow all of the writes to a given
     923              :    location (thus reducing the total number of logging calls), but not
     924              :    so high as to be called on a path that does not perform a
     925              :    write.  */
     926              : 
     927              : /* One individual log entry.  We may have multiple statements for the
     928              :    same location if neither dominate each other (on different
     929              :    execution paths).  */
     930              : struct tm_log_entry
     931              : {
     932              :   /* Address to save.  */
     933              :   tree addr;
     934              :   /* Entry block for the transaction this address occurs in.  */
     935              :   basic_block entry_block;
     936              :   /* Dominating statements the store occurs in.  */
     937              :   vec<gimple *> stmts;
     938              :   /* Initially, while we are building the log, we place a nonzero
     939              :      value here to mean that this address *will* be saved with a
     940              :      save/restore sequence.  Later, when generating the save sequence
     941              :      we place the SSA temp generated here.  */
     942              :   tree save_var;
     943              : };
     944              : 
     945              : 
     946              : /* Log entry hashtable helpers.  */
     947              : 
     948              : struct log_entry_hasher : pointer_hash <tm_log_entry>
     949              : {
     950              :   static inline hashval_t hash (const tm_log_entry *);
     951              :   static inline bool equal (const tm_log_entry *, const tm_log_entry *);
     952              :   static inline void remove (tm_log_entry *);
     953              : };
     954              : 
     955              : /* Htab support.  Return hash value for a `tm_log_entry'.  */
     956              : inline hashval_t
     957           85 : log_entry_hasher::hash (const tm_log_entry *log)
     958              : {
     959           85 :   return iterative_hash_expr (log->addr, 0);
     960              : }
     961              : 
     962              : /* Htab support.  Return true if two log entries are the same.  */
     963              : inline bool
     964           37 : log_entry_hasher::equal (const tm_log_entry *log1, const tm_log_entry *log2)
     965              : {
     966              :   /* FIXME:
     967              : 
     968              :      rth: I suggest that we get rid of the component refs etc.
     969              :      I.e. resolve the reference to base + offset.
     970              : 
     971              :      We may need to actually finish a merge with mainline for this,
     972              :      since we'd like to be presented with Richi's MEM_REF_EXPRs more
     973              :      often than not.  But in the meantime your tm_log_entry could save
     974              :      the results of get_inner_reference.
     975              : 
     976              :      See: g++.dg/tm/pr46653.C
     977              :   */
     978              : 
     979              :   /* Special case plain equality because operand_equal_p() below will
     980              :      return FALSE if the addresses are equal but they have
     981              :      side-effects (e.g. a volatile address).  */
     982           37 :   if (log1->addr == log2->addr)
     983              :     return true;
     984              : 
     985            1 :   return operand_equal_p (log1->addr, log2->addr, 0);
     986              : }
     987              : 
     988              : /* Htab support.  Free one tm_log_entry.  */
     989              : inline void
     990           24 : log_entry_hasher::remove (tm_log_entry *lp)
     991              : {
     992           24 :   lp->stmts.release ();
     993           24 :   free (lp);
     994           24 : }
     995              : 
     996              : 
     997              : /* The actual log.  */
     998              : static hash_table<log_entry_hasher> *tm_log;
     999              : 
    1000              : /* Addresses to log with a save/restore sequence.  These should be in
    1001              :    dominator order.  */
    1002              : static vec<tree> tm_log_save_addresses;
    1003              : 
    1004              : enum thread_memory_type
    1005              :   {
    1006              :     mem_non_local = 0,
    1007              :     mem_thread_local,
    1008              :     mem_transaction_local,
    1009              :     mem_max
    1010              :   };
    1011              : 
    1012              : struct tm_new_mem_map
    1013              : {
    1014              :   /* SSA_NAME being dereferenced.  */
    1015              :   tree val;
    1016              :   enum thread_memory_type local_new_memory;
    1017              : };
    1018              : 
    1019              : /* Hashtable helpers.  */
    1020              : 
    1021              : struct tm_mem_map_hasher : free_ptr_hash <tm_new_mem_map>
    1022              : {
    1023              :   static inline hashval_t hash (const tm_new_mem_map *);
    1024              :   static inline bool equal (const tm_new_mem_map *, const tm_new_mem_map *);
    1025              : };
    1026              : 
    1027              : inline hashval_t
    1028          287 : tm_mem_map_hasher::hash (const tm_new_mem_map *v)
    1029              : {
    1030          287 :   return (intptr_t)v->val >> 4;
    1031              : }
    1032              : 
    1033              : inline bool
    1034          140 : tm_mem_map_hasher::equal (const tm_new_mem_map *v, const tm_new_mem_map *c)
    1035              : {
    1036          140 :   return v->val == c->val;
    1037              : }
    1038              : 
    1039              : /* Map for an SSA_NAME originally pointing to a non aliased new piece
    1040              :    of memory (malloc, alloc, etc).  */
    1041              : static hash_table<tm_mem_map_hasher> *tm_new_mem_hash;
    1042              : 
    1043              : /* Initialize logging data structures.  */
    1044              : static void
    1045          474 : tm_log_init (void)
    1046              : {
    1047          474 :   tm_log = new hash_table<log_entry_hasher> (10);
    1048          474 :   tm_new_mem_hash = new hash_table<tm_mem_map_hasher> (5);
    1049          474 :   tm_log_save_addresses.create (5);
    1050          474 : }
    1051              : 
    1052              : /* Free logging data structures.  */
    1053              : static void
    1054          474 : tm_log_delete (void)
    1055              : {
    1056          474 :   delete tm_log;
    1057          474 :   tm_log = NULL;
    1058          474 :   delete tm_new_mem_hash;
    1059          474 :   tm_new_mem_hash = NULL;
    1060          474 :   tm_log_save_addresses.release ();
    1061          474 : }
    1062              : 
    1063              : /* Return true if MEM is a transaction invariant memory for the TM
    1064              :    region starting at REGION_ENTRY_BLOCK.  */
    1065              : static bool
    1066           24 : transaction_invariant_address_p (const_tree mem, basic_block region_entry_block)
    1067              : {
    1068           24 :   if ((INDIRECT_REF_P (mem) || TREE_CODE (mem) == MEM_REF)
    1069           31 :       && TREE_CODE (TREE_OPERAND (mem, 0)) == SSA_NAME)
    1070              :     {
    1071            7 :       basic_block def_bb;
    1072              : 
    1073            7 :       def_bb = gimple_bb (SSA_NAME_DEF_STMT (TREE_OPERAND (mem, 0)));
    1074            7 :       return def_bb != region_entry_block
    1075            7 :         && dominated_by_p (CDI_DOMINATORS, region_entry_block, def_bb);
    1076              :     }
    1077              : 
    1078           17 :   mem = strip_invariant_refs (mem);
    1079           17 :   return mem && (CONSTANT_CLASS_P (mem) || decl_address_invariant_p (mem));
    1080              : }
    1081              : 
    1082              : /* Given an address ADDR in STMT, find it in the memory log or add it,
    1083              :    making sure to keep only the addresses highest in the dominator
    1084              :    tree.
    1085              : 
    1086              :    ENTRY_BLOCK is the entry_block for the transaction.
    1087              : 
    1088              :    If we find the address in the log, make sure it's either the same
    1089              :    address, or an equivalent one that dominates ADDR.
    1090              : 
    1091              :    If we find the address, but neither ADDR dominates the found
    1092              :    address, nor the found one dominates ADDR, we're on different
    1093              :    execution paths.  Add it.
    1094              : 
    1095              :    If known, ENTRY_BLOCK is the entry block for the region, otherwise
    1096              :    NULL.  */
    1097              : static void
    1098           24 : tm_log_add (basic_block entry_block, tree addr, gimple *stmt)
    1099              : {
    1100           24 :   tm_log_entry **slot;
    1101           24 :   struct tm_log_entry l, *lp;
    1102              : 
    1103           24 :   l.addr = addr;
    1104           24 :   slot = tm_log->find_slot (&l, INSERT);
    1105           24 :   if (!*slot)
    1106              :     {
    1107           24 :       tree type = TREE_TYPE (addr);
    1108              : 
    1109           24 :       lp = XNEW (struct tm_log_entry);
    1110           24 :       lp->addr = addr;
    1111           24 :       *slot = lp;
    1112              : 
    1113              :       /* Small invariant addresses can be handled as save/restores.  */
    1114           24 :       if (entry_block
    1115           24 :           && transaction_invariant_address_p (lp->addr, entry_block)
    1116           21 :           && TYPE_SIZE_UNIT (type) != NULL
    1117           21 :           && tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
    1118           21 :           && ((HOST_WIDE_INT) tree_to_uhwi (TYPE_SIZE_UNIT (type))
    1119           21 :               < param_tm_max_aggregate_size)
    1120              :           /* We must be able to copy this type normally.  I.e., no
    1121              :              special constructors and the like.  */
    1122           43 :           && !TREE_ADDRESSABLE (type))
    1123              :         {
    1124           19 :           lp->save_var = create_tmp_reg (TREE_TYPE (lp->addr), "tm_save");
    1125           19 :           lp->stmts.create (0);
    1126           19 :           lp->entry_block = entry_block;
    1127              :           /* Save addresses separately in dominator order so we don't
    1128              :              get confused by overlapping addresses in the save/restore
    1129              :              sequence.  */
    1130           19 :           tm_log_save_addresses.safe_push (lp->addr);
    1131              :         }
    1132              :       else
    1133              :         {
    1134              :           /* Use the logging functions.  */
    1135            5 :           lp->stmts.create (5);
    1136            5 :           lp->stmts.quick_push (stmt);
    1137            5 :           lp->save_var = NULL;
    1138              :         }
    1139              :     }
    1140              :   else
    1141              :     {
    1142            0 :       size_t i;
    1143            0 :       gimple *oldstmt;
    1144              : 
    1145            0 :       lp = *slot;
    1146              : 
    1147              :       /* If we're generating a save/restore sequence, we don't care
    1148              :          about statements.  */
    1149            0 :       if (lp->save_var)
    1150            0 :         return;
    1151              : 
    1152            0 :       for (i = 0; lp->stmts.iterate (i, &oldstmt); ++i)
    1153              :         {
    1154            0 :           if (stmt == oldstmt)
    1155              :             return;
    1156              :           /* We already have a store to the same address, higher up the
    1157              :              dominator tree.  Nothing to do.  */
    1158            0 :           if (dominated_by_p (CDI_DOMINATORS,
    1159            0 :                               gimple_bb (stmt), gimple_bb (oldstmt)))
    1160              :             return;
    1161              :           /* We should be processing blocks in dominator tree order.  */
    1162            0 :           gcc_assert (!dominated_by_p (CDI_DOMINATORS,
    1163              :                                        gimple_bb (oldstmt), gimple_bb (stmt)));
    1164              :         }
    1165              :       /* Store is on a different code path.  */
    1166            0 :       lp->stmts.safe_push (stmt);
    1167              :     }
    1168              : }
    1169              : 
    1170              : /* Gimplify the address of a TARGET_MEM_REF.  Return the SSA_NAME
    1171              :    result, insert the new statements before GSI.  */
    1172              : 
    1173              : static tree
    1174          662 : gimplify_addr (gimple_stmt_iterator *gsi, tree x)
    1175              : {
    1176          662 :   if (TREE_CODE (x) == TARGET_MEM_REF)
    1177           12 :     x = tree_mem_ref_addr (build_pointer_type (TREE_TYPE (x)), x);
    1178              :   else
    1179          650 :     x = build_fold_addr_expr (x);
    1180          662 :   return force_gimple_operand_gsi (gsi, x, true, NULL, true, GSI_SAME_STMT);
    1181              : }
    1182              : 
    1183              : /* Instrument one address with the logging functions.
    1184              :    ADDR is the address to save.
    1185              :    STMT is the statement before which to place it.  */
    1186              : static void
    1187            5 : tm_log_emit_stmt (tree addr, gimple *stmt)
    1188              : {
    1189            5 :   tree type = TREE_TYPE (addr);
    1190            5 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
    1191            5 :   gimple *log;
    1192            5 :   enum built_in_function code = BUILT_IN_TM_LOG;
    1193              : 
    1194            5 :   if (type == float_type_node)
    1195              :     code = BUILT_IN_TM_LOG_FLOAT;
    1196            5 :   else if (type == double_type_node)
    1197              :     code = BUILT_IN_TM_LOG_DOUBLE;
    1198            5 :   else if (type == long_double_type_node)
    1199              :     code = BUILT_IN_TM_LOG_LDOUBLE;
    1200            5 :   else if (TYPE_SIZE (type) != NULL
    1201            5 :            && tree_fits_uhwi_p (TYPE_SIZE (type)))
    1202              :     {
    1203            5 :       unsigned HOST_WIDE_INT type_size = tree_to_uhwi (TYPE_SIZE (type));
    1204              : 
    1205            5 :       if (TREE_CODE (type) == VECTOR_TYPE)
    1206              :         {
    1207            1 :           switch (type_size)
    1208              :             {
    1209              :             case 64:
    1210              :               code = BUILT_IN_TM_LOG_M64;
    1211              :               break;
    1212            1 :             case 128:
    1213            1 :               code = BUILT_IN_TM_LOG_M128;
    1214            1 :               break;
    1215            0 :             case 256:
    1216            0 :               code = BUILT_IN_TM_LOG_M256;
    1217            0 :               break;
    1218            0 :             default:
    1219            0 :               goto unhandled_vec;
    1220              :             }
    1221            1 :           if (!builtin_decl_explicit_p (code))
    1222            0 :             goto unhandled_vec;
    1223              :         }
    1224              :       else
    1225              :         {
    1226            4 :         unhandled_vec:
    1227            4 :           switch (type_size)
    1228              :             {
    1229              :             case 8:
    1230              :               code = BUILT_IN_TM_LOG_1;
    1231              :               break;
    1232              :             case 16:
    1233              :               code = BUILT_IN_TM_LOG_2;
    1234              :               break;
    1235              :             case 32:
    1236              :               code = BUILT_IN_TM_LOG_4;
    1237              :               break;
    1238              :             case 64:
    1239              :               code = BUILT_IN_TM_LOG_8;
    1240              :               break;
    1241              :             }
    1242              :         }
    1243              :     }
    1244              : 
    1245            5 :   if (code != BUILT_IN_TM_LOG && !builtin_decl_explicit_p (code))
    1246              :     code = BUILT_IN_TM_LOG;
    1247            5 :   tree decl = builtin_decl_explicit (code);
    1248              : 
    1249            5 :   addr = gimplify_addr (&gsi, addr);
    1250            5 :   if (code == BUILT_IN_TM_LOG)
    1251            0 :     log = gimple_build_call (decl, 2, addr, TYPE_SIZE_UNIT (type));
    1252              :   else
    1253            5 :     log = gimple_build_call (decl, 1, addr);
    1254            5 :   gsi_insert_before (&gsi, log, GSI_SAME_STMT);
    1255            5 : }
    1256              : 
    1257              : /* Go through the log and instrument address that must be instrumented
    1258              :    with the logging functions.  Leave the save/restore addresses for
    1259              :    later.  */
    1260              : static void
    1261          474 : tm_log_emit (void)
    1262              : {
    1263          474 :   hash_table<log_entry_hasher>::iterator hi;
    1264          474 :   struct tm_log_entry *lp;
    1265              : 
    1266          498 :   FOR_EACH_HASH_TABLE_ELEMENT (*tm_log, lp, tm_log_entry_t, hi)
    1267              :     {
    1268           24 :       size_t i;
    1269           24 :       gimple *stmt;
    1270              : 
    1271           24 :       if (dump_file)
    1272              :         {
    1273            7 :           fprintf (dump_file, "TM thread private mem logging: ");
    1274            7 :           print_generic_expr (dump_file, lp->addr);
    1275            7 :           fprintf (dump_file, "\n");
    1276              :         }
    1277              : 
    1278           24 :       if (lp->save_var)
    1279              :         {
    1280           19 :           if (dump_file)
    1281            4 :             fprintf (dump_file, "DUMPING to variable\n");
    1282           19 :           continue;
    1283              :         }
    1284              :       else
    1285              :         {
    1286            5 :           if (dump_file)
    1287            3 :             fprintf (dump_file, "DUMPING with logging functions\n");
    1288           34 :           for (i = 0; lp->stmts.iterate (i, &stmt); ++i)
    1289            5 :             tm_log_emit_stmt (lp->addr, stmt);
    1290              :         }
    1291              :     }
    1292          474 : }
    1293              : 
    1294              : /* Emit the save sequence for the corresponding addresses in the log.
    1295              :    ENTRY_BLOCK is the entry block for the transaction.
    1296              :    BB is the basic block to insert the code in.  */
    1297              : static void
    1298           18 : tm_log_emit_saves (basic_block entry_block, basic_block bb)
    1299              : {
    1300           18 :   size_t i;
    1301           18 :   gimple_stmt_iterator gsi = gsi_last_bb (bb);
    1302           18 :   gimple *stmt;
    1303           18 :   struct tm_log_entry l, *lp;
    1304              : 
    1305           36 :   for (i = 0; i < tm_log_save_addresses.length (); ++i)
    1306              :     {
    1307           18 :       l.addr = tm_log_save_addresses[i];
    1308           18 :       lp = *(tm_log->find_slot (&l, NO_INSERT));
    1309           18 :       gcc_assert (lp->save_var != NULL);
    1310              : 
    1311              :       /* We only care about variables in the current transaction.  */
    1312           18 :       if (lp->entry_block != entry_block)
    1313            6 :         continue;
    1314              : 
    1315           12 :       stmt = gimple_build_assign (lp->save_var, unshare_expr (lp->addr));
    1316              : 
    1317              :       /* Make sure we can create an SSA_NAME for this type.  For
    1318              :          instance, aggregates aren't allowed, in which case the system
    1319              :          will create a VOP for us and everything will just work.  */
    1320           12 :       if (is_gimple_reg_type (TREE_TYPE (lp->save_var)))
    1321              :         {
    1322           11 :           lp->save_var = make_ssa_name (lp->save_var, stmt);
    1323           11 :           gimple_assign_set_lhs (stmt, lp->save_var);
    1324              :         }
    1325              : 
    1326           12 :       gsi_insert_before (&gsi, stmt, GSI_SAME_STMT);
    1327              :     }
    1328           18 : }
    1329              : 
    1330              : /* Emit the restore sequence for the corresponding addresses in the log.
    1331              :    ENTRY_BLOCK is the entry block for the transaction.
    1332              :    BB is the basic block to insert the code in.  */
    1333              : static void
    1334           18 : tm_log_emit_restores (basic_block entry_block, basic_block bb)
    1335              : {
    1336           18 :   int i;
    1337           18 :   struct tm_log_entry l, *lp;
    1338           18 :   gimple_stmt_iterator gsi;
    1339           18 :   gimple *stmt;
    1340              : 
    1341           54 :   for (i = tm_log_save_addresses.length () - 1; i >= 0; i--)
    1342              :     {
    1343           18 :       l.addr = tm_log_save_addresses[i];
    1344           18 :       lp = *(tm_log->find_slot (&l, NO_INSERT));
    1345           18 :       gcc_assert (lp->save_var != NULL);
    1346              : 
    1347              :       /* We only care about variables in the current transaction.  */
    1348           18 :       if (lp->entry_block != entry_block)
    1349            6 :         continue;
    1350              : 
    1351              :       /* Restores are in LIFO order from the saves in case we have
    1352              :          overlaps.  */
    1353           12 :       gsi = gsi_start_bb (bb);
    1354              : 
    1355           12 :       stmt = gimple_build_assign (unshare_expr (lp->addr), lp->save_var);
    1356           12 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    1357              :     }
    1358           18 : }
    1359              : 
    1360              : 
    1361              : static tree lower_sequence_tm (gimple_stmt_iterator *, bool *,
    1362              :                                struct walk_stmt_info *);
    1363              : static tree lower_sequence_no_tm (gimple_stmt_iterator *, bool *,
    1364              :                                   struct walk_stmt_info *);
    1365              : 
    1366              : /* Evaluate an address X being dereferenced and determine if it
    1367              :    originally points to a non aliased new chunk of memory (malloc,
    1368              :    alloca, etc).
    1369              : 
    1370              :    Return MEM_THREAD_LOCAL if it points to a thread-local address.
    1371              :    Return MEM_TRANSACTION_LOCAL if it points to a transaction-local address.
    1372              :    Return MEM_NON_LOCAL otherwise.
    1373              : 
    1374              :    ENTRY_BLOCK is the entry block to the transaction containing the
    1375              :    dereference of X.  */
    1376              : static enum thread_memory_type
    1377          483 : thread_private_new_memory (basic_block entry_block, tree x)
    1378              : {
    1379          483 :   gimple *stmt = NULL;
    1380          483 :   enum tree_code code;
    1381          483 :   tm_new_mem_map **slot;
    1382          483 :   tm_new_mem_map elt, *elt_p;
    1383          483 :   tree val = x;
    1384          483 :   enum thread_memory_type retval = mem_transaction_local;
    1385              : 
    1386          483 :   if (!entry_block
    1387          337 :       || TREE_CODE (x) != SSA_NAME
    1388              :       /* Possible uninitialized use, or a function argument.  In
    1389              :          either case, we don't care.  */
    1390          817 :       || SSA_NAME_IS_DEFAULT_DEF (x))
    1391              :     return mem_non_local;
    1392              : 
    1393              :   /* Look in cache first.  */
    1394          161 :   elt.val = x;
    1395          161 :   slot = tm_new_mem_hash->find_slot (&elt, INSERT);
    1396          161 :   elt_p = *slot;
    1397          161 :   if (elt_p)
    1398           40 :     return elt_p->local_new_memory;
    1399              : 
    1400              :   /* Optimistically assume the memory is transaction local during
    1401              :      processing.  This catches recursion into this variable.  */
    1402          121 :   *slot = elt_p = XNEW (tm_new_mem_map);
    1403          121 :   elt_p->val = val;
    1404          121 :   elt_p->local_new_memory = mem_transaction_local;
    1405              : 
    1406              :   /* Search DEF chain to find the original definition of this address.  */
    1407          122 :   do
    1408              :     {
    1409          122 :       if (ptr_deref_may_alias_global_p (x, true))
    1410              :         {
    1411              :           /* Address escapes.  This is not thread-private.  */
    1412          108 :           retval = mem_non_local;
    1413          108 :           goto new_memory_ret;
    1414              :         }
    1415              : 
    1416           14 :       stmt = SSA_NAME_DEF_STMT (x);
    1417              : 
    1418              :       /* If the malloc call is outside the transaction, this is
    1419              :          thread-local.  */
    1420           14 :       if (retval != mem_thread_local
    1421           14 :           && !dominated_by_p (CDI_DOMINATORS, gimple_bb (stmt), entry_block))
    1422              :         retval = mem_thread_local;
    1423              : 
    1424           14 :       if (is_gimple_assign (stmt))
    1425              :         {
    1426            2 :           code = gimple_assign_rhs_code (stmt);
    1427              :           /* x = foo ==> foo */
    1428            2 :           if (code == SSA_NAME)
    1429            0 :             x = gimple_assign_rhs1 (stmt);
    1430              :           /* x = foo + n ==> foo */
    1431            2 :           else if (code == POINTER_PLUS_EXPR)
    1432            1 :             x = gimple_assign_rhs1 (stmt);
    1433              :           /* x = (cast*) foo ==> foo */
    1434            1 :           else if (code == VIEW_CONVERT_EXPR || CONVERT_EXPR_CODE_P (code))
    1435            0 :             x = gimple_assign_rhs1 (stmt);
    1436              :           /* x = c ? op1 : op2 == > op1 or op2 just like a PHI */
    1437            1 :           else if (code == COND_EXPR)
    1438              :             {
    1439            1 :               tree op1 = gimple_assign_rhs2 (stmt);
    1440            1 :               tree op2 = gimple_assign_rhs3 (stmt);
    1441            1 :               enum thread_memory_type mem;
    1442            1 :               retval = thread_private_new_memory (entry_block, op1);
    1443            1 :               if (retval == mem_non_local)
    1444            0 :                 goto new_memory_ret;
    1445            1 :               mem = thread_private_new_memory (entry_block, op2);
    1446            1 :               retval = MIN (retval, mem);
    1447            1 :               goto new_memory_ret;
    1448              :             }
    1449              :           else
    1450              :             {
    1451            0 :               retval = mem_non_local;
    1452            0 :               goto new_memory_ret;
    1453              :             }
    1454              :         }
    1455              :       else
    1456              :         {
    1457           12 :           if (gimple_code (stmt) == GIMPLE_PHI)
    1458              :             {
    1459            4 :               unsigned int i;
    1460            4 :               enum thread_memory_type mem;
    1461            4 :               tree phi_result = gimple_phi_result (stmt);
    1462              : 
    1463              :               /* If any of the ancestors are non-local, we are sure to
    1464              :                  be non-local.  Otherwise we can avoid doing anything
    1465              :                  and inherit what has already been generated.  */
    1466            4 :               retval = mem_max;
    1467            7 :               for (i = 0; i < gimple_phi_num_args (stmt); ++i)
    1468              :                 {
    1469            6 :                   tree op = PHI_ARG_DEF (stmt, i);
    1470              : 
    1471              :                   /* Exclude self-assignment.  */
    1472            6 :                   if (phi_result == op)
    1473            0 :                     continue;
    1474              : 
    1475            6 :                   mem = thread_private_new_memory (entry_block, op);
    1476            6 :                   if (mem == mem_non_local)
    1477              :                     {
    1478            3 :                       retval = mem;
    1479            3 :                       goto new_memory_ret;
    1480              :                     }
    1481            4 :                   retval = MIN (retval, mem);
    1482              :                 }
    1483            1 :               goto new_memory_ret;
    1484              :             }
    1485              :           break;
    1486              :         }
    1487              :     }
    1488            1 :   while (TREE_CODE (x) == SSA_NAME);
    1489              : 
    1490            8 :   if (stmt && is_gimple_call (stmt) && gimple_call_flags (stmt) & ECF_MALLOC)
    1491              :     /* Thread-local or transaction-local.  */
    1492              :     ;
    1493              :   else
    1494              :     retval = mem_non_local;
    1495              : 
    1496          121 :  new_memory_ret:
    1497          121 :   elt_p->local_new_memory = retval;
    1498          121 :   return retval;
    1499              : }
    1500              : 
    1501              : /* Determine whether X has to be instrumented using a read
    1502              :    or write barrier.
    1503              : 
    1504              :    ENTRY_BLOCK is the entry block for the region where stmt resides
    1505              :    in.  NULL if unknown.
    1506              : 
    1507              :    STMT is the statement in which X occurs in.  It is used for thread
    1508              :    private memory instrumentation.  If no TPM instrumentation is
    1509              :    desired, STMT should be null.  */
    1510              : static bool
    1511         4009 : requires_barrier (basic_block entry_block, tree x, gimple *stmt)
    1512              : {
    1513         4009 :   tree orig = x;
    1514         4338 :   while (handled_component_p (x))
    1515          329 :     x = TREE_OPERAND (x, 0);
    1516              : 
    1517         4009 :   switch (TREE_CODE (x))
    1518              :     {
    1519          475 :     case INDIRECT_REF:
    1520          475 :     case MEM_REF:
    1521          475 :       {
    1522          475 :         enum thread_memory_type ret;
    1523              : 
    1524          475 :         ret = thread_private_new_memory (entry_block, TREE_OPERAND (x, 0));
    1525          475 :         if (ret == mem_non_local)
    1526              :           return true;
    1527           20 :         if (stmt && ret == mem_thread_local)
    1528              :           /* ?? Should we pass `orig', or the INDIRECT_REF X.  ?? */
    1529            7 :           tm_log_add (entry_block, orig, stmt);
    1530              : 
    1531              :         /* Transaction-locals require nothing at all.  For malloc, a
    1532              :            transaction restart frees the memory and we reallocate.
    1533              :            For alloca, the stack pointer gets reset by the retry and
    1534              :            we reallocate.  */
    1535              :         return false;
    1536              :       }
    1537              : 
    1538           12 :     case TARGET_MEM_REF:
    1539           12 :       if (TREE_CODE (TMR_BASE (x)) != ADDR_EXPR)
    1540              :         return true;
    1541            1 :       x = TREE_OPERAND (TMR_BASE (x), 0);
    1542            1 :       if (TREE_CODE (x) == PARM_DECL)
    1543              :         return false;
    1544            1 :       gcc_assert (VAR_P (x));
    1545              :       /* FALLTHRU */
    1546              : 
    1547         1567 :     case PARM_DECL:
    1548         1567 :     case RESULT_DECL:
    1549         1567 :     case VAR_DECL:
    1550         1567 :       if (DECL_BY_REFERENCE (x))
    1551              :         {
    1552              :           /* ??? This value is a pointer, but aggregate_value_p has been
    1553              :              jigged to return true which confuses needs_to_live_in_memory.
    1554              :              This ought to be cleaned up generically.
    1555              : 
    1556              :              FIXME: Verify this still happens after the next mainline
    1557              :              merge.  Testcase ie g++.dg/tm/pr47554.C.
    1558              :           */
    1559              :           return false;
    1560              :         }
    1561              : 
    1562         1567 :       if (is_global_var (x))
    1563          655 :         return !TREE_READONLY (x);
    1564          912 :       if (/* FIXME: This condition should actually go below in the
    1565              :              tm_log_add() call, however is_call_clobbered() depends on
    1566              :              aliasing info which is not available during
    1567              :              gimplification.  Since requires_barrier() gets called
    1568              :              during lower_sequence_tm/gimplification, leave the call
    1569              :              to needs_to_live_in_memory until we eliminate
    1570              :              lower_sequence_tm altogether.  */
    1571          912 :           needs_to_live_in_memory (x))
    1572              :         return true;
    1573              :       else
    1574              :         {
    1575              :           /* For local memory that doesn't escape (aka thread private
    1576              :              memory), we can either save the value at the beginning of
    1577              :              the transaction and restore on restart, or call a tm
    1578              :              function to dynamically save and restore on restart
    1579              :              (ITM_L*).  */
    1580          807 :           if (stmt)
    1581           17 :             tm_log_add (entry_block, orig, stmt);
    1582          807 :           return false;
    1583              :         }
    1584              : 
    1585              :     default:
    1586              :       return false;
    1587              :     }
    1588              : }
    1589              : 
    1590              : /* Mark the GIMPLE_ASSIGN statement as appropriate for being inside
    1591              :    a transaction region.  */
    1592              : 
    1593              : static void
    1594          767 : examine_assign_tm (unsigned *state, gimple_stmt_iterator *gsi)
    1595              : {
    1596          767 :   gimple *stmt = gsi_stmt (*gsi);
    1597              : 
    1598          767 :   if (requires_barrier (/*entry_block=*/NULL, gimple_assign_rhs1 (stmt), NULL))
    1599          303 :     *state |= GTMA_HAVE_LOAD;
    1600          767 :   if (requires_barrier (/*entry_block=*/NULL, gimple_assign_lhs (stmt), NULL))
    1601          258 :     *state |= GTMA_HAVE_STORE;
    1602          767 : }
    1603              : 
    1604              : /* Mark a GIMPLE_CALL as appropriate for being inside a transaction.  */
    1605              : 
    1606              : static void
    1607          519 : examine_call_tm (unsigned *state, gimple_stmt_iterator *gsi)
    1608              : {
    1609          519 :   gimple *stmt = gsi_stmt (*gsi);
    1610          519 :   tree fn;
    1611              : 
    1612          519 :   if (is_tm_pure_call (stmt))
    1613              :     return;
    1614              : 
    1615              :   /* Check if this call is a transaction abort.  */
    1616          474 :   fn = gimple_call_fndecl (stmt);
    1617          941 :   if (is_tm_abort (fn))
    1618           29 :     *state |= GTMA_HAVE_ABORT;
    1619              : 
    1620              :   /* Note that something may happen.  */
    1621          474 :   *state |= GTMA_HAVE_LOAD | GTMA_HAVE_STORE;
    1622              : }
    1623              : 
    1624              : /* Iterate through the statements in the sequence, moving labels
    1625              :    (and thus edges) of transactions from "label_norm" to "label_uninst".  */
    1626              : 
    1627              : static tree
    1628         3699 : make_tm_uninst (gimple_stmt_iterator *gsi, bool *handled_ops_p,
    1629              :                 struct walk_stmt_info *)
    1630              : {
    1631         3699 :   gimple *stmt = gsi_stmt (*gsi);
    1632              : 
    1633         3699 :   if (gtransaction *txn = dyn_cast <gtransaction *> (stmt))
    1634              :     {
    1635            6 :       *handled_ops_p = true;
    1636            6 :       txn->label_uninst = txn->label_norm;
    1637            6 :       txn->label_norm = NULL;
    1638              :     }
    1639              :   else
    1640         3693 :     *handled_ops_p = !gimple_has_substatements (stmt);
    1641              : 
    1642         3699 :   return NULL_TREE;
    1643              : }
    1644              : 
    1645              : /* Lower a GIMPLE_TRANSACTION statement.  */
    1646              : 
    1647              : static void
    1648          474 : lower_transaction (gimple_stmt_iterator *gsi, struct walk_stmt_info *wi)
    1649              : {
    1650          474 :   gimple *g;
    1651          474 :   gtransaction *stmt = as_a <gtransaction *> (gsi_stmt (*gsi));
    1652          474 :   unsigned int *outer_state = (unsigned int *) wi->info;
    1653          474 :   unsigned int this_state = 0;
    1654          474 :   struct walk_stmt_info this_wi;
    1655              : 
    1656              :   /* First, lower the body.  The scanning that we do inside gives
    1657              :      us some idea of what we're dealing with.  */
    1658          474 :   memset (&this_wi, 0, sizeof (this_wi));
    1659          474 :   this_wi.info = (void *) &this_state;
    1660          474 :   walk_gimple_seq_mod (gimple_transaction_body_ptr (stmt),
    1661              :                        lower_sequence_tm, NULL, &this_wi);
    1662              : 
    1663              :   /* If there was absolutely nothing transaction related inside the
    1664              :      transaction, we may elide it.  Likewise if this is a nested
    1665              :      transaction and does not contain an abort.  */
    1666          474 :   if (this_state == 0
    1667          430 :       || (!(this_state & GTMA_HAVE_ABORT) && outer_state != NULL))
    1668              :     {
    1669           44 :       if (outer_state)
    1670           29 :         *outer_state |= this_state;
    1671              : 
    1672           73 :       gsi_insert_seq_before (gsi, gimple_transaction_body (stmt),
    1673              :                              GSI_SAME_STMT);
    1674           73 :       gimple_transaction_set_body (stmt, NULL);
    1675              : 
    1676           73 :       gsi_remove (gsi, true);
    1677           73 :       wi->removed_stmt = true;
    1678           73 :       return;
    1679              :     }
    1680              : 
    1681              :   /* Wrap the body of the transaction in a try-finally node so that
    1682              :      the commit call is always properly called.  */
    1683          401 :   g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT), 0);
    1684          401 :   if (flag_exceptions)
    1685              :     {
    1686          276 :       tree ptr;
    1687          276 :       gimple_seq n_seq, e_seq;
    1688              : 
    1689          276 :       n_seq = gimple_seq_alloc_with_stmt (g);
    1690          276 :       e_seq = NULL;
    1691              : 
    1692          276 :       g = gimple_build_call (builtin_decl_explicit (BUILT_IN_EH_POINTER),
    1693              :                              1, integer_zero_node);
    1694          276 :       ptr = create_tmp_var (ptr_type_node);
    1695          276 :       gimple_call_set_lhs (g, ptr);
    1696          276 :       gimple_seq_add_stmt (&e_seq, g);
    1697              : 
    1698          276 :       g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_COMMIT_EH),
    1699              :                              1, ptr);
    1700          276 :       gimple_seq_add_stmt (&e_seq, g);
    1701              : 
    1702          276 :       g = gimple_build_eh_else (n_seq, e_seq);
    1703              :     }
    1704              : 
    1705          401 :   g = gimple_build_try (gimple_transaction_body (stmt),
    1706              :                         gimple_seq_alloc_with_stmt (g), GIMPLE_TRY_FINALLY);
    1707              : 
    1708              :   /* For a (potentially) outer transaction, create two paths.  */
    1709          401 :   gimple_seq uninst = NULL;
    1710          401 :   if (outer_state == NULL)
    1711              :     {
    1712          391 :       uninst = copy_gimple_seq_and_replace_locals (g);
    1713              :       /* In the uninstrumented copy, reset inner transactions to have only
    1714              :          an uninstrumented code path.  */
    1715          391 :       memset (&this_wi, 0, sizeof (this_wi));
    1716          391 :       walk_gimple_seq (uninst, make_tm_uninst, NULL, &this_wi);
    1717              :     }
    1718              : 
    1719          401 :   tree label1 = create_artificial_label (UNKNOWN_LOCATION);
    1720          401 :   gsi_insert_after (gsi, gimple_build_label (label1), GSI_CONTINUE_LINKING);
    1721          401 :   gsi_insert_after (gsi, g, GSI_CONTINUE_LINKING);
    1722          401 :   gimple_transaction_set_label_norm (stmt, label1);
    1723              : 
    1724              :   /* If the transaction calls abort or if this is an outer transaction,
    1725              :      add an "over" label afterwards.  */
    1726          401 :   tree label3 = NULL;
    1727          401 :   if ((this_state & GTMA_HAVE_ABORT)
    1728          372 :       || outer_state == NULL
    1729          401 :       || (gimple_transaction_subcode (stmt) & GTMA_IS_OUTER))
    1730              :     {
    1731          401 :       label3 = create_artificial_label (UNKNOWN_LOCATION);
    1732          401 :       gimple_transaction_set_label_over (stmt, label3);
    1733              :     }
    1734              : 
    1735          401 :   if (uninst != NULL)
    1736              :     {
    1737          391 :       gsi_insert_after (gsi, gimple_build_goto (label3), GSI_CONTINUE_LINKING);
    1738              : 
    1739          391 :       tree label2 = create_artificial_label (UNKNOWN_LOCATION);
    1740          391 :       gsi_insert_after (gsi, gimple_build_label (label2), GSI_CONTINUE_LINKING);
    1741          391 :       gsi_insert_seq_after (gsi, uninst, GSI_CONTINUE_LINKING);
    1742          391 :       gimple_transaction_set_label_uninst (stmt, label2);
    1743              :     }
    1744              : 
    1745          401 :   if (label3 != NULL)
    1746          401 :     gsi_insert_after (gsi, gimple_build_label (label3), GSI_CONTINUE_LINKING);
    1747              : 
    1748          401 :   gimple_transaction_set_body (stmt, NULL);
    1749              : 
    1750              :   /* Record the set of operations found for use later.  */
    1751          401 :   this_state |= gimple_transaction_subcode (stmt) & GTMA_DECLARATION_MASK;
    1752          401 :   gimple_transaction_set_subcode (stmt, this_state);
    1753              : }
    1754              : 
    1755              : /* Iterate through the statements in the sequence, lowering them all
    1756              :    as appropriate for being in a transaction.  */
    1757              : 
    1758              : static tree
    1759         2204 : lower_sequence_tm (gimple_stmt_iterator *gsi, bool *handled_ops_p,
    1760              :                    struct walk_stmt_info *wi)
    1761              : {
    1762         2204 :   unsigned int *state = (unsigned int *) wi->info;
    1763         2204 :   gimple *stmt = gsi_stmt (*gsi);
    1764              : 
    1765         2204 :   *handled_ops_p = true;
    1766         2204 :   switch (gimple_code (stmt))
    1767              :     {
    1768         1015 :     case GIMPLE_ASSIGN:
    1769              :       /* Only memory reads/writes need to be instrumented.  */
    1770         1015 :       if (gimple_assign_single_p (stmt))
    1771          767 :         examine_assign_tm (state, gsi);
    1772              :       break;
    1773              : 
    1774          519 :     case GIMPLE_CALL:
    1775          519 :       examine_call_tm (state, gsi);
    1776          519 :       break;
    1777              : 
    1778            2 :     case GIMPLE_ASM:
    1779            2 :       *state |= GTMA_MAY_ENTER_IRREVOCABLE;
    1780            2 :       break;
    1781              : 
    1782           39 :     case GIMPLE_TRANSACTION:
    1783           39 :       lower_transaction (gsi, wi);
    1784           39 :       break;
    1785              : 
    1786          629 :     default:
    1787          629 :       *handled_ops_p = !gimple_has_substatements (stmt);
    1788          629 :       break;
    1789              :     }
    1790              : 
    1791         2204 :   return NULL_TREE;
    1792              : }
    1793              : 
    1794              : /* Iterate through the statements in the sequence, lowering them all
    1795              :    as appropriate for being outside of a transaction.  */
    1796              : 
    1797              : static tree
    1798         8769 : lower_sequence_no_tm (gimple_stmt_iterator *gsi, bool *handled_ops_p,
    1799              :                       struct walk_stmt_info * wi)
    1800              : {
    1801         8769 :   gimple *stmt = gsi_stmt (*gsi);
    1802              : 
    1803         8769 :   if (gimple_code (stmt) == GIMPLE_TRANSACTION)
    1804              :     {
    1805          435 :       *handled_ops_p = true;
    1806          435 :       lower_transaction (gsi, wi);
    1807              :     }
    1808              :   else
    1809         8334 :     *handled_ops_p = !gimple_has_substatements (stmt);
    1810              : 
    1811         8769 :   return NULL_TREE;
    1812              : }
    1813              : 
    1814              : /* Main entry point for flattening GIMPLE_TRANSACTION constructs.  After
    1815              :    this, GIMPLE_TRANSACTION nodes still exist, but the nested body has
    1816              :    been moved out, and all the data required for constructing a proper
    1817              :    CFG has been recorded.  */
    1818              : 
    1819              : static unsigned int
    1820         1288 : execute_lower_tm (void)
    1821              : {
    1822         1288 :   struct walk_stmt_info wi;
    1823         1288 :   gimple_seq body;
    1824              : 
    1825              :   /* Transactional clones aren't created until a later pass.  */
    1826         2576 :   gcc_assert (!decl_is_tm_clone (current_function_decl));
    1827              : 
    1828         1288 :   body = gimple_body (current_function_decl);
    1829         1288 :   memset (&wi, 0, sizeof (wi));
    1830         1288 :   walk_gimple_seq_mod (&body, lower_sequence_no_tm, NULL, &wi);
    1831         1288 :   gimple_set_body (current_function_decl, body);
    1832              : 
    1833         1288 :   return 0;
    1834              : }
    1835              : 
    1836              : namespace {
    1837              : 
    1838              : const pass_data pass_data_lower_tm =
    1839              : {
    1840              :   GIMPLE_PASS, /* type */
    1841              :   "tmlower", /* name */
    1842              :   OPTGROUP_NONE, /* optinfo_flags */
    1843              :   TV_TRANS_MEM, /* tv_id */
    1844              :   PROP_gimple_lcf, /* properties_required */
    1845              :   0, /* properties_provided */
    1846              :   0, /* properties_destroyed */
    1847              :   0, /* todo_flags_start */
    1848              :   0, /* todo_flags_finish */
    1849              : };
    1850              : 
    1851              : class pass_lower_tm : public gimple_opt_pass
    1852              : {
    1853              : public:
    1854       285722 :   pass_lower_tm (gcc::context *ctxt)
    1855       571444 :     : gimple_opt_pass (pass_data_lower_tm, ctxt)
    1856              :   {}
    1857              : 
    1858              :   /* opt_pass methods: */
    1859      2869205 :   bool gate (function *) final override { return flag_tm; }
    1860         1288 :   unsigned int execute (function *) final override
    1861              :   {
    1862         1288 :     return execute_lower_tm ();
    1863              :   }
    1864              : 
    1865              : }; // class pass_lower_tm
    1866              : 
    1867              : } // anon namespace
    1868              : 
    1869              : gimple_opt_pass *
    1870       285722 : make_pass_lower_tm (gcc::context *ctxt)
    1871              : {
    1872       285722 :   return new pass_lower_tm (ctxt);
    1873              : }
    1874              : 
    1875              : /* Collect region information for each transaction.  */
    1876              : 
    1877              : struct tm_region
    1878              : {
    1879              : public:
    1880              : 
    1881              :   /* The field "transaction_stmt" is initially a gtransaction *,
    1882              :      but eventually gets lowered to a gcall *(to BUILT_IN_TM_START).
    1883              : 
    1884              :      Helper method to get it as a gtransaction *, with code-checking
    1885              :      in a checked-build.  */
    1886              : 
    1887              :   gtransaction *
    1888         2502 :   get_transaction_stmt () const
    1889              :   {
    1890         2502 :     return as_a <gtransaction *> (transaction_stmt);
    1891              :   }
    1892              : 
    1893              : public:
    1894              : 
    1895              :   /* Link to the next unnested transaction.  */
    1896              :   struct tm_region *next;
    1897              : 
    1898              :   /* Link to the next inner transaction.  */
    1899              :   struct tm_region *inner;
    1900              : 
    1901              :   /* Link to the next outer transaction.  */
    1902              :   struct tm_region *outer;
    1903              : 
    1904              :   /* The GIMPLE_TRANSACTION statement beginning this transaction.
    1905              :      After TM_MARK, this gets replaced by a call to
    1906              :      BUILT_IN_TM_START.
    1907              :      Hence this will be either a gtransaction *or a gcall *.  */
    1908              :   gimple *transaction_stmt;
    1909              : 
    1910              :   /* After TM_MARK expands the GIMPLE_TRANSACTION into a call to
    1911              :      BUILT_IN_TM_START, this field is true if the transaction is an
    1912              :      outer transaction.  */
    1913              :   bool original_transaction_was_outer;
    1914              : 
    1915              :   /* Return value from BUILT_IN_TM_START.  */
    1916              :   tree tm_state;
    1917              : 
    1918              :   /* The entry block to this region.  This will always be the first
    1919              :      block of the body of the transaction.  */
    1920              :   basic_block entry_block;
    1921              : 
    1922              :   /* The first block after an expanded call to _ITM_beginTransaction.  */
    1923              :   basic_block restart_block;
    1924              : 
    1925              :   /* The set of all blocks that end the region; NULL if only EXIT_BLOCK.
    1926              :      These blocks are still a part of the region (i.e., the border is
    1927              :      inclusive). Note that this set is only complete for paths in the CFG
    1928              :      starting at ENTRY_BLOCK, and that there is no exit block recorded for
    1929              :      the edge to the "over" label.  */
    1930              :   bitmap exit_blocks;
    1931              : 
    1932              :   /* The set of all blocks that have an TM_IRREVOCABLE call.  */
    1933              :   bitmap irr_blocks;
    1934              : };
    1935              : 
    1936              : /* True if there are pending edge statements to be committed for the
    1937              :    current function being scanned in the tmmark pass.  */
    1938              : bool pending_edge_inserts_p;
    1939              : 
    1940              : static struct tm_region *all_tm_regions;
    1941              : static bitmap_obstack tm_obstack;
    1942              : 
    1943              : 
    1944              : /* A subroutine of tm_region_init.  Record the existence of the
    1945              :    GIMPLE_TRANSACTION statement in a tree of tm_region elements.  */
    1946              : 
    1947              : static struct tm_region *
    1948          763 : tm_region_init_0 (struct tm_region *outer, basic_block bb,
    1949              :                   gtransaction *stmt)
    1950              : {
    1951          763 :   struct tm_region *region;
    1952              : 
    1953         1526 :   region = (struct tm_region *)
    1954          763 :     obstack_alloc (&tm_obstack.obstack, sizeof (struct tm_region));
    1955              : 
    1956          763 :   if (outer)
    1957              :     {
    1958           35 :       region->next = outer->inner;
    1959           35 :       outer->inner = region;
    1960              :     }
    1961              :   else
    1962              :     {
    1963          728 :       region->next = all_tm_regions;
    1964          728 :       all_tm_regions = region;
    1965              :     }
    1966          763 :   region->inner = NULL;
    1967          763 :   region->outer = outer;
    1968              : 
    1969          763 :   region->transaction_stmt = stmt;
    1970          763 :   region->original_transaction_was_outer = false;
    1971          763 :   region->tm_state = NULL;
    1972              : 
    1973              :   /* There are either one or two edges out of the block containing
    1974              :      the GIMPLE_TRANSACTION, one to the actual region and one to the
    1975              :      "over" label if the region contains an abort.  The former will
    1976              :      always be the one marked FALLTHRU.  */
    1977          763 :   region->entry_block = FALLTHRU_EDGE (bb)->dest;
    1978              : 
    1979          763 :   region->exit_blocks = BITMAP_ALLOC (&tm_obstack);
    1980          763 :   region->irr_blocks = BITMAP_ALLOC (&tm_obstack);
    1981              : 
    1982          763 :   return region;
    1983              : }
    1984              : 
    1985              : /* A subroutine of tm_region_init.  Record all the exit and
    1986              :    irrevocable blocks in BB into the region's exit_blocks and
    1987              :    irr_blocks bitmaps.  Returns the new region being scanned.  */
    1988              : 
    1989              : static struct tm_region *
    1990        11681 : tm_region_init_1 (struct tm_region *region, basic_block bb)
    1991              : {
    1992        11681 :   gimple_stmt_iterator gsi;
    1993        11681 :   gimple *g;
    1994              : 
    1995        11681 :   if (!region
    1996         2775 :       || (!region->irr_blocks && !region->exit_blocks))
    1997              :     return region;
    1998              : 
    1999              :   /* Check to see if this is the end of a region by seeing if it
    2000              :      contains a call to __builtin_tm_commit{,_eh}.  Note that the
    2001              :      outermost region for DECL_IS_TM_CLONE need not collect this.  */
    2002        13226 :   for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi))
    2003              :     {
    2004         4703 :       g = gsi_stmt (gsi);
    2005         4703 :       if (gimple_code (g) == GIMPLE_CALL)
    2006              :         {
    2007         1737 :           tree fn = gimple_call_fndecl (g);
    2008         1737 :           if (fn && fndecl_built_in_p (fn, BUILT_IN_NORMAL))
    2009              :             {
    2010         1088 :               if ((DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT
    2011          397 :                    || DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_COMMIT_EH)
    2012         1287 :                   && region->exit_blocks)
    2013              :                 {
    2014          865 :                   bitmap_set_bit (region->exit_blocks, bb->index);
    2015          865 :                   region = region->outer;
    2016          865 :                   break;
    2017              :                 }
    2018          223 :               if (DECL_FUNCTION_CODE (fn) == BUILT_IN_TM_IRREVOCABLE)
    2019           38 :                 bitmap_set_bit (region->irr_blocks, bb->index);
    2020              :             }
    2021              :         }
    2022              :     }
    2023              :   return region;
    2024              : }
    2025              : 
    2026              : /* Collect all of the transaction regions within the current function
    2027              :    and record them in ALL_TM_REGIONS.  The REGION parameter may specify
    2028              :    an "outermost" region for use by tm clones.  */
    2029              : 
    2030              : static void
    2031         2093 : tm_region_init (struct tm_region *region)
    2032              : {
    2033         2093 :   gimple *g;
    2034         2093 :   edge_iterator ei;
    2035         2093 :   edge e;
    2036         2093 :   basic_block bb;
    2037         2093 :   auto_vec<basic_block> queue;
    2038         2093 :   bitmap visited_blocks = BITMAP_ALLOC (NULL);
    2039         2093 :   struct tm_region *old_region;
    2040         2093 :   auto_vec<tm_region *> bb_regions;
    2041              : 
    2042              :   /* We could store this information in bb->aux, but we may get called
    2043              :      through get_all_tm_blocks() from another pass that may be already
    2044              :      using bb->aux.  */
    2045         2093 :   bb_regions.safe_grow_cleared (last_basic_block_for_fn (cfun), true);
    2046              : 
    2047         2093 :   all_tm_regions = region;
    2048         2093 :   bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    2049         2093 :   queue.safe_push (bb);
    2050         2093 :   bitmap_set_bit (visited_blocks, bb->index);
    2051         2093 :   bb_regions[bb->index] = region;
    2052              : 
    2053        11681 :   do
    2054              :     {
    2055        11681 :       bb = queue.pop ();
    2056        11681 :       region = bb_regions[bb->index];
    2057        11681 :       bb_regions[bb->index] = NULL;
    2058              : 
    2059              :       /* Record exit and irrevocable blocks.  */
    2060        11681 :       region = tm_region_init_1 (region, bb);
    2061              : 
    2062              :       /* Check for the last statement in the block beginning a new region.  */
    2063        11681 :       g = last_nondebug_stmt (bb);
    2064        11681 :       old_region = region;
    2065        11681 :       if (g)
    2066         8702 :         if (gtransaction *trans_stmt = dyn_cast <gtransaction *> (g))
    2067          763 :           region = tm_region_init_0 (region, bb, trans_stmt);
    2068              : 
    2069              :       /* Process subsequent blocks.  */
    2070        23395 :       FOR_EACH_EDGE (e, ei, bb->succs)
    2071        11714 :         if (!bitmap_bit_p (visited_blocks, e->dest->index))
    2072              :           {
    2073         9588 :             bitmap_set_bit (visited_blocks, e->dest->index);
    2074         9588 :             queue.safe_push (e->dest);
    2075              : 
    2076              :             /* If the current block started a new region, make sure that only
    2077              :                the entry block of the new region is associated with this region.
    2078              :                Other successors are still part of the old region.  */
    2079         9588 :             if (old_region != region && e->dest != region->entry_block)
    2080          827 :               bb_regions[e->dest->index] = old_region;
    2081              :             else
    2082         8761 :               bb_regions[e->dest->index] = region;
    2083              :           }
    2084              :     }
    2085        23362 :   while (!queue.is_empty ());
    2086         2093 :   BITMAP_FREE (visited_blocks);
    2087         2093 : }
    2088              : 
    2089              : /* The "gate" function for all transactional memory expansion and optimization
    2090              :    passes.  We collect region information for each top-level transaction, and
    2091              :    if we don't find any, we skip all of the TM passes.  Each region will have
    2092              :    all of the exit blocks recorded, and the originating statement.  */
    2093              : 
    2094              : static bool
    2095      1472254 : gate_tm_init (void)
    2096              : {
    2097      1472254 :   if (!flag_tm)
    2098              :     return false;
    2099              : 
    2100         1162 :   calculate_dominance_info (CDI_DOMINATORS);
    2101         1162 :   bitmap_obstack_initialize (&tm_obstack);
    2102              : 
    2103              :   /* If the function is a TM_CLONE, then the entire function is the region.  */
    2104         2324 :   if (decl_is_tm_clone (current_function_decl))
    2105              :     {
    2106          224 :       struct tm_region *region = (struct tm_region *)
    2107          224 :         obstack_alloc (&tm_obstack.obstack, sizeof (struct tm_region));
    2108          224 :       memset (region, 0, sizeof (*region));
    2109          224 :       region->entry_block = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun));
    2110              :       /* For a clone, the entire function is the region.  But even if
    2111              :          we don't need to record any exit blocks, we may need to
    2112              :          record irrevocable blocks.  */
    2113          224 :       region->irr_blocks = BITMAP_ALLOC (&tm_obstack);
    2114              : 
    2115          224 :       tm_region_init (region);
    2116              :     }
    2117              :   else
    2118              :     {
    2119          938 :       tm_region_init (NULL);
    2120              : 
    2121              :       /* If we didn't find any regions, cleanup and skip the whole tree
    2122              :          of tm-related optimizations.  */
    2123          938 :       if (all_tm_regions == NULL)
    2124              :         {
    2125          632 :           bitmap_obstack_release (&tm_obstack);
    2126          632 :           return false;
    2127              :         }
    2128              :     }
    2129              : 
    2130              :   return true;
    2131              : }
    2132              : 
    2133              : namespace {
    2134              : 
    2135              : const pass_data pass_data_tm_init =
    2136              : {
    2137              :   GIMPLE_PASS, /* type */
    2138              :   "*tminit", /* name */
    2139              :   OPTGROUP_NONE, /* optinfo_flags */
    2140              :   TV_TRANS_MEM, /* tv_id */
    2141              :   ( PROP_ssa | PROP_cfg ), /* properties_required */
    2142              :   0, /* properties_provided */
    2143              :   0, /* properties_destroyed */
    2144              :   0, /* todo_flags_start */
    2145              :   0, /* todo_flags_finish */
    2146              : };
    2147              : 
    2148              : class pass_tm_init : public gimple_opt_pass
    2149              : {
    2150              : public:
    2151       285722 :   pass_tm_init (gcc::context *ctxt)
    2152       571444 :     : gimple_opt_pass (pass_data_tm_init, ctxt)
    2153              :   {}
    2154              : 
    2155              :   /* opt_pass methods: */
    2156      1472150 :   bool gate (function *) final override { return gate_tm_init (); }
    2157              : 
    2158              : }; // class pass_tm_init
    2159              : 
    2160              : } // anon namespace
    2161              : 
    2162              : gimple_opt_pass *
    2163       285722 : make_pass_tm_init (gcc::context *ctxt)
    2164              : {
    2165       285722 :   return new pass_tm_init (ctxt);
    2166              : }
    2167              : 
    2168              : /* Add FLAGS to the GIMPLE_TRANSACTION subcode for the transaction region
    2169              :    represented by STATE.  */
    2170              : 
    2171              : static inline void
    2172         1086 : transaction_subcode_ior (struct tm_region *region, unsigned flags)
    2173              : {
    2174         1086 :   if (region && region->transaction_stmt)
    2175              :     {
    2176          666 :       gtransaction *transaction_stmt = region->get_transaction_stmt ();
    2177          666 :       flags |= gimple_transaction_subcode (transaction_stmt);
    2178          666 :       gimple_transaction_set_subcode (transaction_stmt, flags);
    2179              :     }
    2180         1086 : }
    2181              : 
    2182              : /* Construct a memory load in a transactional context.  Return the
    2183              :    gimple statement performing the load, or NULL if there is no
    2184              :    TM_LOAD builtin of the appropriate size to do the load.
    2185              : 
    2186              :    LOC is the location to use for the new statement(s).  */
    2187              : 
    2188              : static gcall *
    2189          378 : build_tm_load (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
    2190              : {
    2191          378 :   tree t, type = TREE_TYPE (rhs);
    2192          378 :   gcall *gcall;
    2193              : 
    2194          378 :   built_in_function code;
    2195          378 :   if (type == float_type_node)
    2196              :     code = BUILT_IN_TM_LOAD_FLOAT;
    2197          377 :   else if (type == double_type_node)
    2198              :     code = BUILT_IN_TM_LOAD_DOUBLE;
    2199          375 :   else if (type == long_double_type_node)
    2200              :     code = BUILT_IN_TM_LOAD_LDOUBLE;
    2201              :   else
    2202              :     {
    2203          374 :       if (TYPE_SIZE (type) == NULL || !tree_fits_uhwi_p (TYPE_SIZE (type)))
    2204              :         return NULL;
    2205          374 :       unsigned HOST_WIDE_INT type_size = tree_to_uhwi (TYPE_SIZE (type));
    2206              : 
    2207          374 :       if (TREE_CODE (type) == VECTOR_TYPE)
    2208              :         {
    2209            5 :           switch (type_size)
    2210              :             {
    2211              :             case 64:
    2212              :               code = BUILT_IN_TM_LOAD_M64;
    2213              :               break;
    2214            5 :             case 128:
    2215            5 :               code = BUILT_IN_TM_LOAD_M128;
    2216            5 :               break;
    2217            0 :             case 256:
    2218            0 :               code = BUILT_IN_TM_LOAD_M256;
    2219            0 :               break;
    2220            0 :             default:
    2221            0 :               goto unhandled_vec;
    2222              :             }
    2223            5 :           if (!builtin_decl_explicit_p (code))
    2224            0 :             goto unhandled_vec;
    2225              :         }
    2226              :       else
    2227              :         {
    2228          369 :         unhandled_vec:
    2229          369 :           switch (type_size)
    2230              :             {
    2231              :             case 8:
    2232              :               code = BUILT_IN_TM_LOAD_1;
    2233              :               break;
    2234            4 :             case 16:
    2235            4 :               code = BUILT_IN_TM_LOAD_2;
    2236            4 :               break;
    2237          183 :             case 32:
    2238          183 :               code = BUILT_IN_TM_LOAD_4;
    2239          183 :               break;
    2240          172 :             case 64:
    2241          172 :               code = BUILT_IN_TM_LOAD_8;
    2242          172 :               break;
    2243              :             default:
    2244              :               return NULL;
    2245              :             }
    2246              :         }
    2247              :     }
    2248              : 
    2249          376 :   tree decl = builtin_decl_explicit (code);
    2250          376 :   gcc_assert (decl);
    2251              : 
    2252          376 :   t = gimplify_addr (gsi, rhs);
    2253          376 :   gcall = gimple_build_call (decl, 1, t);
    2254          376 :   gimple_set_location (gcall, loc);
    2255              : 
    2256          376 :   t = TREE_TYPE (TREE_TYPE (decl));
    2257          376 :   if (useless_type_conversion_p (type, t))
    2258              :     {
    2259           14 :       gimple_call_set_lhs (gcall, lhs);
    2260           14 :       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2261              :     }
    2262              :   else
    2263              :     {
    2264          362 :       gimple *g;
    2265          362 :       tree temp;
    2266              : 
    2267          362 :       temp = create_tmp_reg (t);
    2268          362 :       gimple_call_set_lhs (gcall, temp);
    2269          362 :       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2270              : 
    2271          362 :       t = fold_build1 (VIEW_CONVERT_EXPR, type, temp);
    2272          362 :       g = gimple_build_assign (lhs, t);
    2273          362 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    2274              :     }
    2275              : 
    2276              :   return gcall;
    2277              : }
    2278              : 
    2279              : 
    2280              : /* Similarly for storing TYPE in a transactional context.  */
    2281              : 
    2282              : static gcall *
    2283          247 : build_tm_store (location_t loc, tree lhs, tree rhs, gimple_stmt_iterator *gsi)
    2284              : {
    2285          247 :   tree t, fn, type = TREE_TYPE (rhs), simple_type;
    2286          247 :   gcall *gcall;
    2287              : 
    2288          247 :   built_in_function code;
    2289          247 :   if (type == float_type_node)
    2290              :     code = BUILT_IN_TM_STORE_FLOAT;
    2291          245 :   else if (type == double_type_node)
    2292              :     code = BUILT_IN_TM_STORE_DOUBLE;
    2293          242 :   else if (type == long_double_type_node)
    2294              :     code = BUILT_IN_TM_STORE_LDOUBLE;
    2295              :   else
    2296              :     {
    2297          240 :       if (TYPE_SIZE (type) == NULL || !tree_fits_uhwi_p (TYPE_SIZE (type)))
    2298              :         return NULL;
    2299          240 :       unsigned HOST_WIDE_INT type_size = tree_to_uhwi (TYPE_SIZE (type));
    2300              : 
    2301          240 :       if (TREE_CODE (type) == VECTOR_TYPE)
    2302              :         {
    2303            2 :           switch (type_size)
    2304              :             {
    2305              :             case 64:
    2306              :               code = BUILT_IN_TM_STORE_M64;
    2307              :               break;
    2308            2 :             case 128:
    2309            2 :               code = BUILT_IN_TM_STORE_M128;
    2310            2 :               break;
    2311            0 :             case 256:
    2312            0 :               code = BUILT_IN_TM_STORE_M256;
    2313            0 :               break;
    2314            0 :             default:
    2315            0 :               goto unhandled_vec;
    2316              :             }
    2317            2 :           if (!builtin_decl_explicit_p (code))
    2318            0 :             goto unhandled_vec;
    2319              :         }
    2320              :       else
    2321              :         {
    2322          238 :         unhandled_vec:
    2323          238 :           switch (type_size)
    2324              :             {
    2325              :             case 8:
    2326              :               code = BUILT_IN_TM_STORE_1;
    2327              :               break;
    2328            4 :             case 16:
    2329            4 :               code = BUILT_IN_TM_STORE_2;
    2330            4 :               break;
    2331          137 :             case 32:
    2332          137 :               code = BUILT_IN_TM_STORE_4;
    2333          137 :               break;
    2334           82 :             case 64:
    2335           82 :               code = BUILT_IN_TM_STORE_8;
    2336           82 :               break;
    2337              :             default:
    2338              :               return NULL;
    2339              :             }
    2340              :         }
    2341              :     }
    2342              : 
    2343          240 :   fn = builtin_decl_explicit (code);
    2344          240 :   gcc_assert (fn);
    2345              : 
    2346          240 :   simple_type = TREE_VALUE (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))));
    2347              : 
    2348          240 :   if (TREE_CODE (rhs) == CONSTRUCTOR)
    2349              :     {
    2350              :       /* Handle the easy initialization to zero.  */
    2351            0 :       if (!CONSTRUCTOR_ELTS (rhs))
    2352            0 :         rhs = build_int_cst (simple_type, 0);
    2353              :       else
    2354              :         {
    2355              :           /* ...otherwise punt to the caller and probably use
    2356              :             BUILT_IN_TM_MEMMOVE, because we can't wrap a
    2357              :             VIEW_CONVERT_EXPR around a CONSTRUCTOR (below) and produce
    2358              :             valid gimple.  */
    2359              :           return NULL;
    2360              :         }
    2361              :     }
    2362          240 :   else if (!useless_type_conversion_p (simple_type, type))
    2363              :     {
    2364          223 :       gimple *g;
    2365          223 :       tree temp;
    2366              : 
    2367          223 :       temp = create_tmp_reg (simple_type);
    2368          223 :       t = fold_build1 (VIEW_CONVERT_EXPR, simple_type, rhs);
    2369          223 :       g = gimple_build_assign (temp, t);
    2370          223 :       gimple_set_location (g, loc);
    2371          223 :       gsi_insert_before (gsi, g, GSI_SAME_STMT);
    2372              : 
    2373          223 :       rhs = temp;
    2374              :     }
    2375              : 
    2376          240 :   t = gimplify_addr (gsi, lhs);
    2377          240 :   gcall = gimple_build_call (fn, 2, t, rhs);
    2378          240 :   gimple_set_location (gcall, loc);
    2379          240 :   gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2380              : 
    2381          240 :   return gcall;
    2382              : }
    2383              : 
    2384              : 
    2385              : /* Expand an assignment statement into transactional builtins.  */
    2386              : 
    2387              : static void
    2388          883 : expand_assign_tm (struct tm_region *region, gimple_stmt_iterator *gsi)
    2389              : {
    2390          883 :   gimple *stmt = gsi_stmt (*gsi);
    2391          883 :   location_t loc = gimple_location (stmt);
    2392          883 :   tree lhs = gimple_assign_lhs (stmt);
    2393          883 :   tree rhs = gimple_assign_rhs1 (stmt);
    2394          883 :   bool store_p = requires_barrier (region->entry_block, lhs, NULL);
    2395          883 :   bool load_p = requires_barrier (region->entry_block, rhs, NULL);
    2396          883 :   gimple *gcall = NULL;
    2397              : 
    2398          883 :   if (!load_p && !store_p)
    2399              :     {
    2400              :       /* Add thread private addresses to log if applicable.  */
    2401          243 :       requires_barrier (region->entry_block, lhs, stmt);
    2402          243 :       gsi_next (gsi);
    2403          243 :       return;
    2404              :     }
    2405              : 
    2406          640 :   if (load_p)
    2407          393 :     transaction_subcode_ior (region, GTMA_HAVE_LOAD);
    2408          640 :   if (store_p)
    2409          262 :     transaction_subcode_ior (region, GTMA_HAVE_STORE);
    2410              : 
    2411              :   // Remove original load/store statement.
    2412          640 :   gsi_remove (gsi, true);
    2413              : 
    2414              :   // Attempt to use a simple load/store helper function.
    2415          640 :   if (load_p && !store_p)
    2416          378 :     gcall = build_tm_load (loc, lhs, rhs, gsi);
    2417          262 :   else if (store_p && !load_p)
    2418          247 :     gcall = build_tm_store (loc, lhs, rhs, gsi);
    2419              : 
    2420              :   // If gcall has not been set, then we do not have a simple helper
    2421              :   // function available for the type.  This may be true of larger
    2422              :   // structures, vectors, and non-standard float types.
    2423          625 :   if (!gcall)
    2424              :     {
    2425           24 :       tree lhs_addr, rhs_addr, ltmp = NULL, copy_fn;
    2426              : 
    2427              :       // If this is a type that we couldn't handle above, but it's
    2428              :       // in a register, we must spill it to memory for the copy.
    2429           24 :       if (is_gimple_reg (lhs))
    2430              :         {
    2431            1 :           ltmp = create_tmp_var (TREE_TYPE (lhs));
    2432            1 :           lhs_addr = build_fold_addr_expr (ltmp);
    2433              :         }
    2434              :       else
    2435           23 :         lhs_addr = gimplify_addr (gsi, lhs);
    2436           24 :       if (is_gimple_reg (rhs))
    2437              :         {
    2438            0 :           tree rtmp = create_tmp_var (TREE_TYPE (rhs));
    2439            0 :           TREE_ADDRESSABLE (rtmp) = 1;
    2440            0 :           rhs_addr = build_fold_addr_expr (rtmp);
    2441            0 :           gcall = gimple_build_assign (rtmp, rhs);
    2442            0 :           gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2443              :         }
    2444           24 :       else if (TREE_CODE (rhs) == CONSTRUCTOR
    2445           24 :                && CONSTRUCTOR_NELTS (rhs) == 0)
    2446              :         {
    2447              :           /* Don't take address of an empty CONSTRUCTOR, it might not
    2448              :              work for C++ non-POD constructors at all and otherwise
    2449              :              would be inefficient.  Use tm memset to clear lhs.  */
    2450            6 :           gcc_assert (!load_p && store_p);
    2451            6 :           rhs_addr = integer_zero_node;
    2452              :         }
    2453              :       else
    2454           18 :         rhs_addr = gimplify_addr (gsi, rhs);
    2455              : 
    2456              :       // Choose the appropriate memory transfer function.
    2457            6 :       if (store_p
    2458           22 :           && TREE_CODE (rhs) == CONSTRUCTOR
    2459           24 :           && CONSTRUCTOR_NELTS (rhs) == 0)
    2460            6 :         copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMSET);
    2461           18 :       else if (load_p && store_p)
    2462              :         // ??? Figure out if there's any possible overlap between
    2463              :         // the LHS and the RHS and if not, use MEMCPY.
    2464           15 :         copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMMOVE);
    2465            3 :       else if (load_p)
    2466              :         // Note that the store is non-transactional and cannot overlap.
    2467            2 :         copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RTWN);
    2468              :       else
    2469              :         // Note that the load is non-transactional and cannot overlap.
    2470            1 :         copy_fn = builtin_decl_explicit (BUILT_IN_TM_MEMCPY_RNWT);
    2471              : 
    2472           24 :       gcall = gimple_build_call (copy_fn, 3, lhs_addr, rhs_addr,
    2473           24 :                                  TYPE_SIZE_UNIT (TREE_TYPE (lhs)));
    2474           24 :       gimple_set_location (gcall, loc);
    2475           24 :       gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2476              : 
    2477           24 :       if (ltmp)
    2478              :         {
    2479            1 :           gcall = gimple_build_assign (lhs, ltmp);
    2480            1 :           gsi_insert_before (gsi, gcall, GSI_SAME_STMT);
    2481              :         }
    2482              :     }
    2483              : 
    2484              :   // Now that we have the load/store in its instrumented form, add
    2485              :   // thread private addresses to the log if applicable.
    2486          640 :   if (!store_p)
    2487          378 :     requires_barrier (region->entry_block, lhs, gcall);
    2488              : }
    2489              : 
    2490              : 
    2491              : /* Expand a call statement as appropriate for a transaction.  That is,
    2492              :    either verify that the call does not affect the transaction, or
    2493              :    redirect the call to a clone that handles transactions, or change
    2494              :    the transaction state to IRREVOCABLE.  Return true if the call is
    2495              :    one of the builtins that end a transaction.  */
    2496              : 
    2497              : static bool
    2498          899 : expand_call_tm (struct tm_region *region,
    2499              :                 gimple_stmt_iterator *gsi)
    2500              : {
    2501          899 :   gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
    2502          899 :   tree lhs = gimple_call_lhs (stmt);
    2503          899 :   tree fn_decl;
    2504          899 :   struct cgraph_node *node;
    2505          899 :   bool retval = false;
    2506              : 
    2507          899 :   fn_decl = gimple_call_fndecl (stmt);
    2508              : 
    2509          899 :   if (fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMCPY)
    2510          899 :       || fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMMOVE))
    2511            4 :     transaction_subcode_ior (region, GTMA_HAVE_STORE | GTMA_HAVE_LOAD);
    2512          899 :   if (fn_decl == builtin_decl_explicit (BUILT_IN_TM_MEMSET))
    2513            2 :     transaction_subcode_ior (region, GTMA_HAVE_STORE);
    2514              : 
    2515          899 :   if (is_tm_pure_call (stmt))
    2516              :     return false;
    2517              : 
    2518          643 :   if (fn_decl)
    2519          625 :     retval = is_tm_ending_fndecl (fn_decl);
    2520          625 :   if (!retval)
    2521              :     {
    2522              :       /* Assume all non-const/pure calls write to memory, except
    2523              :          transaction ending builtins.  */
    2524          236 :       transaction_subcode_ior (region, GTMA_HAVE_STORE);
    2525              :     }
    2526              : 
    2527              :   /* For indirect calls, we already generated a call into the runtime.  */
    2528          643 :   if (!fn_decl)
    2529              :     {
    2530           18 :       tree fn = gimple_call_fn (stmt);
    2531              : 
    2532              :       /* We are guaranteed never to go irrevocable on a safe or pure
    2533              :          call, and the pure call was handled above.  */
    2534           18 :       if (is_tm_safe (fn))
    2535              :         return false;
    2536              :       else
    2537           17 :         transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
    2538              : 
    2539           17 :       return false;
    2540              :     }
    2541              : 
    2542          625 :   node = cgraph_node::get (fn_decl);
    2543              :   /* All calls should have cgraph here.  */
    2544          625 :   if (!node)
    2545              :     {
    2546              :       /* We can have a nodeless call here if some pass after IPA-tm
    2547              :          added uninstrumented calls.  For example, loop distribution
    2548              :          can transform certain loop constructs into __builtin_mem*
    2549              :          calls.  In this case, see if we have a suitable TM
    2550              :          replacement and fill in the gaps.  */
    2551            0 :       gcc_assert (DECL_BUILT_IN_CLASS (fn_decl) == BUILT_IN_NORMAL);
    2552            0 :       enum built_in_function code = DECL_FUNCTION_CODE (fn_decl);
    2553            0 :       gcc_assert (code == BUILT_IN_MEMCPY
    2554              :                   || code == BUILT_IN_MEMMOVE
    2555              :                   || code == BUILT_IN_MEMSET);
    2556              : 
    2557            0 :       tree repl = find_tm_replacement_function (fn_decl);
    2558            0 :       if (repl)
    2559              :         {
    2560            0 :           gimple_call_set_fndecl (stmt, repl);
    2561            0 :           update_stmt (stmt);
    2562            0 :           node = cgraph_node::create (repl);
    2563            0 :           node->tm_may_enter_irr = false;
    2564            0 :           return expand_call_tm (region, gsi);
    2565              :         }
    2566            0 :       gcc_unreachable ();
    2567              :     }
    2568          625 :   if (node->tm_may_enter_irr)
    2569           13 :     transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
    2570              : 
    2571          625 :   if (is_tm_abort (fn_decl))
    2572              :     {
    2573           38 :       transaction_subcode_ior (region, GTMA_HAVE_ABORT);
    2574           38 :       return true;
    2575              :     }
    2576              : 
    2577              :   /* Instrument the store if needed.
    2578              : 
    2579              :      If the assignment happens inside the function call (return slot
    2580              :      optimization), there is no instrumentation to be done, since
    2581              :      the callee should have done the right thing.  */
    2582           88 :   if (lhs && requires_barrier (region->entry_block, lhs, stmt)
    2583          596 :       && !gimple_call_return_slot_opt_p (stmt))
    2584              :     {
    2585            8 :       tree tmp = create_tmp_reg (TREE_TYPE (lhs));
    2586            8 :       location_t loc = gimple_location (stmt);
    2587            8 :       edge fallthru_edge = NULL;
    2588            8 :       gassign *assign_stmt;
    2589              : 
    2590              :       /* Remember if the call was going to throw.  */
    2591            8 :       if (stmt_can_throw_internal (cfun, stmt))
    2592              :         {
    2593            7 :           edge_iterator ei;
    2594            7 :           edge e;
    2595            7 :           basic_block bb = gimple_bb (stmt);
    2596              : 
    2597            8 :           FOR_EACH_EDGE (e, ei, bb->succs)
    2598            8 :             if (e->flags & EDGE_FALLTHRU)
    2599              :               {
    2600              :                 fallthru_edge = e;
    2601              :                 break;
    2602              :               }
    2603              :         }
    2604              : 
    2605            8 :       gimple_call_set_lhs (stmt, tmp);
    2606            8 :       update_stmt (stmt);
    2607            8 :       assign_stmt = gimple_build_assign (lhs, tmp);
    2608            8 :       gimple_set_location (assign_stmt, loc);
    2609              : 
    2610              :       /* We cannot throw in the middle of a BB.  If the call was going
    2611              :          to throw, place the instrumentation on the fallthru edge, so
    2612              :          the call remains the last statement in the block.  */
    2613            8 :       if (fallthru_edge)
    2614              :         {
    2615            7 :           gimple_seq fallthru_seq = gimple_seq_alloc_with_stmt (assign_stmt);
    2616            7 :           gimple_stmt_iterator fallthru_gsi = gsi_start (fallthru_seq);
    2617            7 :           expand_assign_tm (region, &fallthru_gsi);
    2618            7 :           gsi_insert_seq_on_edge (fallthru_edge, fallthru_seq);
    2619            7 :           pending_edge_inserts_p = true;
    2620              :         }
    2621              :       else
    2622              :         {
    2623            1 :           gsi_insert_after (gsi, assign_stmt, GSI_CONTINUE_LINKING);
    2624            1 :           expand_assign_tm (region, gsi);
    2625              :         }
    2626              : 
    2627            8 :       transaction_subcode_ior (region, GTMA_HAVE_STORE);
    2628              :     }
    2629              : 
    2630              :   return retval;
    2631              : }
    2632              : 
    2633              : 
    2634              : /* Expand all statements in BB as appropriate for being inside
    2635              :    a transaction.  */
    2636              : 
    2637              : static void
    2638         1467 : expand_block_tm (struct tm_region *region, basic_block bb)
    2639              : {
    2640         1467 :   gimple_stmt_iterator gsi;
    2641              : 
    2642         5610 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); )
    2643              :     {
    2644         3083 :       gimple *stmt = gsi_stmt (gsi);
    2645         3083 :       switch (gimple_code (stmt))
    2646              :         {
    2647         1285 :         case GIMPLE_ASSIGN:
    2648              :           /* Only memory reads/writes need to be instrumented.  */
    2649         1285 :           if (gimple_assign_single_p (stmt)
    2650         1285 :               && !gimple_clobber_p (stmt))
    2651              :             {
    2652          875 :               expand_assign_tm (region, &gsi);
    2653          875 :               continue;
    2654              :             }
    2655              :           break;
    2656              : 
    2657          899 :         case GIMPLE_CALL:
    2658          899 :           if (expand_call_tm (region, &gsi))
    2659          407 :             return;
    2660              :           break;
    2661              : 
    2662            0 :         case GIMPLE_ASM:
    2663            0 :           gcc_unreachable ();
    2664              : 
    2665              :         default:
    2666              :           break;
    2667              :         }
    2668         1801 :       if (!gsi_end_p (gsi))
    2669         1801 :         gsi_next (&gsi);
    2670              :     }
    2671              : }
    2672              : 
    2673              : /* Return the list of basic-blocks in REGION.
    2674              : 
    2675              :    STOP_AT_IRREVOCABLE_P is true if caller is uninterested in blocks
    2676              :    following a TM_IRREVOCABLE call.
    2677              : 
    2678              :    INCLUDE_UNINSTRUMENTED_P is TRUE if we should include the
    2679              :    uninstrumented code path blocks in the list of basic blocks
    2680              :    returned, false otherwise.  */
    2681              : 
    2682              : static vec<basic_block>
    2683         1950 : get_tm_region_blocks (basic_block entry_block,
    2684              :                       bitmap exit_blocks,
    2685              :                       bitmap irr_blocks,
    2686              :                       bitmap all_region_blocks,
    2687              :                       bool stop_at_irrevocable_p,
    2688              :                       bool include_uninstrumented_p = true)
    2689              : {
    2690         1950 :   vec<basic_block> bbs = vNULL;
    2691         1950 :   unsigned i;
    2692         1950 :   edge e;
    2693         1950 :   edge_iterator ei;
    2694         1950 :   bitmap visited_blocks = BITMAP_ALLOC (NULL);
    2695              : 
    2696         1950 :   i = 0;
    2697         1950 :   bbs.safe_push (entry_block);
    2698         1950 :   bitmap_set_bit (visited_blocks, entry_block->index);
    2699              : 
    2700         5120 :   do
    2701              :     {
    2702         5120 :       basic_block bb = bbs[i++];
    2703              : 
    2704         8921 :       if (exit_blocks &&
    2705         3801 :           bitmap_bit_p (exit_blocks, bb->index))
    2706         1821 :         continue;
    2707              : 
    2708         3342 :       if (stop_at_irrevocable_p
    2709         3299 :           && irr_blocks
    2710         3299 :           && bitmap_bit_p (irr_blocks, bb->index))
    2711           43 :         continue;
    2712              : 
    2713         7099 :       FOR_EACH_EDGE (e, ei, bb->succs)
    2714         3843 :         if ((include_uninstrumented_p
    2715         1743 :              || !(e->flags & EDGE_TM_UNINSTRUMENTED))
    2716         5563 :             && !bitmap_bit_p (visited_blocks, e->dest->index))
    2717              :           {
    2718         3170 :             bitmap_set_bit (visited_blocks, e->dest->index);
    2719         3170 :             bbs.safe_push (e->dest);
    2720              :           }
    2721              :     }
    2722        10240 :   while (i < bbs.length ());
    2723              : 
    2724         1950 :   if (all_region_blocks)
    2725          474 :     bitmap_ior_into (all_region_blocks, visited_blocks);
    2726              : 
    2727         1950 :   BITMAP_FREE (visited_blocks);
    2728         1950 :   return bbs;
    2729              : }
    2730              : 
    2731              : // Callback data for collect_bb2reg.
    2732              : struct bb2reg_stuff
    2733              : {
    2734              :   vec<tm_region *> *bb2reg;
    2735              :   bool include_uninstrumented_p;
    2736              : };
    2737              : 
    2738              : // Callback for expand_regions, collect innermost region data for each bb.
    2739              : static void *
    2740          922 : collect_bb2reg (struct tm_region *region, void *data)
    2741              : {
    2742          922 :   struct bb2reg_stuff *stuff = (struct bb2reg_stuff *)data;
    2743          922 :   vec<tm_region *> *bb2reg = stuff->bb2reg;
    2744          922 :   vec<basic_block> queue;
    2745          922 :   unsigned int i;
    2746          922 :   basic_block bb;
    2747              : 
    2748          922 :   queue = get_tm_region_blocks (region->entry_block,
    2749              :                                 region->exit_blocks,
    2750              :                                 region->irr_blocks,
    2751              :                                 NULL,
    2752              :                                 /*stop_at_irr_p=*/true,
    2753          922 :                                 stuff->include_uninstrumented_p);
    2754              : 
    2755              :   // We expect expand_region to perform a post-order traversal of the region
    2756              :   // tree.  Therefore the last region seen for any bb is the innermost.
    2757         4291 :   FOR_EACH_VEC_ELT (queue, i, bb)
    2758         2447 :     (*bb2reg)[bb->index] = region;
    2759              : 
    2760          922 :   queue.release ();
    2761          922 :   return NULL;
    2762              : }
    2763              : 
    2764              : // Returns a vector, indexed by BB->INDEX, of the innermost tm_region to
    2765              : // which a basic block belongs.  Note that we only consider the instrumented
    2766              : // code paths for the region; the uninstrumented code paths are ignored if
    2767              : // INCLUDE_UNINSTRUMENTED_P is false.
    2768              : //
    2769              : // ??? This data is very similar to the bb_regions array that is collected
    2770              : // during tm_region_init.  Or, rather, this data is similar to what could
    2771              : // be used within tm_region_init.  The actual computation in tm_region_init
    2772              : // begins and ends with bb_regions entirely full of NULL pointers, due to
    2773              : // the way in which pointers are swapped in and out of the array.
    2774              : //
    2775              : // ??? Our callers expect that blocks are not shared between transactions.
    2776              : // When the optimizers get too smart, and blocks are shared, then during
    2777              : // the tm_mark phase we'll add log entries to only one of the two transactions,
    2778              : // and in the tm_edge phase we'll add edges to the CFG that create invalid
    2779              : // cycles.  The symptom being SSA defs that do not dominate their uses.
    2780              : // Note that the optimizers were locally correct with their transformation,
    2781              : // as we have no info within the program that suggests that the blocks cannot
    2782              : // be shared.
    2783              : //
    2784              : // ??? There is currently a hack inside tree-ssa-pre.cc to work around the
    2785              : // only known instance of this block sharing.
    2786              : 
    2787              : static vec<tm_region *>
    2788          948 : get_bb_regions_instrumented (bool traverse_clones,
    2789              :                              bool include_uninstrumented_p)
    2790              : {
    2791          948 :   unsigned n = last_basic_block_for_fn (cfun);
    2792          948 :   struct bb2reg_stuff stuff;
    2793          948 :   vec<tm_region *> ret;
    2794              : 
    2795          948 :   ret.create (n);
    2796          948 :   ret.safe_grow_cleared (n, true);
    2797          948 :   stuff.bb2reg = &ret;
    2798          948 :   stuff.include_uninstrumented_p = include_uninstrumented_p;
    2799          948 :   expand_regions (all_tm_regions, collect_bb2reg, &stuff, traverse_clones);
    2800              : 
    2801          948 :   return ret;
    2802              : }
    2803              : 
    2804              : /* Set the IN_TRANSACTION for all gimple statements that appear in a
    2805              :    transaction.  */
    2806              : 
    2807              : void
    2808          104 : compute_transaction_bits (void)
    2809              : {
    2810          104 :   struct tm_region *region;
    2811          104 :   vec<basic_block> queue;
    2812          104 :   unsigned int i;
    2813          104 :   basic_block bb;
    2814              : 
    2815              :   /* ?? Perhaps we need to abstract gate_tm_init further, because we
    2816              :      certainly don't need it to calculate CDI_DOMINATOR info.  */
    2817          104 :   gate_tm_init ();
    2818              : 
    2819         1349 :   FOR_EACH_BB_FN (bb, cfun)
    2820         1245 :     bb->flags &= ~BB_IN_TRANSACTION;
    2821              : 
    2822          168 :   for (region = all_tm_regions; region; region = region->next)
    2823              :     {
    2824           64 :       queue = get_tm_region_blocks (region->entry_block,
    2825              :                                     region->exit_blocks,
    2826              :                                     region->irr_blocks,
    2827              :                                     NULL,
    2828              :                                     /*stop_at_irr_p=*/true);
    2829          489 :       for (i = 0; queue.iterate (i, &bb); ++i)
    2830          361 :         bb->flags |= BB_IN_TRANSACTION;
    2831           64 :       queue.release ();
    2832              :     }
    2833              : 
    2834          104 :   if (all_tm_regions)
    2835           56 :     bitmap_obstack_release (&tm_obstack);
    2836          104 : }
    2837              : 
    2838              : /* Replace the GIMPLE_TRANSACTION in this region with the corresponding
    2839              :    call to BUILT_IN_TM_START.  */
    2840              : 
    2841              : static void *
    2842          357 : expand_transaction (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
    2843              : {
    2844          357 :   tree tm_start = builtin_decl_explicit (BUILT_IN_TM_START);
    2845          357 :   basic_block transaction_bb = gimple_bb (region->transaction_stmt);
    2846          357 :   tree tm_state = region->tm_state;
    2847          357 :   tree tm_state_type = TREE_TYPE (tm_state);
    2848          357 :   edge abort_edge = NULL;
    2849          357 :   edge inst_edge = NULL;
    2850          357 :   edge uninst_edge = NULL;
    2851          357 :   edge fallthru_edge = NULL;
    2852              : 
    2853              :   // Identify the various successors of the transaction start.
    2854          357 :   {
    2855          357 :     edge_iterator i;
    2856          357 :     edge e;
    2857         1100 :     FOR_EACH_EDGE (e, i, transaction_bb->succs)
    2858              :       {
    2859          743 :         if (e->flags & EDGE_TM_ABORT)
    2860              :           abort_edge = e;
    2861          698 :         else if (e->flags & EDGE_TM_UNINSTRUMENTED)
    2862              :           uninst_edge = e;
    2863              :         else
    2864          351 :           inst_edge = e;
    2865          743 :         if (e->flags & EDGE_FALLTHRU)
    2866          357 :           fallthru_edge = e;
    2867              :       }
    2868              :   }
    2869              : 
    2870              :   /* ??? There are plenty of bits here we're not computing.  */
    2871          357 :   {
    2872          357 :     int subcode = gimple_transaction_subcode (region->get_transaction_stmt ());
    2873          357 :     int flags = 0;
    2874          357 :     if (subcode & GTMA_DOES_GO_IRREVOCABLE)
    2875           39 :       flags |= PR_DOESGOIRREVOCABLE;
    2876          357 :     if ((subcode & GTMA_MAY_ENTER_IRREVOCABLE) == 0)
    2877          302 :       flags |= PR_HASNOIRREVOCABLE;
    2878              :     /* If the transaction does not have an abort in lexical scope and is not
    2879              :        marked as an outer transaction, then it will never abort.  */
    2880          357 :     if ((subcode & GTMA_HAVE_ABORT) == 0 && (subcode & GTMA_IS_OUTER) == 0)
    2881          311 :       flags |= PR_HASNOABORT;
    2882          357 :     if ((subcode & GTMA_HAVE_STORE) == 0)
    2883          153 :       flags |= PR_READONLY;
    2884          357 :     if (inst_edge && !(subcode & GTMA_HAS_NO_INSTRUMENTATION))
    2885          312 :       flags |= PR_INSTRUMENTEDCODE;
    2886          357 :     if (uninst_edge)
    2887          347 :       flags |= PR_UNINSTRUMENTEDCODE;
    2888          357 :     if (subcode & GTMA_IS_OUTER)
    2889           10 :       region->original_transaction_was_outer = true;
    2890          357 :     tree t = build_int_cst (tm_state_type, flags);
    2891          357 :     gcall *call = gimple_build_call (tm_start, 1, t);
    2892          357 :     gimple_call_set_lhs (call, tm_state);
    2893          357 :     gimple_set_location (call, gimple_location (region->transaction_stmt));
    2894              : 
    2895              :     // Replace the GIMPLE_TRANSACTION with the call to BUILT_IN_TM_START.
    2896          357 :     gimple_stmt_iterator gsi = gsi_last_bb (transaction_bb);
    2897          357 :     gcc_assert (gsi_stmt (gsi) == region->transaction_stmt);
    2898          357 :     gsi_insert_before (&gsi, call, GSI_SAME_STMT);
    2899          357 :     gsi_remove (&gsi, true);
    2900          357 :     region->transaction_stmt = call;
    2901              :   }
    2902              : 
    2903              :   // Generate log saves.
    2904          357 :   if (!tm_log_save_addresses.is_empty ())
    2905           18 :     tm_log_emit_saves (region->entry_block, transaction_bb);
    2906              : 
    2907              :   // In the beginning, we've no tests to perform on transaction restart.
    2908              :   // Note that after this point, transaction_bb becomes the "most recent
    2909              :   // block containing tests for the transaction".
    2910          357 :   region->restart_block = region->entry_block;
    2911              : 
    2912              :   // Generate log restores.
    2913          357 :   if (!tm_log_save_addresses.is_empty ())
    2914              :     {
    2915           18 :       basic_block test_bb = create_empty_bb (transaction_bb);
    2916           18 :       basic_block code_bb = create_empty_bb (test_bb);
    2917           18 :       basic_block join_bb = create_empty_bb (code_bb);
    2918           18 :       add_bb_to_loop (test_bb, transaction_bb->loop_father);
    2919           18 :       add_bb_to_loop (code_bb, transaction_bb->loop_father);
    2920           18 :       add_bb_to_loop (join_bb, transaction_bb->loop_father);
    2921           18 :       if (region->restart_block == region->entry_block)
    2922           18 :         region->restart_block = test_bb;
    2923              : 
    2924           18 :       tree t1 = create_tmp_reg (tm_state_type);
    2925           18 :       tree t2 = build_int_cst (tm_state_type, A_RESTORELIVEVARIABLES);
    2926           18 :       gimple *stmt = gimple_build_assign (t1, BIT_AND_EXPR, tm_state, t2);
    2927           18 :       gimple_stmt_iterator gsi = gsi_last_bb (test_bb);
    2928           18 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    2929              : 
    2930           18 :       t2 = build_int_cst (tm_state_type, 0);
    2931           18 :       stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL);
    2932           18 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    2933              : 
    2934           18 :       tm_log_emit_restores (region->entry_block, code_bb);
    2935              : 
    2936           18 :       edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU);
    2937           18 :       edge et = make_edge (test_bb, code_bb, EDGE_TRUE_VALUE);
    2938           18 :       edge ef = make_edge (test_bb, join_bb, EDGE_FALSE_VALUE);
    2939           18 :       redirect_edge_pred (fallthru_edge, join_bb);
    2940              : 
    2941           18 :       join_bb->count = test_bb->count = transaction_bb->count;
    2942              : 
    2943           18 :       ei->probability = profile_probability::always ();
    2944           18 :       et->probability = profile_probability::likely ();
    2945           18 :       ef->probability = profile_probability::unlikely ();
    2946              : 
    2947           18 :       code_bb->count = et->count ();
    2948              : 
    2949           18 :       transaction_bb = join_bb;
    2950              :     }
    2951              : 
    2952              :   // If we have an ABORT edge, create a test to perform the abort.
    2953          357 :   if (abort_edge)
    2954              :     {
    2955           45 :       basic_block test_bb = create_empty_bb (transaction_bb);
    2956           45 :       add_bb_to_loop (test_bb, transaction_bb->loop_father);
    2957           45 :       if (region->restart_block == region->entry_block)
    2958           42 :         region->restart_block = test_bb;
    2959              : 
    2960           45 :       tree t1 = create_tmp_reg (tm_state_type);
    2961           45 :       tree t2 = build_int_cst (tm_state_type, A_ABORTTRANSACTION);
    2962           45 :       gimple *stmt = gimple_build_assign (t1, BIT_AND_EXPR, tm_state, t2);
    2963           45 :       gimple_stmt_iterator gsi = gsi_last_bb (test_bb);
    2964           45 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    2965              : 
    2966           45 :       t2 = build_int_cst (tm_state_type, 0);
    2967           45 :       stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL);
    2968           45 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    2969              : 
    2970           45 :       edge ei = make_edge (transaction_bb, test_bb, EDGE_FALLTHRU);
    2971           45 :       test_bb->count = transaction_bb->count;
    2972           45 :       ei->probability = profile_probability::always ();
    2973              : 
    2974              :       // Not abort edge.  If both are live, chose one at random as we'll
    2975              :       // we'll be fixing that up below.
    2976           45 :       redirect_edge_pred (fallthru_edge, test_bb);
    2977           45 :       fallthru_edge->flags = EDGE_FALSE_VALUE;
    2978           45 :       fallthru_edge->probability = profile_probability::very_likely ();
    2979              : 
    2980              :       // Abort/over edge.
    2981           45 :       redirect_edge_pred (abort_edge, test_bb);
    2982           45 :       abort_edge->flags = EDGE_TRUE_VALUE;
    2983           45 :       abort_edge->probability = profile_probability::unlikely ();
    2984              : 
    2985           45 :       transaction_bb = test_bb;
    2986              :     }
    2987              : 
    2988              :   // If we have both instrumented and uninstrumented code paths, select one.
    2989          357 :   if (inst_edge && uninst_edge)
    2990              :     {
    2991          341 :       basic_block test_bb = create_empty_bb (transaction_bb);
    2992          341 :       add_bb_to_loop (test_bb, transaction_bb->loop_father);
    2993          341 :       if (region->restart_block == region->entry_block)
    2994          297 :         region->restart_block = test_bb;
    2995              : 
    2996          341 :       tree t1 = create_tmp_reg (tm_state_type);
    2997          341 :       tree t2 = build_int_cst (tm_state_type, A_RUNUNINSTRUMENTEDCODE);
    2998              : 
    2999          341 :       gimple *stmt = gimple_build_assign (t1, BIT_AND_EXPR, tm_state, t2);
    3000          341 :       gimple_stmt_iterator gsi = gsi_last_bb (test_bb);
    3001          341 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    3002              : 
    3003          341 :       t2 = build_int_cst (tm_state_type, 0);
    3004          341 :       stmt = gimple_build_cond (NE_EXPR, t1, t2, NULL, NULL);
    3005          341 :       gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
    3006              : 
    3007              :       // Create the edge into test_bb first, as we want to copy values
    3008              :       // out of the fallthru edge.
    3009          341 :       edge e = make_edge (transaction_bb, test_bb, fallthru_edge->flags);
    3010          341 :       e->probability = fallthru_edge->probability;
    3011          341 :       test_bb->count = fallthru_edge->count ();
    3012              : 
    3013              :       // Now update the edges to the inst/uninist implementations.
    3014              :       // For now assume that the paths are equally likely.  When using HTM,
    3015              :       // we'll try the uninst path first and fallback to inst path if htm
    3016              :       // buffers are exceeded.  Without HTM we start with the inst path and
    3017              :       // use the uninst path when falling back to serial mode.
    3018          341 :       redirect_edge_pred (inst_edge, test_bb);
    3019          341 :       inst_edge->flags = EDGE_FALSE_VALUE;
    3020          341 :       inst_edge->probability = profile_probability::even ();
    3021              : 
    3022          341 :       redirect_edge_pred (uninst_edge, test_bb);
    3023          341 :       uninst_edge->flags = EDGE_TRUE_VALUE;
    3024          341 :       uninst_edge->probability = profile_probability::even ();
    3025              :     }
    3026              : 
    3027              :   // If we have no previous special cases, and we have PHIs at the beginning
    3028              :   // of the atomic region, this means we have a loop at the beginning of the
    3029              :   // atomic region that shares the first block.  This can cause problems with
    3030              :   // the transaction restart abnormal edges to be added in the tm_edges pass.
    3031              :   // Solve this by adding a new empty block to receive the abnormal edges.
    3032          357 :   if (region->restart_block == region->entry_block
    3033          357 :       && phi_nodes (region->entry_block))
    3034              :     {
    3035            0 :       basic_block empty_bb = create_empty_bb (transaction_bb);
    3036            0 :       region->restart_block = empty_bb;
    3037            0 :       add_bb_to_loop (empty_bb, transaction_bb->loop_father);
    3038              : 
    3039            0 :       redirect_edge_pred (fallthru_edge, empty_bb);
    3040            0 :       make_edge (transaction_bb, empty_bb, EDGE_FALLTHRU);
    3041              :     }
    3042              : 
    3043          357 :   return NULL;
    3044              : }
    3045              : 
    3046              : /* Generate the temporary to be used for the return value of
    3047              :    BUILT_IN_TM_START.  */
    3048              : 
    3049              : static void *
    3050          565 : generate_tm_state (struct tm_region *region, void *data ATTRIBUTE_UNUSED)
    3051              : {
    3052          565 :   tree tm_start = builtin_decl_explicit (BUILT_IN_TM_START);
    3053         1130 :   region->tm_state =
    3054          565 :     create_tmp_reg (TREE_TYPE (TREE_TYPE (tm_start)), "tm_state");
    3055              : 
    3056              :   // Reset the subcode, post optimizations.  We'll fill this in
    3057              :   // again as we process blocks.
    3058          565 :   if (region->exit_blocks)
    3059              :     {
    3060          357 :       gtransaction *transaction_stmt = region->get_transaction_stmt ();
    3061          357 :       unsigned int subcode = gimple_transaction_subcode (transaction_stmt);
    3062              : 
    3063          357 :       if (subcode & GTMA_DOES_GO_IRREVOCABLE)
    3064           39 :         subcode &= (GTMA_DECLARATION_MASK | GTMA_DOES_GO_IRREVOCABLE
    3065              :                     | GTMA_MAY_ENTER_IRREVOCABLE
    3066              :                     | GTMA_HAS_NO_INSTRUMENTATION);
    3067              :       else
    3068          318 :         subcode &= GTMA_DECLARATION_MASK;
    3069          357 :       gimple_transaction_set_subcode (transaction_stmt, subcode);
    3070              :     }
    3071              : 
    3072          565 :   return NULL;
    3073              : }
    3074              : 
    3075              : // Propagate flags from inner transactions outwards.
    3076              : static void
    3077         1039 : propagate_tm_flags_out (struct tm_region *region)
    3078              : {
    3079         1604 :   if (region == NULL)
    3080         1039 :     return;
    3081          565 :   propagate_tm_flags_out (region->inner);
    3082              : 
    3083          565 :   if (region->outer && region->outer->transaction_stmt)
    3084              :     {
    3085            8 :       unsigned s
    3086            8 :         = gimple_transaction_subcode (region->get_transaction_stmt ());
    3087            8 :       s &= (GTMA_HAVE_ABORT | GTMA_HAVE_LOAD | GTMA_HAVE_STORE
    3088              :             | GTMA_MAY_ENTER_IRREVOCABLE);
    3089            8 :       s |= gimple_transaction_subcode (region->outer->get_transaction_stmt ());
    3090            8 :       gimple_transaction_set_subcode (region->outer->get_transaction_stmt (),
    3091              :                                       s);
    3092              :     }
    3093              : 
    3094          565 :   propagate_tm_flags_out (region->next);
    3095              : }
    3096              : 
    3097              : /* Entry point to the MARK phase of TM expansion.  Here we replace
    3098              :    transactional memory statements with calls to builtins, and function
    3099              :    calls with their transactional clones (if available).  But we don't
    3100              :    yet lower GIMPLE_TRANSACTION or add the transaction restart back-edges.  */
    3101              : 
    3102              : static unsigned int
    3103          474 : execute_tm_mark (void)
    3104              : {
    3105          474 :   pending_edge_inserts_p = false;
    3106              : 
    3107          474 :   expand_regions (all_tm_regions, generate_tm_state, NULL,
    3108              :                   /*traverse_clones=*/true);
    3109              : 
    3110          474 :   tm_log_init ();
    3111              : 
    3112          474 :   vec<tm_region *> bb_regions
    3113          474 :     = get_bb_regions_instrumented (/*traverse_clones=*/true,
    3114              :                                    /*include_uninstrumented_p=*/false);
    3115          474 :   struct tm_region *r;
    3116          474 :   unsigned i;
    3117              : 
    3118              :   // Expand memory operations into calls into the runtime.
    3119              :   // This collects log entries as well.
    3120         4540 :   FOR_EACH_VEC_ELT (bb_regions, i, r)
    3121              :     {
    3122         4066 :       if (r != NULL)
    3123              :         {
    3124         1575 :           if (r->transaction_stmt)
    3125              :             {
    3126          771 :               unsigned sub
    3127          771 :                 = gimple_transaction_subcode (r->get_transaction_stmt ());
    3128              : 
    3129              :               /* If we're sure to go irrevocable, there won't be
    3130              :                  anything to expand, since the run-time will go
    3131              :                  irrevocable right away.  */
    3132          771 :               if (sub & GTMA_DOES_GO_IRREVOCABLE
    3133          108 :                   && sub & GTMA_MAY_ENTER_IRREVOCABLE)
    3134          108 :                 continue;
    3135              :             }
    3136         1467 :           expand_block_tm (r, BASIC_BLOCK_FOR_FN (cfun, i));
    3137              :         }
    3138              :     }
    3139              : 
    3140          474 :   bb_regions.release ();
    3141              : 
    3142              :   // Propagate flags from inner transactions outwards.
    3143          474 :   propagate_tm_flags_out (all_tm_regions);
    3144              : 
    3145              :   // Expand GIMPLE_TRANSACTIONs into calls into the runtime.
    3146          474 :   expand_regions (all_tm_regions, expand_transaction, NULL,
    3147              :                   /*traverse_clones=*/false);
    3148              : 
    3149          474 :   tm_log_emit ();
    3150          474 :   tm_log_delete ();
    3151              : 
    3152          474 :   if (pending_edge_inserts_p)
    3153            4 :     gsi_commit_edge_inserts ();
    3154          474 :   free_dominance_info (CDI_DOMINATORS);
    3155          474 :   return 0;
    3156              : }
    3157              : 
    3158              : namespace {
    3159              : 
    3160              : const pass_data pass_data_tm_mark =
    3161              : {
    3162              :   GIMPLE_PASS, /* type */
    3163              :   "tmmark", /* name */
    3164              :   OPTGROUP_NONE, /* optinfo_flags */
    3165              :   TV_TRANS_MEM, /* tv_id */
    3166              :   ( PROP_ssa | PROP_cfg ), /* properties_required */
    3167              :   0, /* properties_provided */
    3168              :   0, /* properties_destroyed */
    3169              :   0, /* todo_flags_start */
    3170              :   TODO_update_ssa, /* todo_flags_finish */
    3171              : };
    3172              : 
    3173              : class pass_tm_mark : public gimple_opt_pass
    3174              : {
    3175              : public:
    3176       285722 :   pass_tm_mark (gcc::context *ctxt)
    3177       571444 :     : gimple_opt_pass (pass_data_tm_mark, ctxt)
    3178              :   {}
    3179              : 
    3180              :   /* opt_pass methods: */
    3181          474 :   unsigned int execute (function *) final override
    3182              :   {
    3183          474 :     return execute_tm_mark ();
    3184              :   }
    3185              : 
    3186              : }; // class pass_tm_mark
    3187              : 
    3188              : } // anon namespace
    3189              : 
    3190              : gimple_opt_pass *
    3191       285722 : make_pass_tm_mark (gcc::context *ctxt)
    3192              : {
    3193       285722 :   return new pass_tm_mark (ctxt);
    3194              : }
    3195              : 
    3196              : 
    3197              : /* Create an abnormal edge from STMT at iter, splitting the block
    3198              :    as necessary.  Adjust *PNEXT as needed for the split block.  */
    3199              : 
    3200              : static inline void
    3201          925 : split_bb_make_tm_edge (gimple *stmt, basic_block dest_bb,
    3202              :                        gimple_stmt_iterator iter, gimple_stmt_iterator *pnext)
    3203              : {
    3204          925 :   basic_block bb = gimple_bb (stmt);
    3205          925 :   if (!gsi_one_before_end_p (iter))
    3206              :     {
    3207          526 :       edge e = split_block (bb, stmt);
    3208         1052 :       *pnext = gsi_start_bb (e->dest);
    3209              :     }
    3210          925 :   edge e = make_edge (bb, dest_bb, EDGE_ABNORMAL);
    3211          925 :   if (e)
    3212          900 :     e->probability = profile_probability::guessed_never ();
    3213              : 
    3214              :   // Record the need for the edge for the benefit of the rtl passes.
    3215          925 :   if (cfun->gimple_df->tm_restart == NULL)
    3216            8 :     cfun->gimple_df->tm_restart
    3217            8 :       = hash_table<tm_restart_hasher>::create_ggc (31);
    3218              : 
    3219          925 :   struct tm_restart_node dummy;
    3220          925 :   dummy.stmt = stmt;
    3221          925 :   dummy.label_or_list = gimple_block_label (dest_bb);
    3222              : 
    3223          925 :   tm_restart_node **slot = cfun->gimple_df->tm_restart->find_slot (&dummy,
    3224              :                                                                    INSERT);
    3225          925 :   struct tm_restart_node *n = *slot;
    3226          925 :   if (n == NULL)
    3227              :     {
    3228          925 :       *slot = n = ggc_alloc<tm_restart_node> ();
    3229          925 :       *n = dummy;
    3230              :     }
    3231              :   else
    3232              :     {
    3233            0 :       tree old = n->label_or_list;
    3234            0 :       if (TREE_CODE (old) == LABEL_DECL)
    3235            0 :         old = tree_cons (NULL, old, NULL);
    3236            0 :       n->label_or_list = tree_cons (NULL, dummy.label_or_list, old);
    3237              :     }
    3238          925 : }
    3239              : 
    3240              : /* Split block BB as necessary for every builtin function we added, and
    3241              :    wire up the abnormal back edges implied by the transaction restart.  */
    3242              : 
    3243              : static void
    3244          779 : expand_block_edges (struct tm_region *const region, basic_block bb)
    3245              : {
    3246          779 :   gimple_stmt_iterator gsi, next_gsi;
    3247              : 
    3248         4538 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi = next_gsi)
    3249              :     {
    3250         2980 :       gimple *stmt = gsi_stmt (gsi);
    3251         2980 :       gcall *call_stmt;
    3252              : 
    3253         2980 :       next_gsi = gsi;
    3254         2980 :       gsi_next (&next_gsi);
    3255              : 
    3256              :       // ??? Shouldn't we split for any non-pure, non-irrevocable function?
    3257         2980 :       call_stmt = dyn_cast <gcall *> (stmt);
    3258         3302 :       if ((!call_stmt)
    3259         1280 :           || (gimple_call_flags (call_stmt) & ECF_TM_BUILTIN) == 0)
    3260         2022 :         continue;
    3261              : 
    3262          958 :       if (gimple_call_builtin_p (call_stmt, BUILT_IN_TM_ABORT))
    3263              :         {
    3264              :           // If we have a ``_transaction_cancel [[outer]]'', there is only
    3265              :           // one abnormal edge: to the transaction marked OUTER.
    3266              :           // All compiler-generated instances of BUILT_IN_TM_ABORT have a
    3267              :           // constant argument, which we can examine here.  Users invoking
    3268              :           // TM_ABORT directly get what they deserve.
    3269           35 :           tree arg = gimple_call_arg (call_stmt, 0);
    3270           35 :           if (TREE_CODE (arg) == INTEGER_CST
    3271           35 :               && (TREE_INT_CST_LOW (arg) & AR_OUTERABORT) != 0
    3272           43 :               && !decl_is_tm_clone (current_function_decl))
    3273              :             {
    3274              :               // Find the GTMA_IS_OUTER transaction.
    3275            8 :               for (struct tm_region *o = region; o; o = o->outer)
    3276            6 :                 if (o->original_transaction_was_outer)
    3277              :                   {
    3278            2 :                     split_bb_make_tm_edge (call_stmt, o->restart_block,
    3279              :                                            gsi, &next_gsi);
    3280            2 :                     break;
    3281              :                   }
    3282              : 
    3283              :               // Otherwise, the front-end should have semantically checked
    3284              :               // outer aborts, but in either case the target region is not
    3285              :               // within this function.
    3286            4 :               continue;
    3287            4 :             }
    3288              : 
    3289              :           // Non-outer, TM aborts have an abnormal edge to the inner-most
    3290              :           // transaction, the one being aborted;
    3291           31 :           split_bb_make_tm_edge (call_stmt, region->restart_block, gsi,
    3292              :                                  &next_gsi);
    3293              :         }
    3294              : 
    3295              :       // All TM builtins have an abnormal edge to the outer-most transaction.
    3296              :       // We never restart inner transactions.  For tm clones, we know a-priori
    3297              :       // that the outer-most transaction is outside the function.
    3298         1908 :       if (decl_is_tm_clone (current_function_decl))
    3299           62 :         continue;
    3300              : 
    3301          892 :       if (cfun->gimple_df->tm_restart == NULL)
    3302          257 :         cfun->gimple_df->tm_restart
    3303          257 :           = hash_table<tm_restart_hasher>::create_ggc (31);
    3304              : 
    3305              :       // All TM builtins have an abnormal edge to the outer-most transaction.
    3306              :       // We never restart inner transactions.
    3307          928 :       for (struct tm_region *o = region; o; o = o->outer)
    3308          928 :         if (!o->outer)
    3309              :           {
    3310          892 :             split_bb_make_tm_edge (call_stmt, o->restart_block, gsi, &next_gsi);
    3311          892 :             break;
    3312              :           }
    3313              : 
    3314              :       // Delete any tail-call annotation that may have been added.
    3315              :       // The tail-call pass may have mis-identified the commit as being
    3316              :       // a candidate because we had not yet added this restart edge.
    3317          892 :       gimple_call_set_tail (call_stmt, false);
    3318              :     }
    3319          779 : }
    3320              : 
    3321              : /* Entry point to the final expansion of transactional nodes. */
    3322              : 
    3323              : namespace {
    3324              : 
    3325              : const pass_data pass_data_tm_edges =
    3326              : {
    3327              :   GIMPLE_PASS, /* type */
    3328              :   "tmedge", /* name */
    3329              :   OPTGROUP_NONE, /* optinfo_flags */
    3330              :   TV_TRANS_MEM, /* tv_id */
    3331              :   ( PROP_ssa | PROP_cfg ), /* properties_required */
    3332              :   0, /* properties_provided */
    3333              :   0, /* properties_destroyed */
    3334              :   0, /* todo_flags_start */
    3335              :   TODO_update_ssa, /* todo_flags_finish */
    3336              : };
    3337              : 
    3338              : class pass_tm_edges : public gimple_opt_pass
    3339              : {
    3340              : public:
    3341       285722 :   pass_tm_edges (gcc::context *ctxt)
    3342       571444 :     : gimple_opt_pass (pass_data_tm_edges, ctxt)
    3343              :   {}
    3344              : 
    3345              :   /* opt_pass methods: */
    3346              :   unsigned int execute (function *) final override;
    3347              : 
    3348              : }; // class pass_tm_edges
    3349              : 
    3350              : unsigned int
    3351          474 : pass_tm_edges::execute (function *fun)
    3352              : {
    3353          474 :   vec<tm_region *> bb_regions
    3354          474 :     = get_bb_regions_instrumented (/*traverse_clones=*/false,
    3355              :                                    /*include_uninstrumented_p=*/true);
    3356          474 :   struct tm_region *r;
    3357          474 :   unsigned i;
    3358              : 
    3359         5454 :   FOR_EACH_VEC_ELT (bb_regions, i, r)
    3360         4506 :     if (r != NULL)
    3361          779 :       expand_block_edges (r, BASIC_BLOCK_FOR_FN (fun, i));
    3362              : 
    3363          474 :   bb_regions.release ();
    3364              : 
    3365              :   /* We've got to release the dominance info now, to indicate that it
    3366              :      must be rebuilt completely.  Otherwise we'll crash trying to update
    3367              :      the SSA web in the TODO section following this pass.  */
    3368          474 :   free_dominance_info (CDI_DOMINATORS);
    3369              :   /* We'ge also wrecked loops badly with inserting of abnormal edges.  */
    3370          474 :   loops_state_set (LOOPS_NEED_FIXUP);
    3371          474 :   bitmap_obstack_release (&tm_obstack);
    3372          474 :   all_tm_regions = NULL;
    3373              : 
    3374          474 :   return 0;
    3375              : }
    3376              : 
    3377              : } // anon namespace
    3378              : 
    3379              : gimple_opt_pass *
    3380       285722 : make_pass_tm_edges (gcc::context *ctxt)
    3381              : {
    3382       285722 :   return new pass_tm_edges (ctxt);
    3383              : }
    3384              : 
    3385              : /* Helper function for expand_regions.  Expand REGION and recurse to
    3386              :    the inner region.  Call CALLBACK on each region.  CALLBACK returns
    3387              :    NULL to continue the traversal, otherwise a non-null value which
    3388              :    this function will return as well.  TRAVERSE_CLONES is true if we
    3389              :    should traverse transactional clones.  */
    3390              : 
    3391              : static void *
    3392         2260 : expand_regions_1 (struct tm_region *region,
    3393              :                   void *(*callback)(struct tm_region *, void *),
    3394              :                   void *data,
    3395              :                   bool traverse_clones)
    3396              : {
    3397         2260 :   void *retval = NULL;
    3398         2260 :   if (region->exit_blocks
    3399         2676 :       || (traverse_clones && decl_is_tm_clone (current_function_decl)))
    3400              :     {
    3401         1844 :       retval = callback (region, data);
    3402         1844 :       if (retval)
    3403              :         return retval;
    3404              :     }
    3405         2260 :   if (region->inner)
    3406              :     {
    3407           84 :       retval = expand_regions (region->inner, callback, data, traverse_clones);
    3408           84 :       if (retval)
    3409              :         return retval;
    3410              :     }
    3411              :   return retval;
    3412              : }
    3413              : 
    3414              : /* Traverse the regions enclosed and including REGION.  Execute
    3415              :    CALLBACK for each region, passing DATA.  CALLBACK returns NULL to
    3416              :    continue the traversal, otherwise a non-null value which this
    3417              :    function will return as well.  TRAVERSE_CLONES is true if we should
    3418              :    traverse transactional clones.  */
    3419              : 
    3420              : static void *
    3421         1980 : expand_regions (struct tm_region *region,
    3422              :                 void *(*callback)(struct tm_region *, void *),
    3423              :                 void *data,
    3424              :                 bool traverse_clones)
    3425              : {
    3426         1980 :   void *retval = NULL;
    3427         4240 :   while (region)
    3428              :     {
    3429         2260 :       retval = expand_regions_1 (region, callback, data, traverse_clones);
    3430         2260 :       if (retval)
    3431              :         return retval;
    3432         2260 :       region = region->next;
    3433              :     }
    3434              :   return retval;
    3435              : }
    3436              : 
    3437              : 
    3438              : /* A unique TM memory operation.  */
    3439              : struct tm_memop
    3440              : {
    3441              :   /* Unique ID that all memory operations to the same location have.  */
    3442              :   unsigned int value_id;
    3443              :   /* Address of load/store.  */
    3444              :   tree addr;
    3445              : };
    3446              : 
    3447              : /* TM memory operation hashtable helpers.  */
    3448              : 
    3449              : struct tm_memop_hasher : free_ptr_hash <tm_memop>
    3450              : {
    3451              :   static inline hashval_t hash (const tm_memop *);
    3452              :   static inline bool equal (const tm_memop *, const tm_memop *);
    3453              : };
    3454              : 
    3455              : /* Htab support.  Return a hash value for a `tm_memop'.  */
    3456              : inline hashval_t
    3457         1830 : tm_memop_hasher::hash (const tm_memop *mem)
    3458              : {
    3459         1830 :   tree addr = mem->addr;
    3460              :   /* We drill down to the SSA_NAME/DECL for the hash, but equality is
    3461              :      actually done with operand_equal_p (see tm_memop_eq).  */
    3462         1830 :   if (TREE_CODE (addr) == ADDR_EXPR)
    3463          754 :     addr = TREE_OPERAND (addr, 0);
    3464         1830 :   return iterative_hash_expr (addr, 0);
    3465              : }
    3466              : 
    3467              : /* Htab support.  Return true if two tm_memop's are the same.  */
    3468              : inline bool
    3469         1292 : tm_memop_hasher::equal (const tm_memop *mem1, const tm_memop *mem2)
    3470              : {
    3471         1292 :   return operand_equal_p (mem1->addr, mem2->addr, 0);
    3472              : }
    3473              : 
    3474              : /* Sets for solving data flow equations in the memory optimization pass.  */
    3475              : struct tm_memopt_bitmaps
    3476              : {
    3477              :   /* Stores available to this BB upon entry.  Basically, stores that
    3478              :      dominate this BB.  */
    3479              :   bitmap store_avail_in;
    3480              :   /* Stores available at the end of this BB.  */
    3481              :   bitmap store_avail_out;
    3482              :   bitmap store_antic_in;
    3483              :   bitmap store_antic_out;
    3484              :   /* Reads available to this BB upon entry.  Basically, reads that
    3485              :      dominate this BB.  */
    3486              :   bitmap read_avail_in;
    3487              :   /* Reads available at the end of this BB.  */
    3488              :   bitmap read_avail_out;
    3489              :   /* Reads performed in this BB.  */
    3490              :   bitmap read_local;
    3491              :   /* Writes performed in this BB.  */
    3492              :   bitmap store_local;
    3493              : 
    3494              :   /* Temporary storage for pass.  */
    3495              :   /* Is the current BB in the worklist?  */
    3496              :   bool avail_in_worklist_p;
    3497              :   /* Have we visited this BB?  */
    3498              :   bool visited_p;
    3499              : };
    3500              : 
    3501              : static bitmap_obstack tm_memopt_obstack;
    3502              : 
    3503              : /* Unique counter for TM loads and stores. Loads and stores of the
    3504              :    same address get the same ID.  */
    3505              : static unsigned int tm_memopt_value_id;
    3506              : static hash_table<tm_memop_hasher> *tm_memopt_value_numbers;
    3507              : 
    3508              : #define STORE_AVAIL_IN(BB) \
    3509              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_avail_in
    3510              : #define STORE_AVAIL_OUT(BB) \
    3511              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_avail_out
    3512              : #define STORE_ANTIC_IN(BB) \
    3513              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_antic_in
    3514              : #define STORE_ANTIC_OUT(BB) \
    3515              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_antic_out
    3516              : #define READ_AVAIL_IN(BB) \
    3517              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_avail_in
    3518              : #define READ_AVAIL_OUT(BB) \
    3519              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_avail_out
    3520              : #define READ_LOCAL(BB) \
    3521              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->read_local
    3522              : #define STORE_LOCAL(BB) \
    3523              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->store_local
    3524              : #define AVAIL_IN_WORKLIST_P(BB) \
    3525              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->avail_in_worklist_p
    3526              : #define BB_VISITED_P(BB) \
    3527              :   ((struct tm_memopt_bitmaps *) ((BB)->aux))->visited_p
    3528              : 
    3529              : /* Given a TM load/store in STMT, return the value number for the address
    3530              :    it accesses.  */
    3531              : 
    3532              : static unsigned int
    3533          664 : tm_memopt_value_number (gimple *stmt, enum insert_option op)
    3534              : {
    3535          664 :   struct tm_memop tmpmem, *mem;
    3536          664 :   tm_memop **slot;
    3537              : 
    3538          664 :   gcc_assert (is_tm_load (stmt) || is_tm_store (stmt));
    3539          664 :   tmpmem.addr = gimple_call_arg (stmt, 0);
    3540          664 :   slot = tm_memopt_value_numbers->find_slot (&tmpmem, op);
    3541          664 :   if (*slot)
    3542              :     mem = *slot;
    3543          284 :   else if (op == INSERT)
    3544              :     {
    3545          284 :       mem = XNEW (struct tm_memop);
    3546          284 :       *slot = mem;
    3547          284 :       mem->value_id = tm_memopt_value_id++;
    3548          284 :       mem->addr = tmpmem.addr;
    3549              :     }
    3550              :   else
    3551            0 :     gcc_unreachable ();
    3552          664 :   return mem->value_id;
    3553              : }
    3554              : 
    3555              : /* Accumulate TM memory operations in BB into STORE_LOCAL and READ_LOCAL.  */
    3556              : 
    3557              : static void
    3558          621 : tm_memopt_accumulate_memops (basic_block bb)
    3559              : {
    3560          621 :   gimple_stmt_iterator gsi;
    3561              : 
    3562         3209 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    3563              :     {
    3564         1967 :       gimple *stmt = gsi_stmt (gsi);
    3565         1967 :       bitmap bits;
    3566         1967 :       unsigned int loc;
    3567              : 
    3568         1967 :       if (is_tm_store (stmt))
    3569          111 :         bits = STORE_LOCAL (bb);
    3570         1856 :       else if (is_tm_load (stmt))
    3571          221 :         bits = READ_LOCAL (bb);
    3572              :       else
    3573         1635 :         continue;
    3574              : 
    3575          332 :       loc = tm_memopt_value_number (stmt, INSERT);
    3576          332 :       bitmap_set_bit (bits, loc);
    3577          332 :       if (dump_file)
    3578              :         {
    3579           17 :           fprintf (dump_file, "TM memopt (%s): value num=%d, BB=%d, addr=",
    3580           11 :                    is_tm_load (stmt) ? "LOAD" : "STORE", loc,
    3581           11 :                    gimple_bb (stmt)->index);
    3582           11 :           print_generic_expr (dump_file, gimple_call_arg (stmt, 0));
    3583           11 :           fprintf (dump_file, "\n");
    3584              :         }
    3585              :     }
    3586          621 : }
    3587              : 
    3588              : /* Prettily dump one of the memopt sets.  BITS is the bitmap to dump.  */
    3589              : 
    3590              : static void
    3591           96 : dump_tm_memopt_set (const char *set_name, bitmap bits)
    3592              : {
    3593           96 :   unsigned i;
    3594           96 :   bitmap_iterator bi;
    3595           96 :   const char *comma = "";
    3596              : 
    3597           96 :   fprintf (dump_file, "TM memopt: %s: [", set_name);
    3598          228 :   EXECUTE_IF_SET_IN_BITMAP (bits, 0, i, bi)
    3599              :     {
    3600          132 :       hash_table<tm_memop_hasher>::iterator hi;
    3601          132 :       struct tm_memop *mem = NULL;
    3602              : 
    3603              :       /* Yeah, yeah, yeah.  Whatever.  This is just for debugging.  */
    3604          556 :       FOR_EACH_HASH_TABLE_ELEMENT (*tm_memopt_value_numbers, mem, tm_memop_t, hi)
    3605          344 :         if (mem->value_id == i)
    3606              :           break;
    3607          132 :       gcc_assert (mem->value_id == i);
    3608          132 :       fprintf (dump_file, "%s", comma);
    3609          132 :       comma = ", ";
    3610          132 :       print_generic_expr (dump_file, mem->addr);
    3611              :     }
    3612           96 :   fprintf (dump_file, "]\n");
    3613           96 : }
    3614              : 
    3615              : /* Prettily dump all of the memopt sets in BLOCKS.  */
    3616              : 
    3617              : static void
    3618            4 : dump_tm_memopt_sets (vec<basic_block> blocks)
    3619              : {
    3620            4 :   size_t i;
    3621            4 :   basic_block bb;
    3622              : 
    3623           20 :   for (i = 0; blocks.iterate (i, &bb); ++i)
    3624              :     {
    3625           16 :       fprintf (dump_file, "------------BB %d---------\n", bb->index);
    3626           16 :       dump_tm_memopt_set ("STORE_LOCAL", STORE_LOCAL (bb));
    3627           16 :       dump_tm_memopt_set ("READ_LOCAL", READ_LOCAL (bb));
    3628           16 :       dump_tm_memopt_set ("STORE_AVAIL_IN", STORE_AVAIL_IN (bb));
    3629           16 :       dump_tm_memopt_set ("STORE_AVAIL_OUT", STORE_AVAIL_OUT (bb));
    3630           16 :       dump_tm_memopt_set ("READ_AVAIL_IN", READ_AVAIL_IN (bb));
    3631           16 :       dump_tm_memopt_set ("READ_AVAIL_OUT", READ_AVAIL_OUT (bb));
    3632              :     }
    3633            4 : }
    3634              : 
    3635              : /* Compute {STORE,READ}_AVAIL_IN for the basic block BB.  */
    3636              : 
    3637              : static void
    3638          432 : tm_memopt_compute_avin (basic_block bb)
    3639              : {
    3640          432 :   edge e;
    3641          432 :   unsigned ix;
    3642              : 
    3643              :   /* Seed with the AVOUT of any predecessor.  */
    3644          461 :   for (ix = 0; ix < EDGE_COUNT (bb->preds); ix++)
    3645              :     {
    3646          461 :       e = EDGE_PRED (bb, ix);
    3647              :       /* Make sure we have already visited this BB, and is thus
    3648              :          initialized.
    3649              : 
    3650              :           If e->src->aux is NULL, this predecessor is actually on an
    3651              :           enclosing transaction.  We only care about the current
    3652              :           transaction, so ignore it.  */
    3653          461 :       if (e->src->aux && BB_VISITED_P (e->src))
    3654              :         {
    3655          432 :           bitmap_copy (STORE_AVAIL_IN (bb), STORE_AVAIL_OUT (e->src));
    3656          432 :           bitmap_copy (READ_AVAIL_IN (bb), READ_AVAIL_OUT (e->src));
    3657          432 :           break;
    3658              :         }
    3659              :     }
    3660              : 
    3661          968 :   for (; ix < EDGE_COUNT (bb->preds); ix++)
    3662              :     {
    3663          536 :       e = EDGE_PRED (bb, ix);
    3664          536 :       if (e->src->aux && BB_VISITED_P (e->src))
    3665              :         {
    3666          513 :           bitmap_and_into (STORE_AVAIL_IN (bb), STORE_AVAIL_OUT (e->src));
    3667          513 :           bitmap_and_into (READ_AVAIL_IN (bb), READ_AVAIL_OUT (e->src));
    3668              :         }
    3669              :     }
    3670              : 
    3671          432 :   BB_VISITED_P (bb) = true;
    3672          432 : }
    3673              : 
    3674              : /* Compute the STORE_ANTIC_IN for the basic block BB.  */
    3675              : 
    3676              : static void
    3677          230 : tm_memopt_compute_antin (basic_block bb)
    3678              : {
    3679          230 :   edge e;
    3680          230 :   unsigned ix;
    3681              : 
    3682              :   /* Seed with the ANTIC_OUT of any successor.  */
    3683          251 :   for (ix = 0; ix < EDGE_COUNT (bb->succs); ix++)
    3684              :     {
    3685          205 :       e = EDGE_SUCC (bb, ix);
    3686              :       /* Make sure we have already visited this BB, and is thus
    3687              :          initialized.  */
    3688          205 :       if (BB_VISITED_P (e->dest))
    3689              :         {
    3690          184 :           bitmap_copy (STORE_ANTIC_IN (bb), STORE_ANTIC_OUT (e->dest));
    3691          184 :           break;
    3692              :         }
    3693              :     }
    3694              : 
    3695          512 :   for (; ix < EDGE_COUNT (bb->succs); ix++)
    3696              :     {
    3697          282 :       e = EDGE_SUCC (bb, ix);
    3698          282 :       if (BB_VISITED_P  (e->dest))
    3699          282 :         bitmap_and_into (STORE_ANTIC_IN (bb), STORE_ANTIC_OUT (e->dest));
    3700              :     }
    3701              : 
    3702          230 :   BB_VISITED_P (bb) = true;
    3703          230 : }
    3704              : 
    3705              : /* Compute the AVAIL sets for every basic block in BLOCKS.
    3706              : 
    3707              :    We compute {STORE,READ}_AVAIL_{OUT,IN} as follows:
    3708              : 
    3709              :      AVAIL_OUT[bb] = union (AVAIL_IN[bb], LOCAL[bb])
    3710              :      AVAIL_IN[bb]  = intersect (AVAIL_OUT[predecessors])
    3711              : 
    3712              :    This is basically what we do in lcm's compute_available(), but here
    3713              :    we calculate two sets of sets (one for STOREs and one for READs),
    3714              :    and we work on a region instead of the entire CFG.
    3715              : 
    3716              :    REGION is the TM region.
    3717              :    BLOCKS are the basic blocks in the region.  */
    3718              : 
    3719              : static void
    3720          221 : tm_memopt_compute_available (struct tm_region *region,
    3721              :                              vec<basic_block> blocks)
    3722              : {
    3723          221 :   edge e;
    3724          221 :   basic_block *worklist, *qin, *qout, *qend, bb;
    3725          221 :   unsigned int qlen, i;
    3726          221 :   edge_iterator ei;
    3727          221 :   bool changed;
    3728              : 
    3729              :   /* Allocate a worklist array/queue.  Entries are only added to the
    3730              :      list if they were not already on the list.  So the size is
    3731              :      bounded by the number of basic blocks in the region.  */
    3732          221 :   gcc_assert (!blocks.is_empty ());
    3733          221 :   qlen = blocks.length () - 1;
    3734          221 :   qin = qout = worklist = XNEWVEC (basic_block, qlen);
    3735              : 
    3736              :   /* Put every block in the region on the worklist.  */
    3737         1063 :   for (i = 0; blocks.iterate (i, &bb); ++i)
    3738              :     {
    3739              :       /* Seed AVAIL_OUT with the LOCAL set.  */
    3740          621 :       bitmap_ior_into (STORE_AVAIL_OUT (bb), STORE_LOCAL (bb));
    3741          621 :       bitmap_ior_into (READ_AVAIL_OUT (bb), READ_LOCAL (bb));
    3742              : 
    3743          621 :       AVAIL_IN_WORKLIST_P (bb) = true;
    3744              :       /* No need to insert the entry block, since it has an AVIN of
    3745              :          null, and an AVOUT that has already been seeded in.  */
    3746          621 :       if (bb != region->entry_block)
    3747          400 :         *qin++ = bb;
    3748              :     }
    3749              : 
    3750              :   /* The entry block has been initialized with the local sets.  */
    3751          221 :   BB_VISITED_P (region->entry_block) = true;
    3752              : 
    3753          221 :   qin = worklist;
    3754          221 :   qend = &worklist[qlen];
    3755              : 
    3756              :   /* Iterate until the worklist is empty.  */
    3757          653 :   while (qlen)
    3758              :     {
    3759              :       /* Take the first entry off the worklist.  */
    3760          432 :       bb = *qout++;
    3761          432 :       qlen--;
    3762              : 
    3763          432 :       if (qout >= qend)
    3764           95 :         qout = worklist;
    3765              : 
    3766              :       /* This block can be added to the worklist again if necessary.  */
    3767          432 :       AVAIL_IN_WORKLIST_P (bb) = false;
    3768          432 :       tm_memopt_compute_avin (bb);
    3769              : 
    3770              :       /* Note: We do not add the LOCAL sets here because we already
    3771              :          seeded the AVAIL_OUT sets with them.  */
    3772          432 :       changed  = bitmap_ior_into (STORE_AVAIL_OUT (bb), STORE_AVAIL_IN (bb));
    3773          432 :       changed |= bitmap_ior_into (READ_AVAIL_OUT (bb), READ_AVAIL_IN (bb));
    3774          432 :       if (changed
    3775          432 :           && (region->exit_blocks == NULL
    3776          150 :               || !bitmap_bit_p (region->exit_blocks, bb->index)))
    3777              :         /* If the out state of this block changed, then we need to add
    3778              :            its successors to the worklist if they are not already in.  */
    3779          454 :         FOR_EACH_EDGE (e, ei, bb->succs)
    3780          236 :           if (!AVAIL_IN_WORKLIST_P (e->dest)
    3781           32 :               && e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
    3782              :             {
    3783           32 :               *qin++ = e->dest;
    3784           32 :               AVAIL_IN_WORKLIST_P (e->dest) = true;
    3785           32 :               qlen++;
    3786              : 
    3787           32 :               if (qin >= qend)
    3788            0 :                 qin = worklist;
    3789              :             }
    3790              :     }
    3791              : 
    3792          221 :   free (worklist);
    3793              : 
    3794          221 :   if (dump_file)
    3795            2 :     dump_tm_memopt_sets (blocks);
    3796          221 : }
    3797              : 
    3798              : /* Compute ANTIC sets for every basic block in BLOCKS.
    3799              : 
    3800              :    We compute STORE_ANTIC_OUT as follows:
    3801              : 
    3802              :         STORE_ANTIC_OUT[bb] = union(STORE_ANTIC_IN[bb], STORE_LOCAL[bb])
    3803              :         STORE_ANTIC_IN[bb]  = intersect(STORE_ANTIC_OUT[successors])
    3804              : 
    3805              :    REGION is the TM region.
    3806              :    BLOCKS are the basic blocks in the region.  */
    3807              : 
    3808              : static void
    3809          221 : tm_memopt_compute_antic (struct tm_region *region,
    3810              :                          vec<basic_block> blocks)
    3811              : {
    3812          221 :   edge e;
    3813          221 :   basic_block *worklist, *qin, *qout, *qend, bb;
    3814          221 :   unsigned int qlen;
    3815          221 :   int i;
    3816          221 :   edge_iterator ei;
    3817              : 
    3818              :   /* Allocate a worklist array/queue.  Entries are only added to the
    3819              :      list if they were not already on the list.  So the size is
    3820              :      bounded by the number of basic blocks in the region.  */
    3821          442 :   qin = qout = worklist = XNEWVEC (basic_block, blocks.length ());
    3822              : 
    3823         1063 :   for (qlen = 0, i = blocks.length () - 1; i >= 0; --i)
    3824              :     {
    3825          621 :       bb = blocks[i];
    3826              : 
    3827              :       /* Seed ANTIC_OUT with the LOCAL set.  */
    3828          621 :       bitmap_ior_into (STORE_ANTIC_OUT (bb), STORE_LOCAL (bb));
    3829              : 
    3830              :       /* Put every block in the region on the worklist.  */
    3831          621 :       AVAIL_IN_WORKLIST_P (bb) = true;
    3832              :       /* No need to insert exit blocks, since their ANTIC_IN is NULL,
    3833              :          and their ANTIC_OUT has already been seeded in.  */
    3834          621 :       if (region->exit_blocks
    3835          621 :           && !bitmap_bit_p (region->exit_blocks, bb->index))
    3836              :         {
    3837          230 :           qlen++;
    3838          230 :           *qin++ = bb;
    3839              :         }
    3840              :     }
    3841              : 
    3842              :   /* The exit blocks have been initialized with the local sets.  */
    3843          221 :   if (region->exit_blocks)
    3844              :     {
    3845          181 :       unsigned int i;
    3846          181 :       bitmap_iterator bi;
    3847          381 :       EXECUTE_IF_SET_IN_BITMAP (region->exit_blocks, 0, i, bi)
    3848          200 :         BB_VISITED_P (BASIC_BLOCK_FOR_FN (cfun, i)) = true;
    3849              :     }
    3850              : 
    3851          221 :   qin = worklist;
    3852          221 :   qend = &worklist[qlen];
    3853              : 
    3854              :   /* Iterate until the worklist is empty.  */
    3855          451 :   while (qlen)
    3856              :     {
    3857              :       /* Take the first entry off the worklist.  */
    3858          230 :       bb = *qout++;
    3859          230 :       qlen--;
    3860              : 
    3861          230 :       if (qout >= qend)
    3862           62 :         qout = worklist;
    3863              : 
    3864              :       /* This block can be added to the worklist again if necessary.  */
    3865          230 :       AVAIL_IN_WORKLIST_P (bb) = false;
    3866          230 :       tm_memopt_compute_antin (bb);
    3867              : 
    3868              :       /* Note: We do not add the LOCAL sets here because we already
    3869              :          seeded the ANTIC_OUT sets with them.  */
    3870          230 :       if (bitmap_ior_into (STORE_ANTIC_OUT (bb), STORE_ANTIC_IN (bb))
    3871          230 :           && bb != region->entry_block)
    3872              :         /* If the out state of this block changed, then we need to add
    3873              :            its predecessors to the worklist if they are not already in.  */
    3874            0 :         FOR_EACH_EDGE (e, ei, bb->preds)
    3875            0 :           if (!AVAIL_IN_WORKLIST_P (e->src))
    3876              :             {
    3877            0 :               *qin++ = e->src;
    3878            0 :               AVAIL_IN_WORKLIST_P (e->src) = true;
    3879            0 :               qlen++;
    3880              : 
    3881            0 :               if (qin >= qend)
    3882            0 :                 qin = worklist;
    3883              :             }
    3884              :     }
    3885              : 
    3886          221 :   free (worklist);
    3887              : 
    3888          221 :   if (dump_file)
    3889            2 :     dump_tm_memopt_sets (blocks);
    3890          221 : }
    3891              : 
    3892              : /* Offsets of load variants from TM_LOAD.  For example,
    3893              :    BUILT_IN_TM_LOAD_RAR* is an offset of 1 from BUILT_IN_TM_LOAD*.
    3894              :    See gtm-builtins.def.  */
    3895              : #define TRANSFORM_RAR 1
    3896              : #define TRANSFORM_RAW 2
    3897              : #define TRANSFORM_RFW 3
    3898              : /* Offsets of store variants from TM_STORE.  */
    3899              : #define TRANSFORM_WAR 1
    3900              : #define TRANSFORM_WAW 2
    3901              : 
    3902              : /* Inform about a load/store optimization.  */
    3903              : 
    3904              : static void
    3905           87 : dump_tm_memopt_transform (gimple *stmt)
    3906              : {
    3907           87 :   if (dump_file)
    3908              :     {
    3909            7 :       fprintf (dump_file, "TM memopt: transforming: ");
    3910            7 :       print_gimple_stmt (dump_file, stmt, 0);
    3911            7 :       fprintf (dump_file, "\n");
    3912              :     }
    3913           87 : }
    3914              : 
    3915              : /* Perform a read/write optimization.  Replaces the TM builtin in STMT
    3916              :    by a builtin that is OFFSET entries down in the builtins table in
    3917              :    gtm-builtins.def.  */
    3918              : 
    3919              : static void
    3920           87 : tm_memopt_transform_stmt (unsigned int offset,
    3921              :                           gcall *stmt,
    3922              :                           gimple_stmt_iterator *gsi)
    3923              : {
    3924           87 :   tree fn = gimple_call_fn (stmt);
    3925           87 :   gcc_assert (TREE_CODE (fn) == ADDR_EXPR);
    3926           87 :   TREE_OPERAND (fn, 0)
    3927          174 :     = builtin_decl_explicit ((enum built_in_function)
    3928           87 :                              (DECL_FUNCTION_CODE (TREE_OPERAND (fn, 0))
    3929           87 :                               + offset));
    3930           87 :   gimple_call_set_fn (stmt, fn);
    3931           87 :   gsi_replace (gsi, stmt, true);
    3932           87 :   dump_tm_memopt_transform (stmt);
    3933           87 : }
    3934              : 
    3935              : /* Perform the actual TM memory optimization transformations in the
    3936              :    basic blocks in BLOCKS.  */
    3937              : 
    3938              : static void
    3939          221 : tm_memopt_transform_blocks (vec<basic_block> blocks)
    3940              : {
    3941          221 :   size_t i;
    3942          221 :   basic_block bb;
    3943          221 :   gimple_stmt_iterator gsi;
    3944              : 
    3945          842 :   for (i = 0; blocks.iterate (i, &bb); ++i)
    3946              :     {
    3947         3209 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    3948              :         {
    3949         1967 :           gimple *stmt = gsi_stmt (gsi);
    3950         1967 :           bitmap read_avail = READ_AVAIL_IN (bb);
    3951         1967 :           bitmap store_avail = STORE_AVAIL_IN (bb);
    3952         1967 :           bitmap store_antic = STORE_ANTIC_OUT (bb);
    3953         1967 :           unsigned int loc;
    3954              : 
    3955         1967 :           if (is_tm_simple_load (stmt))
    3956              :             {
    3957          221 :               gcall *call_stmt = as_a <gcall *> (stmt);
    3958          221 :               loc = tm_memopt_value_number (stmt, NO_INSERT);
    3959          221 :               if (store_avail && bitmap_bit_p (store_avail, loc))
    3960            4 :                 tm_memopt_transform_stmt (TRANSFORM_RAW, call_stmt, &gsi);
    3961          217 :               else if (store_antic && bitmap_bit_p (store_antic, loc))
    3962              :                 {
    3963           39 :                   tm_memopt_transform_stmt (TRANSFORM_RFW, call_stmt, &gsi);
    3964           39 :                   bitmap_set_bit (store_avail, loc);
    3965              :                 }
    3966          178 :               else if (read_avail && bitmap_bit_p (read_avail, loc))
    3967            0 :                 tm_memopt_transform_stmt (TRANSFORM_RAR, call_stmt, &gsi);
    3968              :               else
    3969          178 :                 bitmap_set_bit (read_avail, loc);
    3970              :             }
    3971         1746 :           else if (is_tm_simple_store (stmt))
    3972              :             {
    3973          111 :               gcall *call_stmt = as_a <gcall *> (stmt);
    3974          111 :               loc = tm_memopt_value_number (stmt, NO_INSERT);
    3975          111 :               if (store_avail && bitmap_bit_p (store_avail, loc))
    3976           40 :                 tm_memopt_transform_stmt (TRANSFORM_WAW, call_stmt, &gsi);
    3977              :               else
    3978              :                 {
    3979           71 :                   if (read_avail && bitmap_bit_p (read_avail, loc))
    3980            4 :                     tm_memopt_transform_stmt (TRANSFORM_WAR, call_stmt, &gsi);
    3981           71 :                   bitmap_set_bit (store_avail, loc);
    3982              :                 }
    3983              :             }
    3984              :         }
    3985              :     }
    3986          221 : }
    3987              : 
    3988              : /* Return a new set of bitmaps for a BB.  */
    3989              : 
    3990              : static struct tm_memopt_bitmaps *
    3991          621 : tm_memopt_init_sets (void)
    3992              : {
    3993          621 :   struct tm_memopt_bitmaps *b
    3994          621 :     = XOBNEW (&tm_memopt_obstack.obstack, struct tm_memopt_bitmaps);
    3995          621 :   b->store_avail_in = BITMAP_ALLOC (&tm_memopt_obstack);
    3996          621 :   b->store_avail_out = BITMAP_ALLOC (&tm_memopt_obstack);
    3997          621 :   b->store_antic_in = BITMAP_ALLOC (&tm_memopt_obstack);
    3998          621 :   b->store_antic_out = BITMAP_ALLOC (&tm_memopt_obstack);
    3999          621 :   b->store_avail_out = BITMAP_ALLOC (&tm_memopt_obstack);
    4000          621 :   b->read_avail_in = BITMAP_ALLOC (&tm_memopt_obstack);
    4001          621 :   b->read_avail_out = BITMAP_ALLOC (&tm_memopt_obstack);
    4002          621 :   b->read_local = BITMAP_ALLOC (&tm_memopt_obstack);
    4003          621 :   b->store_local = BITMAP_ALLOC (&tm_memopt_obstack);
    4004          621 :   return b;
    4005              : }
    4006              : 
    4007              : /* Free sets computed for each BB.  */
    4008              : 
    4009              : static void
    4010          221 : tm_memopt_free_sets (vec<basic_block> blocks)
    4011              : {
    4012          221 :   size_t i;
    4013          221 :   basic_block bb;
    4014              : 
    4015          842 :   for (i = 0; blocks.iterate (i, &bb); ++i)
    4016          621 :     bb->aux = NULL;
    4017          221 : }
    4018              : 
    4019              : /* Clear the visited bit for every basic block in BLOCKS.  */
    4020              : 
    4021              : static void
    4022          442 : tm_memopt_clear_visited (vec<basic_block> blocks)
    4023              : {
    4024          442 :   size_t i;
    4025          442 :   basic_block bb;
    4026              : 
    4027         1684 :   for (i = 0; blocks.iterate (i, &bb); ++i)
    4028         1242 :     BB_VISITED_P (bb) = false;
    4029          442 : }
    4030              : 
    4031              : /* Replace TM load/stores with hints for the runtime.  We handle
    4032              :    things like read-after-write, write-after-read, read-after-read,
    4033              :    read-for-write, etc.  */
    4034              : 
    4035              : static unsigned int
    4036          163 : execute_tm_memopt (void)
    4037              : {
    4038          163 :   struct tm_region *region;
    4039          163 :   vec<basic_block> bbs;
    4040              : 
    4041          163 :   tm_memopt_value_id = 0;
    4042          163 :   tm_memopt_value_numbers = new hash_table<tm_memop_hasher> (10);
    4043              : 
    4044          384 :   for (region = all_tm_regions; region; region = region->next)
    4045              :     {
    4046              :       /* All the TM stores/loads in the current region.  */
    4047          221 :       size_t i;
    4048          221 :       basic_block bb;
    4049              : 
    4050          221 :       bitmap_obstack_initialize (&tm_memopt_obstack);
    4051              : 
    4052              :       /* Save all BBs for the current region.  */
    4053          221 :       bbs = get_tm_region_blocks (region->entry_block,
    4054              :                                   region->exit_blocks,
    4055              :                                   region->irr_blocks,
    4056              :                                   NULL,
    4057              :                                   false);
    4058              : 
    4059              :       /* Collect all the memory operations.  */
    4060         1063 :       for (i = 0; bbs.iterate (i, &bb); ++i)
    4061              :         {
    4062          621 :           bb->aux = tm_memopt_init_sets ();
    4063          621 :           tm_memopt_accumulate_memops (bb);
    4064              :         }
    4065              : 
    4066              :       /* Solve data flow equations and transform each block accordingly.  */
    4067          221 :       tm_memopt_clear_visited (bbs);
    4068          221 :       tm_memopt_compute_available (region, bbs);
    4069          221 :       tm_memopt_clear_visited (bbs);
    4070          221 :       tm_memopt_compute_antic (region, bbs);
    4071          221 :       tm_memopt_transform_blocks (bbs);
    4072              : 
    4073          221 :       tm_memopt_free_sets (bbs);
    4074          221 :       bbs.release ();
    4075          221 :       bitmap_obstack_release (&tm_memopt_obstack);
    4076          384 :       tm_memopt_value_numbers->empty ();
    4077              :     }
    4078              : 
    4079          163 :   delete tm_memopt_value_numbers;
    4080          163 :   tm_memopt_value_numbers = NULL;
    4081          163 :   return 0;
    4082              : }
    4083              : 
    4084              : namespace {
    4085              : 
    4086              : const pass_data pass_data_tm_memopt =
    4087              : {
    4088              :   GIMPLE_PASS, /* type */
    4089              :   "tmmemopt", /* name */
    4090              :   OPTGROUP_NONE, /* optinfo_flags */
    4091              :   TV_TRANS_MEM, /* tv_id */
    4092              :   ( PROP_ssa | PROP_cfg ), /* properties_required */
    4093              :   0, /* properties_provided */
    4094              :   0, /* properties_destroyed */
    4095              :   0, /* todo_flags_start */
    4096              :   0, /* todo_flags_finish */
    4097              : };
    4098              : 
    4099              : class pass_tm_memopt : public gimple_opt_pass
    4100              : {
    4101              : public:
    4102       285722 :   pass_tm_memopt (gcc::context *ctxt)
    4103       571444 :     : gimple_opt_pass (pass_data_tm_memopt, ctxt)
    4104              :   {}
    4105              : 
    4106              :   /* opt_pass methods: */
    4107          479 :   bool gate (function *) final override { return flag_tm && optimize > 0; }
    4108          163 :   unsigned int execute (function *) final override
    4109              :   {
    4110          163 :     return execute_tm_memopt ();
    4111              :   }
    4112              : 
    4113              : }; // class pass_tm_memopt
    4114              : 
    4115              : } // anon namespace
    4116              : 
    4117              : gimple_opt_pass *
    4118       285722 : make_pass_tm_memopt (gcc::context *ctxt)
    4119              : {
    4120       285722 :   return new pass_tm_memopt (ctxt);
    4121              : }
    4122              : 
    4123              : 
    4124              : /* Interprocedual analysis for the creation of transactional clones.
    4125              :    The aim of this pass is to find which functions are referenced in
    4126              :    a non-irrevocable transaction context, and for those over which
    4127              :    we have control (or user directive), create a version of the
    4128              :    function which uses only the transactional interface to reference
    4129              :    protected memories.  This analysis proceeds in several steps:
    4130              : 
    4131              :      (1) Collect the set of all possible transactional clones:
    4132              : 
    4133              :         (a) For all local public functions marked tm_callable, push
    4134              :             it onto the tm_callee queue.
    4135              : 
    4136              :         (b) For all local functions, scan for calls in transaction blocks.
    4137              :             Push the caller and callee onto the tm_caller and tm_callee
    4138              :             queues.  Count the number of callers for each callee.
    4139              : 
    4140              :         (c) For each local function on the callee list, assume we will
    4141              :             create a transactional clone.  Push *all* calls onto the
    4142              :             callee queues; count the number of clone callers separately
    4143              :             to the number of original callers.
    4144              : 
    4145              :      (2) Propagate irrevocable status up the dominator tree:
    4146              : 
    4147              :         (a) Any external function on the callee list that is not marked
    4148              :             tm_callable is irrevocable.  Push all callers of such onto
    4149              :             a worklist.
    4150              : 
    4151              :         (b) For each function on the worklist, mark each block that
    4152              :             contains an irrevocable call.  Use the AND operator to
    4153              :             propagate that mark up the dominator tree.
    4154              : 
    4155              :         (c) If we reach the entry block for a possible transactional
    4156              :             clone, then the transactional clone is irrevocable, and
    4157              :             we should not create the clone after all.  Push all
    4158              :             callers onto the worklist.
    4159              : 
    4160              :         (d) Place tm_irrevocable calls at the beginning of the relevant
    4161              :             blocks.  Special case here is the entry block for the entire
    4162              :             transaction region; there we mark it GTMA_DOES_GO_IRREVOCABLE for
    4163              :             the library to begin the region in serial mode.  Decrement
    4164              :             the call count for all callees in the irrevocable region.
    4165              : 
    4166              :      (3) Create the transactional clones:
    4167              : 
    4168              :         Any tm_callee that still has a non-zero call count is cloned.
    4169              : */
    4170              : 
    4171              : /* This structure is stored in the AUX field of each cgraph_node.  */
    4172              : struct tm_ipa_cg_data
    4173              : {
    4174              :   /* The clone of the function that got created.  */
    4175              :   struct cgraph_node *clone;
    4176              : 
    4177              :   /* The tm regions in the normal function.  */
    4178              :   struct tm_region *all_tm_regions;
    4179              : 
    4180              :   /* The blocks of the normal/clone functions that contain irrevocable
    4181              :      calls, or blocks that are post-dominated by irrevocable calls.  */
    4182              :   bitmap irrevocable_blocks_normal;
    4183              :   bitmap irrevocable_blocks_clone;
    4184              : 
    4185              :   /* The blocks of the normal function that are involved in transactions.  */
    4186              :   bitmap transaction_blocks_normal;
    4187              : 
    4188              :   /* The number of callers to the transactional clone of this function
    4189              :      from normal and transactional clones respectively.  */
    4190              :   unsigned tm_callers_normal;
    4191              :   unsigned tm_callers_clone;
    4192              : 
    4193              :   /* True if all calls to this function's transactional clone
    4194              :      are irrevocable.  Also automatically true if the function
    4195              :      has no transactional clone.  */
    4196              :   bool is_irrevocable;
    4197              : 
    4198              :   /* Flags indicating the presence of this function in various queues.  */
    4199              :   bool in_callee_queue;
    4200              :   bool in_worklist;
    4201              : 
    4202              :   /* Flags indicating the kind of scan desired while in the worklist.  */
    4203              :   bool want_irr_scan_normal;
    4204              : };
    4205              : 
    4206              : typedef vec<cgraph_node *> cgraph_node_queue;
    4207              : 
    4208              : /* Return the ipa data associated with NODE, allocating zeroed memory
    4209              :    if necessary.  TRAVERSE_ALIASES is true if we must traverse aliases
    4210              :    and set *NODE accordingly.  */
    4211              : 
    4212              : static struct tm_ipa_cg_data *
    4213         9068 : get_cg_data (struct cgraph_node **node, bool traverse_aliases)
    4214              : {
    4215         9068 :   struct tm_ipa_cg_data *d;
    4216              : 
    4217         9068 :   if (traverse_aliases && (*node)->alias)
    4218          185 :     *node = (*node)->get_alias_target ();
    4219              : 
    4220         9068 :   d = (struct tm_ipa_cg_data *) (*node)->aux;
    4221              : 
    4222         9068 :   if (d == NULL)
    4223              :     {
    4224         2926 :       d = (struct tm_ipa_cg_data *)
    4225         1463 :         obstack_alloc (&tm_obstack.obstack, sizeof (*d));
    4226         1463 :       (*node)->aux = (void *) d;
    4227         1463 :       memset (d, 0, sizeof (*d));
    4228              :     }
    4229              : 
    4230         9068 :   return d;
    4231              : }
    4232              : 
    4233              : /* Add NODE to the end of QUEUE, unless IN_QUEUE_P indicates that
    4234              :    it is already present.  */
    4235              : 
    4236              : static void
    4237         1878 : maybe_push_queue (struct cgraph_node *node,
    4238              :                   cgraph_node_queue *queue_p, bool *in_queue_p)
    4239              : {
    4240            0 :   if (!*in_queue_p)
    4241              :     {
    4242         1480 :       *in_queue_p = true;
    4243         1351 :       queue_p->safe_push (node);
    4244              :     }
    4245            0 : }
    4246              : 
    4247              : /* A subroutine of ipa_tm_scan_calls_transaction and ipa_tm_scan_calls_clone.
    4248              :    Queue all callees within block BB.  */
    4249              : 
    4250              : static void
    4251         1476 : ipa_tm_scan_calls_block (cgraph_node_queue *callees_p,
    4252              :                          basic_block bb, bool for_clone)
    4253              : {
    4254         1476 :   gimple_stmt_iterator gsi;
    4255              : 
    4256         7276 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    4257              :     {
    4258         4324 :       gimple *stmt = gsi_stmt (gsi);
    4259         5613 :       if (is_gimple_call (stmt) && !is_tm_pure_call (stmt))
    4260              :         {
    4261         1134 :           tree fndecl = gimple_call_fndecl (stmt);
    4262         1134 :           if (fndecl)
    4263              :             {
    4264         1117 :               struct tm_ipa_cg_data *d;
    4265         1117 :               unsigned *pcallers;
    4266         1117 :               struct cgraph_node *node;
    4267              : 
    4268         1117 :               if (is_tm_ending_fndecl (fndecl))
    4269          624 :                 continue;
    4270          627 :               if (find_tm_replacement_function (fndecl))
    4271          134 :                 continue;
    4272              : 
    4273          493 :               node = cgraph_node::get (fndecl);
    4274          493 :               gcc_assert (node != NULL);
    4275          493 :               d = get_cg_data (&node, true);
    4276              : 
    4277          493 :               pcallers = (for_clone ? &d->tm_callers_clone
    4278              :                           : &d->tm_callers_normal);
    4279          493 :               *pcallers += 1;
    4280              : 
    4281          839 :               maybe_push_queue (node, callees_p, &d->in_callee_queue);
    4282              :             }
    4283              :         }
    4284              :     }
    4285         1476 : }
    4286              : 
    4287              : /* Scan all calls in NODE that are within a transaction region,
    4288              :    and push the resulting nodes into the callee queue.  */
    4289              : 
    4290              : static void
    4291          284 : ipa_tm_scan_calls_transaction (struct tm_ipa_cg_data *d,
    4292              :                                cgraph_node_queue *callees_p)
    4293              : {
    4294          284 :   d->transaction_blocks_normal = BITMAP_ALLOC (&tm_obstack);
    4295          284 :   d->all_tm_regions = all_tm_regions;
    4296              : 
    4297          634 :   for (tm_region *r = all_tm_regions; r; r = r->next)
    4298              :     {
    4299          350 :       vec<basic_block> bbs;
    4300          350 :       basic_block bb;
    4301          350 :       unsigned i;
    4302              : 
    4303          350 :       bbs = get_tm_region_blocks (r->entry_block, r->exit_blocks, NULL,
    4304              :                                   d->transaction_blocks_normal, false, false);
    4305              : 
    4306         1464 :       FOR_EACH_VEC_ELT (bbs, i, bb)
    4307          764 :         ipa_tm_scan_calls_block (callees_p, bb, false);
    4308              : 
    4309          350 :       bbs.release ();
    4310              :     }
    4311          284 : }
    4312              : 
    4313              : /* Scan all calls in NODE as if this is the transactional clone,
    4314              :    and push the destinations into the callee queue.  */
    4315              : 
    4316              : static void
    4317          337 : ipa_tm_scan_calls_clone (struct cgraph_node *node,
    4318              :                          cgraph_node_queue *callees_p)
    4319              : {
    4320          337 :   struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
    4321          337 :   basic_block bb;
    4322              : 
    4323         1049 :   FOR_EACH_BB_FN (bb, fn)
    4324          712 :     ipa_tm_scan_calls_block (callees_p, bb, true);
    4325          337 : }
    4326              : 
    4327              : /* The function NODE has been detected to be irrevocable.  Push all
    4328              :    of its callers onto WORKLIST for the purpose of re-scanning them.  */
    4329              : 
    4330              : static void
    4331          124 : ipa_tm_note_irrevocable (struct cgraph_node *node,
    4332              :                          cgraph_node_queue *worklist_p)
    4333              : {
    4334          124 :   struct tm_ipa_cg_data *d = get_cg_data (&node, true);
    4335          124 :   struct cgraph_edge *e;
    4336              : 
    4337          124 :   d->is_irrevocable = true;
    4338              : 
    4339          317 :   for (e = node->callers; e ; e = e->next_caller)
    4340              :     {
    4341          193 :       basic_block bb;
    4342          193 :       struct cgraph_node *caller;
    4343              : 
    4344              :       /* Don't examine recursive calls.  */
    4345          193 :       if (e->caller == node)
    4346           21 :         continue;
    4347              :       /* Even if we think we can go irrevocable, believe the user
    4348              :          above all.  */
    4349          193 :       if (is_tm_safe_or_pure (e->caller->decl))
    4350           21 :         continue;
    4351              : 
    4352          172 :       caller = e->caller;
    4353          172 :       d = get_cg_data (&caller, true);
    4354              : 
    4355              :       /* Check if the callee is in a transactional region.  If so,
    4356              :          schedule the function for normal re-scan as well.  */
    4357          172 :       bb = gimple_bb (e->call_stmt);
    4358          172 :       gcc_assert (bb != NULL);
    4359          172 :       if (d->transaction_blocks_normal
    4360          172 :           && bitmap_bit_p (d->transaction_blocks_normal, bb->index))
    4361           63 :         d->want_irr_scan_normal = true;
    4362              : 
    4363          195 :       maybe_push_queue (caller, worklist_p, &d->in_worklist);
    4364              :     }
    4365          124 : }
    4366              : 
    4367              : /* A subroutine of ipa_tm_scan_irr_blocks; return true iff any statement
    4368              :    within the block is irrevocable.  */
    4369              : 
    4370              : static bool
    4371         1750 : ipa_tm_scan_irr_block (basic_block bb)
    4372              : {
    4373         1750 :   gimple_stmt_iterator gsi;
    4374         1750 :   tree fn;
    4375              : 
    4376         7491 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    4377              :     {
    4378         4119 :       gimple *stmt = gsi_stmt (gsi);
    4379         4119 :       switch (gimple_code (stmt))
    4380              :         {
    4381         1610 :         case GIMPLE_ASSIGN:
    4382         1610 :           if (gimple_assign_single_p (stmt))
    4383              :             {
    4384         1262 :               tree lhs = gimple_assign_lhs (stmt);
    4385         1262 :               tree rhs = gimple_assign_rhs1 (stmt);
    4386         1262 :               if (volatile_lvalue_p (lhs) || volatile_lvalue_p (rhs))
    4387              :                 return true;
    4388              :             }
    4389              :           break;
    4390              : 
    4391         1181 :         case GIMPLE_CALL:
    4392         1181 :           {
    4393         1181 :             tree lhs = gimple_call_lhs (stmt);
    4394         1181 :             if (lhs && volatile_lvalue_p (lhs))
    4395              :               return true;
    4396              : 
    4397         1181 :             if (is_tm_pure_call (stmt))
    4398              :               break;
    4399              : 
    4400         1048 :             fn = gimple_call_fn (stmt);
    4401              : 
    4402              :             /* Functions with the attribute are by definition irrevocable.  */
    4403         1048 :             if (is_tm_irrevocable (fn))
    4404              :               return true;
    4405              : 
    4406              :             /* For direct function calls, go ahead and check for replacement
    4407              :                functions, or transitive irrevocable functions.  For indirect
    4408              :                functions, we'll ask the runtime.  */
    4409         1039 :             if (TREE_CODE (fn) == ADDR_EXPR)
    4410              :               {
    4411         1022 :                 struct tm_ipa_cg_data *d;
    4412         1022 :                 struct cgraph_node *node;
    4413              : 
    4414         1022 :                 fn = TREE_OPERAND (fn, 0);
    4415         1022 :                 if (is_tm_ending_fndecl (fn))
    4416              :                   break;
    4417          600 :                 if (find_tm_replacement_function (fn))
    4418              :                   break;
    4419              : 
    4420          466 :                 node = cgraph_node::get (fn);
    4421          466 :                 d = get_cg_data (&node, true);
    4422              : 
    4423              :                 /* Return true if irrevocable, but above all, believe
    4424              :                    the user.  */
    4425          466 :                 if (d->is_irrevocable
    4426          466 :                     && !is_tm_safe_or_pure (fn))
    4427           94 :                   return true;
    4428              :               }
    4429              :             break;
    4430              :           }
    4431              : 
    4432           18 :         case GIMPLE_ASM:
    4433              :           /* ??? The Approved Method of indicating that an inline
    4434              :              assembly statement is not relevant to the transaction
    4435              :              is to wrap it in a __tm_waiver block.  This is not
    4436              :              yet implemented, so we can't check for it.  */
    4437           18 :           if (is_tm_safe (current_function_decl))
    4438            1 :             error_at (gimple_location (stmt),
    4439              :                       "%<asm%> not allowed in %<transaction_safe%> function");
    4440              :           return true;
    4441              : 
    4442              :         default:
    4443              :           break;
    4444              :         }
    4445              :     }
    4446              : 
    4447              :   return false;
    4448              : }
    4449              : 
    4450              : /* For each of the blocks seeded witin PQUEUE, walk the CFG looking
    4451              :    for new irrevocable blocks, marking them in NEW_IRR.  Don't bother
    4452              :    scanning past OLD_IRR or EXIT_BLOCKS.  */
    4453              : 
    4454              : static bool
    4455          708 : ipa_tm_scan_irr_blocks (vec<basic_block> *pqueue, bitmap new_irr,
    4456              :                         bitmap old_irr, bitmap exit_blocks)
    4457              : {
    4458          708 :   bool any_new_irr = false;
    4459          708 :   edge e;
    4460          708 :   edge_iterator ei;
    4461          708 :   bitmap visited_blocks = BITMAP_ALLOC (NULL);
    4462              : 
    4463         1750 :   do
    4464              :     {
    4465         1750 :       basic_block bb = pqueue->pop ();
    4466              : 
    4467              :       /* Don't re-scan blocks we know already are irrevocable.  */
    4468         1750 :       if (old_irr && bitmap_bit_p (old_irr, bb->index))
    4469            0 :         continue;
    4470              : 
    4471         1750 :       if (ipa_tm_scan_irr_block (bb))
    4472              :         {
    4473          128 :           bitmap_set_bit (new_irr, bb->index);
    4474          128 :           any_new_irr = true;
    4475              :         }
    4476         1622 :       else if (exit_blocks == NULL || !bitmap_bit_p (exit_blocks, bb->index))
    4477              :         {
    4478         2517 :           FOR_EACH_EDGE (e, ei, bb->succs)
    4479         1219 :             if (!bitmap_bit_p (visited_blocks, e->dest->index))
    4480              :               {
    4481         1042 :                 bitmap_set_bit (visited_blocks, e->dest->index);
    4482         1042 :                 pqueue->safe_push (e->dest);
    4483              :               }
    4484              :         }
    4485              :     }
    4486         3500 :   while (!pqueue->is_empty ());
    4487              : 
    4488          708 :   BITMAP_FREE (visited_blocks);
    4489              : 
    4490          708 :   return any_new_irr;
    4491              : }
    4492              : 
    4493              : /* Propagate the irrevocable property both up and down the dominator tree.
    4494              :    BB is the current block being scanned; EXIT_BLOCKS are the edges of the
    4495              :    TM regions; OLD_IRR are the results of a previous scan of the dominator
    4496              :    tree which has been fully propagated; NEW_IRR is the set of new blocks
    4497              :    which are gaining the irrevocable property during the current scan.  */
    4498              : 
    4499              : static void
    4500          124 : ipa_tm_propagate_irr (basic_block entry_block, bitmap new_irr,
    4501              :                       bitmap old_irr, bitmap exit_blocks)
    4502              : {
    4503          124 :   vec<basic_block> bbs;
    4504          124 :   bitmap all_region_blocks;
    4505              : 
    4506              :   /* If this block is in the old set, no need to rescan.  */
    4507          124 :   if (old_irr && bitmap_bit_p (old_irr, entry_block->index))
    4508            0 :     return;
    4509              : 
    4510          124 :   all_region_blocks = BITMAP_ALLOC (&tm_obstack);
    4511          124 :   bbs = get_tm_region_blocks (entry_block, exit_blocks, NULL,
    4512              :                               all_region_blocks, false);
    4513          376 :   do
    4514              :     {
    4515          376 :       basic_block bb = bbs.pop ();
    4516          376 :       bool this_irr = bitmap_bit_p (new_irr, bb->index);
    4517          376 :       bool all_son_irr = false;
    4518          376 :       edge_iterator ei;
    4519          376 :       edge e;
    4520              : 
    4521              :       /* Propagate up.  If my children are, I am too, but we must have
    4522              :          at least one child that is.  */
    4523          376 :       if (!this_irr)
    4524              :         {
    4525          267 :           FOR_EACH_EDGE (e, ei, bb->succs)
    4526              :             {
    4527          162 :               if (!bitmap_bit_p (new_irr, e->dest->index))
    4528              :                 {
    4529              :                   all_son_irr = false;
    4530              :                   break;
    4531              :                 }
    4532              :               else
    4533           19 :                 all_son_irr = true;
    4534              :             }
    4535          248 :           if (all_son_irr)
    4536              :             {
    4537              :               /* Add block to new_irr if it hasn't already been processed. */
    4538            7 :               if (!old_irr || !bitmap_bit_p (old_irr, bb->index))
    4539              :                 {
    4540            7 :                   bitmap_set_bit (new_irr, bb->index);
    4541            7 :                   this_irr = true;
    4542              :                 }
    4543              :             }
    4544              :         }
    4545              : 
    4546              :       /* Propagate down to everyone we immediately dominate.  */
    4547            7 :       if (this_irr)
    4548              :         {
    4549          135 :           basic_block son;
    4550          135 :           for (son = first_dom_son (CDI_DOMINATORS, bb);
    4551          225 :                son;
    4552           90 :                son = next_dom_son (CDI_DOMINATORS, son))
    4553              :             {
    4554              :               /* Make sure block is actually in a TM region, and it
    4555              :                  isn't already in old_irr.  */
    4556            2 :               if ((!old_irr || !bitmap_bit_p (old_irr, son->index))
    4557           91 :                   && bitmap_bit_p (all_region_blocks, son->index))
    4558           89 :                 bitmap_set_bit (new_irr, son->index);
    4559              :             }
    4560              :         }
    4561              :     }
    4562          500 :   while (!bbs.is_empty ());
    4563              : 
    4564          124 :   BITMAP_FREE (all_region_blocks);
    4565          124 :   bbs.release ();
    4566              : }
    4567              : 
    4568              : static void
    4569          216 : ipa_tm_decrement_clone_counts (basic_block bb, bool for_clone)
    4570              : {
    4571          216 :   gimple_stmt_iterator gsi;
    4572              : 
    4573         1120 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    4574              :     {
    4575          688 :       gimple *stmt = gsi_stmt (gsi);
    4576          987 :       if (is_gimple_call (stmt) && !is_tm_pure_call (stmt))
    4577              :         {
    4578          264 :           tree fndecl = gimple_call_fndecl (stmt);
    4579          264 :           if (fndecl)
    4580              :             {
    4581          264 :               struct tm_ipa_cg_data *d;
    4582          264 :               unsigned *pcallers;
    4583          264 :               struct cgraph_node *tnode;
    4584              : 
    4585          264 :               if (is_tm_ending_fndecl (fndecl))
    4586           65 :                 continue;
    4587          199 :               if (find_tm_replacement_function (fndecl))
    4588            0 :                 continue;
    4589              : 
    4590          199 :               tnode = cgraph_node::get (fndecl);
    4591          199 :               d = get_cg_data (&tnode, true);
    4592              : 
    4593          199 :               pcallers = (for_clone ? &d->tm_callers_clone
    4594              :                           : &d->tm_callers_normal);
    4595              : 
    4596          199 :               gcc_assert (*pcallers > 0);
    4597          199 :               *pcallers -= 1;
    4598              :             }
    4599              :         }
    4600              :     }
    4601          216 : }
    4602              : 
    4603              : /* (Re-)Scan the transaction blocks in NODE for calls to irrevocable functions,
    4604              :    as well as other irrevocable actions such as inline assembly.  Mark all
    4605              :    such blocks as irrevocable and decrement the number of calls to
    4606              :    transactional clones.  Return true if, for the transactional clone, the
    4607              :    entire function is irrevocable.  */
    4608              : 
    4609              : static bool
    4610          812 : ipa_tm_scan_irr_function (struct cgraph_node *node, bool for_clone)
    4611              : {
    4612          812 :   struct tm_ipa_cg_data *d;
    4613          812 :   bitmap new_irr, old_irr;
    4614          812 :   bool ret = false;
    4615              : 
    4616              :   /* Builtin operators (operator new, and such).  */
    4617          812 :   if (DECL_STRUCT_FUNCTION (node->decl) == NULL
    4618          812 :       || DECL_STRUCT_FUNCTION (node->decl)->cfg == NULL)
    4619              :     return false;
    4620              : 
    4621          642 :   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    4622          642 :   calculate_dominance_info (CDI_DOMINATORS);
    4623              : 
    4624          642 :   d = get_cg_data (&node, true);
    4625          642 :   auto_vec<basic_block, 10> queue;
    4626          642 :   new_irr = BITMAP_ALLOC (&tm_obstack);
    4627              : 
    4628              :   /* Scan each tm region, propagating irrevocable status through the tree.  */
    4629          642 :   if (for_clone)
    4630              :     {
    4631          351 :       old_irr = d->irrevocable_blocks_clone;
    4632          351 :       queue.quick_push (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
    4633          351 :       if (ipa_tm_scan_irr_blocks (&queue, new_irr, old_irr, NULL))
    4634              :         {
    4635           59 :           ipa_tm_propagate_irr (single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
    4636              :                                 new_irr,
    4637              :                                 old_irr, NULL);
    4638          118 :           ret = bitmap_bit_p (new_irr,
    4639           59 :                               single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun))->index);
    4640              :         }
    4641              :     }
    4642              :   else
    4643              :     {
    4644          291 :       struct tm_region *region;
    4645              : 
    4646          291 :       old_irr = d->irrevocable_blocks_normal;
    4647          648 :       for (region = d->all_tm_regions; region; region = region->next)
    4648              :         {
    4649          357 :           queue.quick_push (region->entry_block);
    4650          357 :           if (ipa_tm_scan_irr_blocks (&queue, new_irr, old_irr,
    4651              :                                       region->exit_blocks))
    4652           65 :             ipa_tm_propagate_irr (region->entry_block, new_irr, old_irr,
    4653              :                                   region->exit_blocks);
    4654              :         }
    4655              :     }
    4656              : 
    4657              :   /* If we found any new irrevocable blocks, reduce the call count for
    4658              :      transactional clones within the irrevocable blocks.  Save the new
    4659              :      set of irrevocable blocks for next time.  */
    4660          642 :   if (!bitmap_empty_p (new_irr))
    4661              :     {
    4662          112 :       bitmap_iterator bmi;
    4663          112 :       unsigned i;
    4664              : 
    4665          328 :       EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi)
    4666          216 :         ipa_tm_decrement_clone_counts (BASIC_BLOCK_FOR_FN (cfun, i),
    4667              :                                        for_clone);
    4668              : 
    4669          112 :       if (old_irr)
    4670              :         {
    4671            1 :           bitmap_ior_into (old_irr, new_irr);
    4672            1 :           BITMAP_FREE (new_irr);
    4673              :         }
    4674          111 :       else if (for_clone)
    4675           58 :         d->irrevocable_blocks_clone = new_irr;
    4676              :       else
    4677           53 :         d->irrevocable_blocks_normal = new_irr;
    4678              : 
    4679          112 :       if (dump_file && new_irr)
    4680              :         {
    4681            8 :           const char *dname;
    4682            8 :           bitmap_iterator bmi;
    4683            8 :           unsigned i;
    4684              : 
    4685            8 :           dname = lang_hooks.decl_printable_name (current_function_decl, 2);
    4686           25 :           EXECUTE_IF_SET_IN_BITMAP (new_irr, 0, i, bmi)
    4687           17 :             fprintf (dump_file, "%s: bb %d goes irrevocable\n", dname, i);
    4688              :         }
    4689              :     }
    4690              :   else
    4691          530 :     BITMAP_FREE (new_irr);
    4692              : 
    4693          642 :   pop_cfun ();
    4694              : 
    4695          642 :   return ret;
    4696          642 : }
    4697              : 
    4698              : /* Return true if, for the transactional clone of NODE, any call
    4699              :    may enter irrevocable mode.  */
    4700              : 
    4701              : static bool
    4702          508 : ipa_tm_mayenterirr_function (struct cgraph_node *node)
    4703              : {
    4704          508 :   struct tm_ipa_cg_data *d;
    4705          508 :   tree decl;
    4706          508 :   unsigned flags;
    4707              : 
    4708          508 :   d = get_cg_data (&node, true);
    4709          508 :   decl = node->decl;
    4710          508 :   flags = flags_from_decl_or_type (decl);
    4711              : 
    4712              :   /* Handle some TM builtins.  Ordinarily these aren't actually generated
    4713              :      at this point, but handling these functions when written in by the
    4714              :      user makes it easier to build unit tests.  */
    4715          508 :   if (flags & ECF_TM_BUILTIN)
    4716              :     return false;
    4717              : 
    4718              :   /* Filter out all functions that are marked.  */
    4719          507 :   if (flags & ECF_TM_PURE)
    4720              :     return false;
    4721          500 :   if (is_tm_safe (decl))
    4722              :     return false;
    4723          276 :   if (is_tm_irrevocable (decl))
    4724              :     return true;
    4725          270 :   if (is_tm_callable (decl))
    4726              :     return true;
    4727          229 :   if (find_tm_replacement_function (decl))
    4728              :     return true;
    4729              : 
    4730              :   /* If we aren't seeing the final version of the function we don't
    4731              :      know what it will contain at runtime.  */
    4732          229 :   if (node->get_availability () < AVAIL_AVAILABLE)
    4733              :     return true;
    4734              : 
    4735              :   /* If the function must go irrevocable, then of course true.  */
    4736          175 :   if (d->is_irrevocable)
    4737              :     return true;
    4738              : 
    4739              :   /* If there are any blocks marked irrevocable, then the function
    4740              :      as a whole may enter irrevocable.  */
    4741          150 :   if (d->irrevocable_blocks_clone)
    4742              :     return true;
    4743              : 
    4744              :   /* We may have previously marked this function as tm_may_enter_irr;
    4745              :      see pass_diagnose_tm_blocks.  */
    4746          147 :   if (node->tm_may_enter_irr)
    4747              :     return true;
    4748              : 
    4749              :   /* Recurse on the main body for aliases.  In general, this will
    4750              :      result in one of the bits above being set so that we will not
    4751              :      have to recurse next time.  */
    4752          147 :   if (node->alias)
    4753            0 :     return ipa_tm_mayenterirr_function
    4754            0 :                  (cgraph_node::get (thunk_info::get (node)->alias));
    4755              : 
    4756              :   /* What remains is unmarked local functions without items that force
    4757              :      the function to go irrevocable.  */
    4758              :   return false;
    4759              : }
    4760              : 
    4761              : /* Diagnose calls from transaction_safe functions to unmarked
    4762              :    functions that are determined to not be safe.  */
    4763              : 
    4764              : static void
    4765          130 : ipa_tm_diagnose_tm_safe (struct cgraph_node *node)
    4766              : {
    4767          130 :   struct cgraph_edge *e;
    4768              : 
    4769          311 :   for (e = node->callees; e ; e = e->next_callee)
    4770          181 :     if (!is_tm_callable (e->callee->decl)
    4771          181 :         && e->callee->tm_may_enter_irr)
    4772           21 :       error_at (gimple_location (e->call_stmt),
    4773              :                 "unsafe function call %qD within "
    4774              :                 "%<transaction_safe%> function", e->callee->decl);
    4775          130 : }
    4776              : 
    4777              : /* Diagnose call from atomic transactions to unmarked functions
    4778              :    that are determined to not be safe.  */
    4779              : 
    4780              : static void
    4781          275 : ipa_tm_diagnose_transaction (struct cgraph_node *node,
    4782              :                            struct tm_region *all_tm_regions)
    4783              : {
    4784          275 :   struct tm_region *r;
    4785              : 
    4786          610 :   for (r = all_tm_regions; r ; r = r->next)
    4787          335 :     if (gimple_transaction_subcode (r->get_transaction_stmt ())
    4788              :         & GTMA_IS_RELAXED)
    4789              :       {
    4790              :         /* Atomic transactions can be nested inside relaxed.  */
    4791           66 :         if (r->inner)
    4792            0 :           ipa_tm_diagnose_transaction (node, r->inner);
    4793              :       }
    4794              :     else
    4795              :       {
    4796          269 :         vec<basic_block> bbs;
    4797          269 :         gimple_stmt_iterator gsi;
    4798          269 :         basic_block bb;
    4799          269 :         size_t i;
    4800              : 
    4801          269 :         bbs = get_tm_region_blocks (r->entry_block, r->exit_blocks,
    4802              :                                     r->irr_blocks, NULL, false);
    4803              : 
    4804          820 :         for (i = 0; bbs.iterate (i, &bb); ++i)
    4805         2555 :           for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    4806              :             {
    4807         1745 :               gimple *stmt = gsi_stmt (gsi);
    4808         1745 :               tree fndecl;
    4809              : 
    4810         1745 :               if (gimple_code (stmt) == GIMPLE_ASM)
    4811              :                 {
    4812            4 :                   error_at (gimple_location (stmt),
    4813              :                             "%<asm%> not allowed in atomic transaction");
    4814            4 :                   continue;
    4815              :                 }
    4816              : 
    4817         1741 :               if (!is_gimple_call (stmt))
    4818         1116 :                 continue;
    4819          625 :               fndecl = gimple_call_fndecl (stmt);
    4820              : 
    4821              :               /* Indirect function calls have been diagnosed already.  */
    4822          625 :               if (!fndecl)
    4823            7 :                 continue;
    4824              : 
    4825              :               /* Stop at the end of the transaction.  */
    4826          618 :               if (is_tm_ending_fndecl (fndecl))
    4827              :                 {
    4828          332 :                   if (bitmap_bit_p (r->exit_blocks, bb->index))
    4829              :                     break;
    4830           40 :                   continue;
    4831              :                 }
    4832              : 
    4833              :               /* Marked functions have been diagnosed already.  */
    4834          286 :               if (is_tm_pure_call (stmt))
    4835           76 :                 continue;
    4836          210 :               if (is_tm_callable (fndecl))
    4837           69 :                 continue;
    4838              : 
    4839          141 :               if (cgraph_node::local_info_node (fndecl)->tm_may_enter_irr)
    4840           13 :                 error_at (gimple_location (stmt),
    4841              :                           "unsafe function call %qD within "
    4842              :                           "atomic transaction", fndecl);
    4843              :             }
    4844              : 
    4845          269 :         bbs.release ();
    4846              :       }
    4847          275 : }
    4848              : 
    4849              : /* Return a transactional mangled name for the DECL_ASSEMBLER_NAME in
    4850              :    OLD_DECL.  The returned value is a freshly malloced pointer that
    4851              :    should be freed by the caller.  */
    4852              : 
    4853              : static tree
    4854          440 : tm_mangle (tree old_asm_id)
    4855              : {
    4856          440 :   const char *old_asm_name;
    4857          440 :   char *tm_name;
    4858          440 :   void *alloc = NULL;
    4859          440 :   struct demangle_component *dc;
    4860          440 :   tree new_asm_id;
    4861              : 
    4862              :   /* Determine if the symbol is already a valid C++ mangled name.  Do this
    4863              :      even for C, which might be interfacing with C++ code via appropriately
    4864              :      ugly identifiers.  */
    4865              :   /* ??? We could probably do just as well checking for "_Z" and be done.  */
    4866          440 :   old_asm_name = IDENTIFIER_POINTER (old_asm_id);
    4867          440 :   dc = cplus_demangle_v3_components (old_asm_name, DMGL_NO_OPTS, &alloc);
    4868              : 
    4869          440 :   if (dc == NULL)
    4870              :     {
    4871           66 :       char length[12];
    4872              : 
    4873           66 :     do_unencoded:
    4874           66 :       sprintf (length, "%u", IDENTIFIER_LENGTH (old_asm_id));
    4875           66 :       tm_name = concat ("_ZGTt", length, old_asm_name, NULL);
    4876              :     }
    4877              :   else
    4878              :     {
    4879          374 :       old_asm_name += 2;        /* Skip _Z */
    4880              : 
    4881          374 :       switch (dc->type)
    4882              :         {
    4883            0 :         case DEMANGLE_COMPONENT_TRANSACTION_CLONE:
    4884            0 :         case DEMANGLE_COMPONENT_NONTRANSACTION_CLONE:
    4885              :           /* Don't play silly games, you!  */
    4886            0 :           goto do_unencoded;
    4887              : 
    4888            0 :         case DEMANGLE_COMPONENT_HIDDEN_ALIAS:
    4889              :           /* I'd really like to know if we can ever be passed one of
    4890              :              these from the C++ front end.  The Logical Thing would
    4891              :              seem that hidden-alias should be outer-most, so that we
    4892              :              get hidden-alias of a transaction-clone and not vice-versa.  */
    4893            0 :           old_asm_name += 2;
    4894            0 :           break;
    4895              : 
    4896              :         default:
    4897              :           break;
    4898              :         }
    4899              : 
    4900          374 :       tm_name = concat ("_ZGTt", old_asm_name, NULL);
    4901              :     }
    4902          440 :   free (alloc);
    4903              : 
    4904          440 :   new_asm_id = get_identifier (tm_name);
    4905          440 :   free (tm_name);
    4906              : 
    4907          440 :   return new_asm_id;
    4908              : }
    4909              : 
    4910              : static inline void
    4911          221 : ipa_tm_mark_force_output_node (struct cgraph_node *node)
    4912              : {
    4913          221 :   node->mark_force_output ();
    4914          221 :   node->analyzed = true;
    4915          221 : }
    4916              : 
    4917              : static inline void
    4918            3 : ipa_tm_mark_forced_by_abi_node (struct cgraph_node *node)
    4919              : {
    4920            3 :   node->forced_by_abi = true;
    4921            3 :   node->analyzed = true;
    4922            3 : }
    4923              : 
    4924              : /* Callback data for ipa_tm_create_version_alias.  */
    4925              : struct create_version_alias_info
    4926              : {
    4927              :   struct cgraph_node *old_node;
    4928              :   tree new_decl;
    4929              : };
    4930              : 
    4931              : /* A subroutine of ipa_tm_create_version, called via
    4932              :    cgraph_for_node_and_aliases.  Create new tm clones for each of
    4933              :    the existing aliases.  */
    4934              : static bool
    4935          440 : ipa_tm_create_version_alias (struct cgraph_node *node, void *data)
    4936              : {
    4937          440 :   struct create_version_alias_info *info
    4938              :     = (struct create_version_alias_info *)data;
    4939          440 :   tree old_decl, new_decl, tm_name;
    4940          440 :   struct cgraph_node *new_node;
    4941              : 
    4942          440 :   if (!node->cpp_implicit_alias)
    4943              :     return false;
    4944              : 
    4945           58 :   old_decl = node->decl;
    4946           58 :   tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
    4947           58 :   new_decl = build_decl (DECL_SOURCE_LOCATION (old_decl),
    4948           58 :                          TREE_CODE (old_decl), tm_name,
    4949           58 :                          TREE_TYPE (old_decl));
    4950              : 
    4951           58 :   SET_DECL_ASSEMBLER_NAME (new_decl, tm_name);
    4952           58 :   SET_DECL_RTL (new_decl, NULL);
    4953              : 
    4954              :   /* Based loosely on C++'s make_alias_for().  */
    4955           58 :   TREE_PUBLIC (new_decl) = TREE_PUBLIC (old_decl);
    4956           58 :   DECL_CONTEXT (new_decl) = DECL_CONTEXT (old_decl);
    4957           58 :   DECL_LANG_SPECIFIC (new_decl) = DECL_LANG_SPECIFIC (old_decl);
    4958           58 :   TREE_READONLY (new_decl) = TREE_READONLY (old_decl);
    4959           58 :   DECL_EXTERNAL (new_decl) = 0;
    4960           58 :   DECL_ARTIFICIAL (new_decl) = 1;
    4961           58 :   TREE_ADDRESSABLE (new_decl) = 1;
    4962           58 :   TREE_USED (new_decl) = 1;
    4963           58 :   TREE_SYMBOL_REFERENCED (tm_name) = 1;
    4964              : 
    4965              :   /* Perform the same remapping to the comdat group.  */
    4966           58 :   if (DECL_ONE_ONLY (new_decl))
    4967            0 :     varpool_node::get (new_decl)->set_comdat_group
    4968            0 :       (tm_mangle (decl_comdat_group_id (old_decl)));
    4969              : 
    4970           58 :   new_node = cgraph_node::create_same_body_alias (new_decl, info->new_decl);
    4971           58 :   new_node->tm_clone = true;
    4972           58 :   new_node->externally_visible = info->old_node->externally_visible;
    4973           58 :   new_node->no_reorder = info->old_node->no_reorder;
    4974              :   /* ?? Do not traverse aliases here.  */
    4975           58 :   get_cg_data (&node, false)->clone = new_node;
    4976              : 
    4977           58 :   record_tm_clone_pair (old_decl, new_decl);
    4978              : 
    4979           58 :   if (info->old_node->force_output
    4980           58 :       || info->old_node->ref_list.first_referring ())
    4981           58 :     ipa_tm_mark_force_output_node (new_node);
    4982           58 :   if (info->old_node->forced_by_abi)
    4983            0 :     ipa_tm_mark_forced_by_abi_node (new_node);
    4984              :   return false;
    4985              : }
    4986              : 
    4987              : /* Create a copy of the function (possibly declaration only) of OLD_NODE,
    4988              :    appropriate for the transactional clone.  */
    4989              : 
    4990              : static void
    4991          382 : ipa_tm_create_version (struct cgraph_node *old_node)
    4992              : {
    4993          382 :   tree new_decl, old_decl, tm_name;
    4994          382 :   struct cgraph_node *new_node;
    4995              : 
    4996          382 :   old_decl = old_node->decl;
    4997          382 :   new_decl = copy_node (old_decl);
    4998              : 
    4999              :   /* DECL_ASSEMBLER_NAME needs to be set before we call
    5000              :      cgraph_copy_node_for_versioning below, because cgraph_node will
    5001              :      fill the assembler_name_hash.  */
    5002          382 :   tm_name = tm_mangle (DECL_ASSEMBLER_NAME (old_decl));
    5003          382 :   SET_DECL_ASSEMBLER_NAME (new_decl, tm_name);
    5004          382 :   SET_DECL_RTL (new_decl, NULL);
    5005          382 :   TREE_SYMBOL_REFERENCED (tm_name) = 1;
    5006              : 
    5007              :   /* Perform the same remapping to the comdat group.  */
    5008          382 :   if (DECL_ONE_ONLY (new_decl))
    5009            0 :     varpool_node::get (new_decl)->set_comdat_group
    5010            0 :       (tm_mangle (DECL_COMDAT_GROUP (old_decl)));
    5011              : 
    5012          382 :   gcc_assert (!old_node->ipa_transforms_to_apply.exists ());
    5013          382 :   new_node = old_node->create_version_clone (new_decl, vNULL, NULL);
    5014          382 :   new_node->local = false;
    5015          382 :   new_node->externally_visible = old_node->externally_visible;
    5016          382 :   new_node->lowered = true;
    5017          382 :   new_node->tm_clone = 1;
    5018          382 :   if (!old_node->implicit_section)
    5019          382 :     new_node->set_section (*old_node);
    5020          382 :   get_cg_data (&old_node, true)->clone = new_node;
    5021              : 
    5022          382 :   if (old_node->get_availability () >= AVAIL_INTERPOSABLE)
    5023              :     {
    5024              :       /* Remap extern inline to static inline.  */
    5025              :       /* ??? Is it worth trying to use make_decl_one_only?  */
    5026          272 :       if (DECL_DECLARED_INLINE_P (new_decl) && DECL_EXTERNAL (new_decl))
    5027              :         {
    5028            3 :           DECL_EXTERNAL (new_decl) = 0;
    5029            3 :           TREE_PUBLIC (new_decl) = 0;
    5030            3 :           DECL_WEAK (new_decl) = 0;
    5031              :         }
    5032              : 
    5033          272 :       tree_function_versioning (old_decl, new_decl,
    5034              :                                 NULL,  NULL, false, NULL, NULL);
    5035              :     }
    5036              : 
    5037          382 :   record_tm_clone_pair (old_decl, new_decl);
    5038              : 
    5039          382 :   symtab->call_cgraph_insertion_hooks (new_node);
    5040          382 :   if (old_node->force_output
    5041          382 :       || old_node->ref_list.first_referring ())
    5042          163 :     ipa_tm_mark_force_output_node (new_node);
    5043          382 :   if (old_node->forced_by_abi)
    5044            3 :     ipa_tm_mark_forced_by_abi_node (new_node);
    5045              : 
    5046              :   /* Do the same thing, but for any aliases of the original node.  */
    5047          382 :   {
    5048          382 :     struct create_version_alias_info data;
    5049          382 :     data.old_node = old_node;
    5050          382 :     data.new_decl = new_decl;
    5051          382 :     old_node->call_for_symbol_thunks_and_aliases (ipa_tm_create_version_alias,
    5052              :                                                 &data, true);
    5053              :   }
    5054          382 : }
    5055              : 
    5056              : /* Construct a call to TM_IRREVOCABLE and insert it at the beginning of BB.  */
    5057              : 
    5058              : static void
    5059           43 : ipa_tm_insert_irr_call (struct cgraph_node *node, struct tm_region *region,
    5060              :                         basic_block bb)
    5061              : {
    5062           43 :   gimple_stmt_iterator gsi;
    5063           43 :   gcall *g;
    5064              : 
    5065           43 :   transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
    5066              : 
    5067           43 :   g = gimple_build_call (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE),
    5068              :                          1, build_int_cst (NULL_TREE, MODE_SERIALIRREVOCABLE));
    5069              : 
    5070           43 :   split_block_after_labels (bb);
    5071           43 :   gsi = gsi_after_labels (bb);
    5072           43 :   gsi_insert_before (&gsi, g, GSI_SAME_STMT);
    5073              : 
    5074           43 :   node->create_edge (cgraph_node::get_create
    5075              :                        (builtin_decl_explicit (BUILT_IN_TM_IRREVOCABLE)),
    5076           43 :                      g, gimple_bb (g)->count);
    5077           43 : }
    5078              : 
    5079              : /* Construct a call to TM_GETTMCLONE and insert it before GSI.  */
    5080              : 
    5081              : static bool
    5082           24 : ipa_tm_insert_gettmclone_call (struct cgraph_node *node,
    5083              :                                struct tm_region *region,
    5084              :                                gimple_stmt_iterator *gsi, gcall *stmt)
    5085              : {
    5086           24 :   tree gettm_fn, ret, old_fn, callfn;
    5087           24 :   gcall *g;
    5088           24 :   gassign *g2;
    5089           24 :   bool safe;
    5090              : 
    5091           24 :   old_fn = gimple_call_fn (stmt);
    5092              : 
    5093           24 :   if (TREE_CODE (old_fn) == ADDR_EXPR)
    5094              :     {
    5095            7 :       tree fndecl = TREE_OPERAND (old_fn, 0);
    5096            7 :       tree clone = get_tm_clone_pair (fndecl);
    5097              : 
    5098              :       /* By transforming the call into a TM_GETTMCLONE, we are
    5099              :          technically taking the address of the original function and
    5100              :          its clone.  Explain this so inlining will know this function
    5101              :          is needed.  */
    5102            7 :       cgraph_node::get (fndecl)->mark_address_taken () ;
    5103            7 :       if (clone)
    5104            0 :         cgraph_node::get (clone)->mark_address_taken ();
    5105              :     }
    5106              : 
    5107           24 :   safe = is_tm_safe (TREE_TYPE (old_fn));
    5108           36 :   gettm_fn = builtin_decl_explicit (safe ? BUILT_IN_TM_GETTMCLONE_SAFE
    5109              :                                     : BUILT_IN_TM_GETTMCLONE_IRR);
    5110           24 :   ret = create_tmp_var (ptr_type_node);
    5111              : 
    5112           24 :   if (!safe)
    5113           12 :     transaction_subcode_ior (region, GTMA_MAY_ENTER_IRREVOCABLE);
    5114              : 
    5115              :   /* Discard OBJ_TYPE_REF, since we weren't able to fold it.  */
    5116           24 :   if (TREE_CODE (old_fn) == OBJ_TYPE_REF)
    5117           14 :     old_fn = OBJ_TYPE_REF_EXPR (old_fn);
    5118              : 
    5119           24 :   g = gimple_build_call (gettm_fn, 1, old_fn);
    5120           24 :   ret = make_ssa_name (ret, g);
    5121           24 :   gimple_call_set_lhs (g, ret);
    5122              : 
    5123           24 :   gsi_insert_before (gsi, g, GSI_SAME_STMT);
    5124              : 
    5125           24 :   node->create_edge (cgraph_node::get_create (gettm_fn), g, gimple_bb (g)->count);
    5126              : 
    5127              :   /* Cast return value from tm_gettmclone* into appropriate function
    5128              :      pointer.  */
    5129           24 :   callfn = create_tmp_var (TREE_TYPE (old_fn));
    5130           24 :   g2 = gimple_build_assign (callfn,
    5131           24 :                             fold_build1 (NOP_EXPR, TREE_TYPE (callfn), ret));
    5132           24 :   callfn = make_ssa_name (callfn, g2);
    5133           24 :   gimple_assign_set_lhs (g2, callfn);
    5134           24 :   gsi_insert_before (gsi, g2, GSI_SAME_STMT);
    5135              : 
    5136              :   /* ??? This is a hack to preserve the NOTHROW bit on the call,
    5137              :      which we would have derived from the decl.  Failure to save
    5138              :      this bit means we might have to split the basic block.  */
    5139           24 :   if (gimple_call_nothrow_p (stmt))
    5140            6 :     gimple_call_set_nothrow (stmt, true);
    5141              : 
    5142           24 :   gimple_call_set_fn (stmt, callfn);
    5143              : 
    5144              :   /* Discarding OBJ_TYPE_REF above may produce incompatible LHS and RHS
    5145              :      for a call statement.  Fix it.  */
    5146           24 :   {
    5147           24 :     tree lhs = gimple_call_lhs (stmt);
    5148           48 :     tree rettype = TREE_TYPE (gimple_call_fntype (stmt));
    5149           24 :     if (lhs
    5150           24 :         && !useless_type_conversion_p (TREE_TYPE (lhs), rettype))
    5151              :     {
    5152            0 :       tree temp;
    5153              : 
    5154            0 :       temp = create_tmp_reg (rettype);
    5155            0 :       gimple_call_set_lhs (stmt, temp);
    5156              : 
    5157            0 :       g2 = gimple_build_assign (lhs,
    5158            0 :                                 fold_build1 (VIEW_CONVERT_EXPR,
    5159              :                                              TREE_TYPE (lhs), temp));
    5160            0 :       gsi_insert_after (gsi, g2, GSI_SAME_STMT);
    5161              :     }
    5162              :   }
    5163              : 
    5164           24 :   update_stmt (stmt);
    5165           24 :   cgraph_edge *e = cgraph_node::get (current_function_decl)->get_edge (stmt);
    5166           24 :   if (e)
    5167              :     {
    5168           24 :       cgraph_polymorphic_indirect_info *pii
    5169           24 :         = dyn_cast <cgraph_polymorphic_indirect_info *> (e->indirect_info);
    5170           14 :       if (pii)
    5171           14 :         pii->mark_unusable ();
    5172              :     }
    5173           24 :   return true;
    5174              : }
    5175              : 
    5176              : /* Helper function for ipa_tm_transform_calls*.  Given a call
    5177              :    statement in GSI which resides inside transaction REGION, redirect
    5178              :    the call to either its wrapper function, or its clone.  */
    5179              : 
    5180              : static void
    5181          813 : ipa_tm_transform_calls_redirect (struct cgraph_node *node,
    5182              :                                  struct tm_region *region,
    5183              :                                  gimple_stmt_iterator *gsi,
    5184              :                                  bool *need_ssa_rename_p)
    5185              : {
    5186          813 :   gcall *stmt = as_a <gcall *> (gsi_stmt (*gsi));
    5187          813 :   struct cgraph_node *new_node;
    5188          813 :   struct cgraph_edge *e = node->get_edge (stmt);
    5189          813 :   tree fndecl = gimple_call_fndecl (stmt);
    5190              : 
    5191              :   /* For indirect calls, pass the address through the runtime.  */
    5192          813 :   if (fndecl == NULL)
    5193              :     {
    5194           34 :       *need_ssa_rename_p |=
    5195           17 :         ipa_tm_insert_gettmclone_call (node, region, gsi, stmt);
    5196           17 :       return;
    5197              :     }
    5198              : 
    5199              :   /* Handle some TM builtins.  Ordinarily these aren't actually generated
    5200              :      at this point, but handling these functions when written in by the
    5201              :      user makes it easier to build unit tests.  */
    5202          796 :   if (flags_from_decl_or_type (fndecl) & ECF_TM_BUILTIN)
    5203              :     return;
    5204              : 
    5205              :   /* Fixup recursive calls inside clones.  */
    5206              :   /* ??? Why did cgraph_copy_node_for_versioning update the call edges
    5207              :      for recursion but not update the call statements themselves?  */
    5208          384 :   if (e->caller == e->callee && decl_is_tm_clone (current_function_decl))
    5209              :     {
    5210            0 :       gimple_call_set_fndecl (stmt, current_function_decl);
    5211            0 :       return;
    5212              :     }
    5213              : 
    5214              :   /* If there is a replacement, use it.  */
    5215          383 :   fndecl = find_tm_replacement_function (fndecl);
    5216          383 :   if (fndecl)
    5217              :     {
    5218          134 :       new_node = cgraph_node::get_create (fndecl);
    5219              : 
    5220              :       /* ??? Mark all transaction_wrap functions tm_may_enter_irr.
    5221              : 
    5222              :          We can't do this earlier in record_tm_replacement because
    5223              :          cgraph_remove_unreachable_nodes is called before we inject
    5224              :          references to the node.  Further, we can't do this in some
    5225              :          nice central place in ipa_tm_execute because we don't have
    5226              :          the exact list of wrapper functions that would be used.
    5227              :          Marking more wrappers than necessary results in the creation
    5228              :          of unnecessary cgraph_nodes, which can cause some of the
    5229              :          other IPA passes to crash.
    5230              : 
    5231              :          We do need to mark these nodes so that we get the proper
    5232              :          result in expand_call_tm.  */
    5233              :       /* ??? This seems broken.  How is it that we're marking the
    5234              :          CALLEE as may_enter_irr?  Surely we should be marking the
    5235              :          CALLER.  Also note that find_tm_replacement_function also
    5236              :          contains mappings into the TM runtime, e.g. memcpy.  These
    5237              :          we know won't go irrevocable.  */
    5238          134 :       new_node->tm_may_enter_irr = 1;
    5239              :     }
    5240              :   else
    5241              :     {
    5242          249 :       struct tm_ipa_cg_data *d;
    5243          249 :       struct cgraph_node *tnode = e->callee;
    5244              : 
    5245          249 :       d = get_cg_data (&tnode, true);
    5246          249 :       new_node = d->clone;
    5247              : 
    5248              :       /* As we've already skipped pure calls and appropriate builtins,
    5249              :          and we've already marked irrevocable blocks, if we can't come
    5250              :          up with a static replacement, then ask the runtime.  */
    5251          249 :       if (new_node == NULL)
    5252              :         {
    5253           14 :           *need_ssa_rename_p |=
    5254            7 :             ipa_tm_insert_gettmclone_call (node, region, gsi, stmt);
    5255            7 :           return;
    5256              :         }
    5257              : 
    5258          242 :       fndecl = new_node->decl;
    5259              :     }
    5260              : 
    5261          376 :   e->redirect_callee (new_node);
    5262          376 :   gimple_call_set_fndecl (stmt, fndecl);
    5263              : }
    5264              : 
    5265              : /* Helper function for ipa_tm_transform_calls.  For a given BB,
    5266              :    install calls to tm_irrevocable when IRR_BLOCKS are reached,
    5267              :    redirect other calls to the generated transactional clone.  */
    5268              : 
    5269              : static bool
    5270         1388 : ipa_tm_transform_calls_1 (struct cgraph_node *node, struct tm_region *region,
    5271              :                           basic_block bb, bitmap irr_blocks)
    5272              : {
    5273         1388 :   gimple_stmt_iterator gsi;
    5274         1388 :   bool need_ssa_rename = false;
    5275              : 
    5276         1388 :   if (irr_blocks && bitmap_bit_p (irr_blocks, bb->index))
    5277              :     {
    5278           43 :       ipa_tm_insert_irr_call (node, region, bb);
    5279           43 :       return true;
    5280              :     }
    5281              : 
    5282         5862 :   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    5283              :     {
    5284         3172 :       gimple *stmt = gsi_stmt (gsi);
    5285              : 
    5286         3172 :       if (!is_gimple_call (stmt))
    5287         2241 :         continue;
    5288          931 :       if (is_tm_pure_call (stmt))
    5289          118 :         continue;
    5290              : 
    5291              :       /* Redirect edges to the appropriate replacement or clone.  */
    5292          813 :       ipa_tm_transform_calls_redirect (node, region, &gsi, &need_ssa_rename);
    5293              :     }
    5294              : 
    5295         1345 :   return need_ssa_rename;
    5296              : }
    5297              : 
    5298              : /* Walk the CFG for REGION, beginning at BB.  Install calls to
    5299              :    tm_irrevocable when IRR_BLOCKS are reached, redirect other calls to
    5300              :    the generated transactional clone.  */
    5301              : 
    5302              : static bool
    5303          466 : ipa_tm_transform_calls (struct cgraph_node *node, struct tm_region *region,
    5304              :                         basic_block bb, bitmap irr_blocks)
    5305              : {
    5306          466 :   bool need_ssa_rename = false;
    5307          466 :   edge e;
    5308          466 :   edge_iterator ei;
    5309          466 :   auto_vec<basic_block> queue;
    5310          466 :   bitmap visited_blocks = BITMAP_ALLOC (NULL);
    5311              : 
    5312          466 :   queue.safe_push (bb);
    5313         1388 :   do
    5314              :     {
    5315         1388 :       bb = queue.pop ();
    5316              : 
    5317         2776 :       need_ssa_rename |=
    5318         1388 :         ipa_tm_transform_calls_1 (node, region, bb, irr_blocks);
    5319              : 
    5320         1388 :       if (irr_blocks && bitmap_bit_p (irr_blocks, bb->index))
    5321           43 :         continue;
    5322              : 
    5323         1345 :       if (region && bitmap_bit_p (region->exit_blocks, bb->index))
    5324          316 :         continue;
    5325              : 
    5326         2093 :       FOR_EACH_EDGE (e, ei, bb->succs)
    5327         1064 :         if (!bitmap_bit_p (visited_blocks, e->dest->index))
    5328              :           {
    5329          922 :             bitmap_set_bit (visited_blocks, e->dest->index);
    5330          922 :             queue.safe_push (e->dest);
    5331              :           }
    5332              :     }
    5333         2776 :   while (!queue.is_empty ());
    5334              : 
    5335          466 :   BITMAP_FREE (visited_blocks);
    5336              : 
    5337          466 :   return need_ssa_rename;
    5338          466 : }
    5339              : 
    5340              : /* Transform the calls within the TM regions within NODE.  */
    5341              : 
    5342              : static void
    5343          284 : ipa_tm_transform_transaction (struct cgraph_node *node)
    5344              : {
    5345          284 :   struct tm_ipa_cg_data *d;
    5346          284 :   struct tm_region *region;
    5347          284 :   bool need_ssa_rename = false;
    5348              : 
    5349          284 :   d = get_cg_data (&node, true);
    5350              : 
    5351          284 :   push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    5352          284 :   calculate_dominance_info (CDI_DOMINATORS);
    5353              : 
    5354          634 :   for (region = d->all_tm_regions; region; region = region->next)
    5355              :     {
    5356              :       /* If we're sure to go irrevocable, don't transform anything.  */
    5357          408 :       if (d->irrevocable_blocks_normal
    5358          417 :           && bitmap_bit_p (d->irrevocable_blocks_normal,
    5359           67 :                            region->entry_block->index))
    5360              :         {
    5361           58 :           transaction_subcode_ior (region, GTMA_DOES_GO_IRREVOCABLE
    5362              :                                            | GTMA_MAY_ENTER_IRREVOCABLE
    5363              :                                            | GTMA_HAS_NO_INSTRUMENTATION);
    5364           58 :           continue;
    5365              :         }
    5366              : 
    5367          292 :       need_ssa_rename |=
    5368          292 :         ipa_tm_transform_calls (node, region, region->entry_block,
    5369              :                                 d->irrevocable_blocks_normal);
    5370              :     }
    5371              : 
    5372          284 :   if (need_ssa_rename)
    5373           13 :     update_ssa (TODO_update_ssa_only_virtuals);
    5374              : 
    5375          284 :   pop_cfun ();
    5376          284 : }
    5377              : 
    5378              : /* Transform the calls within the transactional clone of NODE.  */
    5379              : 
    5380              : static void
    5381          272 : ipa_tm_transform_clone (struct cgraph_node *node)
    5382              : {
    5383          272 :   struct tm_ipa_cg_data *d;
    5384          272 :   bool need_ssa_rename;
    5385              : 
    5386          272 :   d = get_cg_data (&node, true);
    5387              : 
    5388              :   /* If this function makes no calls and has no irrevocable blocks,
    5389              :      then there's nothing to do.  */
    5390              :   /* ??? Remove non-aborting top-level transactions.  */
    5391          272 :   if (!node->callees && !node->indirect_calls && !d->irrevocable_blocks_clone)
    5392              :     return;
    5393              : 
    5394          174 :   push_cfun (DECL_STRUCT_FUNCTION (d->clone->decl));
    5395          174 :   calculate_dominance_info (CDI_DOMINATORS);
    5396              : 
    5397          174 :   need_ssa_rename =
    5398          174 :     ipa_tm_transform_calls (d->clone, NULL,
    5399          174 :                             single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)),
    5400              :                             d->irrevocable_blocks_clone);
    5401              : 
    5402          174 :   if (need_ssa_rename)
    5403           48 :     update_ssa (TODO_update_ssa_only_virtuals);
    5404              : 
    5405          174 :   pop_cfun ();
    5406              : }
    5407              : 
    5408              : /* Main entry point for the transactional memory IPA pass.  */
    5409              : 
    5410              : static unsigned int
    5411          400 : ipa_tm_execute (void)
    5412              : {
    5413          400 :   cgraph_node_queue tm_callees = cgraph_node_queue ();
    5414              :   /* List of functions that will go irrevocable.  */
    5415          400 :   cgraph_node_queue irr_worklist = cgraph_node_queue ();
    5416              : 
    5417          400 :   struct cgraph_node *node;
    5418          400 :   struct tm_ipa_cg_data *d;
    5419          400 :   enum availability a;
    5420          400 :   unsigned int i;
    5421              : 
    5422          400 :   cgraph_node::checking_verify_cgraph_nodes ();
    5423              : 
    5424          400 :   bitmap_obstack_initialize (&tm_obstack);
    5425          400 :   initialize_original_copy_tables ();
    5426              : 
    5427              :   /* For all local functions marked tm_callable, queue them.  */
    5428         1503 :   FOR_EACH_DEFINED_FUNCTION (node)
    5429         1103 :     if (is_tm_callable (node->decl)
    5430         1103 :         && node->get_availability () >= AVAIL_INTERPOSABLE)
    5431              :       {
    5432          162 :         d = get_cg_data (&node, true);
    5433          324 :         maybe_push_queue (node, &tm_callees, &d->in_callee_queue);
    5434              :       }
    5435              : 
    5436              :   /* For all local reachable functions...  */
    5437         1524 :   FOR_EACH_DEFINED_FUNCTION (node)
    5438         1124 :     if (node->lowered
    5439         1124 :         && node->get_availability () >= AVAIL_INTERPOSABLE)
    5440              :       {
    5441              :         /* ... marked tm_pure, record that fact for the runtime by
    5442              :            indicating that the pure function is its own tm_callable.
    5443              :            No need to do this if the function's address can't be taken.  */
    5444          958 :         if (is_tm_pure (node->decl))
    5445              :           {
    5446           27 :             if (!node->local)
    5447           23 :               record_tm_clone_pair (node->decl, node->decl);
    5448           27 :             continue;
    5449              :           }
    5450              : 
    5451          931 :         push_cfun (DECL_STRUCT_FUNCTION (node->decl));
    5452          931 :         calculate_dominance_info (CDI_DOMINATORS);
    5453              : 
    5454          931 :         tm_region_init (NULL);
    5455          931 :         if (all_tm_regions)
    5456              :           {
    5457          284 :             d = get_cg_data (&node, true);
    5458              : 
    5459              :             /* Scan for calls that are in each transaction, and
    5460              :                generate the uninstrumented code path.  */
    5461          284 :             ipa_tm_scan_calls_transaction (d, &tm_callees);
    5462              : 
    5463              :             /* Put it in the worklist so we can scan the function
    5464              :                later (ipa_tm_scan_irr_function) and mark the
    5465              :                irrevocable blocks.  */
    5466          284 :             maybe_push_queue (node, &irr_worklist, &d->in_worklist);
    5467          284 :             d->want_irr_scan_normal = true;
    5468              :           }
    5469              : 
    5470          931 :         pop_cfun ();
    5471              :       }
    5472              : 
    5473              :   /* For every local function on the callee list, scan as if we will be
    5474              :      creating a transactional clone, queueing all new functions we find
    5475              :      along the way.  */
    5476         1594 :   for (i = 0; i < tm_callees.length (); ++i)
    5477              :     {
    5478          508 :       node = tm_callees[i];
    5479          508 :       a = node->get_availability ();
    5480          508 :       d = get_cg_data (&node, true);
    5481              : 
    5482              :       /* Put it in the worklist so we can scan the function later
    5483              :          (ipa_tm_scan_irr_function) and mark the irrevocable
    5484              :          blocks.  */
    5485          508 :       maybe_push_queue (node, &irr_worklist, &d->in_worklist);
    5486              : 
    5487              :       /* Some callees cannot be arbitrarily cloned.  These will always be
    5488              :          irrevocable.  Mark these now, so that we need not scan them.  */
    5489          508 :       if (is_tm_irrevocable (node->decl))
    5490            6 :         ipa_tm_note_irrevocable (node, &irr_worklist);
    5491          502 :       else if (a <= AVAIL_NOT_AVAILABLE
    5492          502 :                && !is_tm_safe_or_pure (node->decl))
    5493           64 :         ipa_tm_note_irrevocable (node, &irr_worklist);
    5494          438 :       else if (a >= AVAIL_INTERPOSABLE)
    5495              :         {
    5496          337 :           if (!tree_versionable_function_p (node->decl))
    5497            0 :             ipa_tm_note_irrevocable (node, &irr_worklist);
    5498          337 :           else if (!d->is_irrevocable)
    5499              :             {
    5500              :               /* If this is an alias, make sure its base is queued as well.
    5501              :                  we need not scan the callees now, as the base will do.  */
    5502          337 :               if (node->alias)
    5503              :                 {
    5504            0 :                   node = cgraph_node::get (thunk_info::get (node)->alias);
    5505            0 :                   d = get_cg_data (&node, true);
    5506            0 :                   maybe_push_queue (node, &tm_callees, &d->in_callee_queue);
    5507            0 :                   continue;
    5508              :                 }
    5509              : 
    5510              :               /* Add all nodes called by this function into
    5511              :                  tm_callees as well.  */
    5512          337 :               ipa_tm_scan_calls_clone (node, &tm_callees);
    5513              :             }
    5514              :         }
    5515              :     }
    5516              : 
    5517              :   /* Iterate scans until no more work to be done.  Prefer not to use
    5518              :      vec::pop because the worklist tends to follow a breadth-first
    5519              :      search of the callgraph, which should allow convergance with a
    5520              :      minimum number of scans.  But we also don't want the worklist
    5521              :      array to grow without bound, so we shift the array up periodically.  */
    5522         1201 :   for (i = 0; i < irr_worklist.length (); ++i)
    5523              :     {
    5524          801 :       if (i > 256 && i == irr_worklist.length () / 8)
    5525              :         {
    5526            0 :           irr_worklist.block_remove (0, i);
    5527            0 :           i = 0;
    5528              :         }
    5529              : 
    5530          801 :       node = irr_worklist[i];
    5531          801 :       d = get_cg_data (&node, true);
    5532          801 :       d->in_worklist = false;
    5533              : 
    5534          801 :       if (d->want_irr_scan_normal)
    5535              :         {
    5536          291 :           d->want_irr_scan_normal = false;
    5537          291 :           ipa_tm_scan_irr_function (node, false);
    5538              :         }
    5539          801 :       if (d->in_callee_queue && ipa_tm_scan_irr_function (node, true))
    5540           54 :         ipa_tm_note_irrevocable (node, &irr_worklist);
    5541              :     }
    5542              : 
    5543              :   /* For every function on the callee list, collect the tm_may_enter_irr
    5544              :      bit on the node.  */
    5545          400 :   irr_worklist.truncate (0);
    5546         1994 :   for (i = 0; i < tm_callees.length (); ++i)
    5547              :     {
    5548          508 :       node = tm_callees[i];
    5549          508 :       if (ipa_tm_mayenterirr_function (node))
    5550              :         {
    5551          129 :           d = get_cg_data (&node, true);
    5552          129 :           gcc_assert (d->in_worklist == false);
    5553          129 :           maybe_push_queue (node, &irr_worklist, &d->in_worklist);
    5554              :         }
    5555              :     }
    5556              : 
    5557              :   /* Propagate the tm_may_enter_irr bit to callers until stable.  */
    5558          571 :   for (i = 0; i < irr_worklist.length (); ++i)
    5559              :     {
    5560          171 :       struct cgraph_node *caller;
    5561          171 :       struct cgraph_edge *e;
    5562          171 :       struct ipa_ref *ref;
    5563              : 
    5564          171 :       if (i > 256 && i == irr_worklist.length () / 8)
    5565              :         {
    5566            0 :           irr_worklist.block_remove (0, i);
    5567            0 :           i = 0;
    5568              :         }
    5569              : 
    5570          171 :       node = irr_worklist[i];
    5571          171 :       d = get_cg_data (&node, true);
    5572          171 :       d->in_worklist = false;
    5573          171 :       node->tm_may_enter_irr = true;
    5574              : 
    5575              :       /* Propagate back to normal callers.  */
    5576          357 :       for (e = node->callers; e ; e = e->next_caller)
    5577              :         {
    5578          186 :           caller = e->caller;
    5579          186 :           if (!is_tm_safe_or_pure (caller->decl)
    5580          186 :               && !caller->tm_may_enter_irr)
    5581              :             {
    5582          122 :               d = get_cg_data (&caller, true);
    5583          160 :               maybe_push_queue (caller, &irr_worklist, &d->in_worklist);
    5584              :             }
    5585              :         }
    5586              : 
    5587              :       /* Propagate back to referring aliases as well.  */
    5588          179 :       FOR_EACH_ALIAS (node, ref)
    5589              :         {
    5590            8 :           caller = dyn_cast<cgraph_node *> (ref->referring);
    5591            8 :           if (!caller->tm_may_enter_irr)
    5592              :             {
    5593              :               /* ?? Do not traverse aliases here.  */
    5594            8 :               d = get_cg_data (&caller, false);
    5595           12 :               maybe_push_queue (caller, &irr_worklist, &d->in_worklist);
    5596              :             }
    5597              :         }
    5598              :     }
    5599              : 
    5600              :   /* Now validate all tm_safe functions, and all atomic regions in
    5601              :      other functions.  */
    5602         1524 :   FOR_EACH_DEFINED_FUNCTION (node)
    5603         1124 :     if (node->lowered
    5604         1124 :         && node->get_availability () >= AVAIL_INTERPOSABLE)
    5605              :       {
    5606          958 :         d = get_cg_data (&node, true);
    5607          958 :         if (is_tm_safe (node->decl))
    5608          130 :           ipa_tm_diagnose_tm_safe (node);
    5609          828 :         else if (d->all_tm_regions)
    5610          275 :           ipa_tm_diagnose_transaction (node, d->all_tm_regions);
    5611              :       }
    5612              : 
    5613              :   /* Create clones.  Do those that are not irrevocable and have a
    5614              :      positive call count.  Do those publicly visible functions that
    5615              :      the user directed us to clone.  */
    5616         1594 :   for (i = 0; i < tm_callees.length (); ++i)
    5617              :     {
    5618          508 :       bool doit = false;
    5619              : 
    5620          508 :       node = tm_callees[i];
    5621          508 :       if (node->cpp_implicit_alias)
    5622            0 :         continue;
    5623              : 
    5624          508 :       a = node->get_availability ();
    5625          508 :       d = get_cg_data (&node, true);
    5626              : 
    5627          508 :       if (a <= AVAIL_NOT_AVAILABLE)
    5628          170 :         doit = is_tm_callable (node->decl);
    5629          338 :       else if (a <= AVAIL_AVAILABLE && is_tm_callable (node->decl))
    5630              :         doit = true;
    5631          179 :       else if (!d->is_irrevocable
    5632          153 :                && d->tm_callers_normal + d->tm_callers_clone > 0)
    5633              :         doit = true;
    5634              : 
    5635          170 :       if (doit)
    5636          382 :         ipa_tm_create_version (node);
    5637              :     }
    5638              : 
    5639              :   /* Redirect calls to the new clones, and insert irrevocable marks.  */
    5640          908 :   for (i = 0; i < tm_callees.length (); ++i)
    5641              :     {
    5642          508 :       node = tm_callees[i];
    5643          508 :       if (node->analyzed)
    5644              :         {
    5645          338 :           d = get_cg_data (&node, true);
    5646          338 :           if (d->clone)
    5647          272 :             ipa_tm_transform_clone (node);
    5648              :         }
    5649              :     }
    5650         1854 :   FOR_EACH_DEFINED_FUNCTION (node)
    5651         1454 :     if (node->lowered
    5652         1454 :         && node->get_availability () >= AVAIL_INTERPOSABLE)
    5653              :       {
    5654         1230 :         d = get_cg_data (&node, true);
    5655         1230 :         if (d->all_tm_regions)
    5656          284 :           ipa_tm_transform_transaction (node);
    5657              :       }
    5658              : 
    5659              :   /* Free and clear all data structures.  */
    5660          400 :   tm_callees.release ();
    5661          400 :   irr_worklist.release ();
    5662          400 :   bitmap_obstack_release (&tm_obstack);
    5663          400 :   free_original_copy_tables ();
    5664              : 
    5665         2937 :   FOR_EACH_FUNCTION (node)
    5666         2537 :     node->aux = NULL;
    5667              : 
    5668          400 :   cgraph_node::checking_verify_cgraph_nodes ();
    5669              : 
    5670          400 :   return 0;
    5671              : }
    5672              : 
    5673              : namespace {
    5674              : 
    5675              : const pass_data pass_data_ipa_tm =
    5676              : {
    5677              :   SIMPLE_IPA_PASS, /* type */
    5678              :   "tmipa", /* name */
    5679              :   OPTGROUP_NONE, /* optinfo_flags */
    5680              :   TV_TRANS_MEM, /* tv_id */
    5681              :   ( PROP_ssa | PROP_cfg ), /* properties_required */
    5682              :   0, /* properties_provided */
    5683              :   0, /* properties_destroyed */
    5684              :   0, /* todo_flags_start */
    5685              :   0, /* todo_flags_finish */
    5686              : };
    5687              : 
    5688              : class pass_ipa_tm : public simple_ipa_opt_pass
    5689              : {
    5690              : public:
    5691       285722 :   pass_ipa_tm (gcc::context *ctxt)
    5692       571444 :     : simple_ipa_opt_pass (pass_data_ipa_tm, ctxt)
    5693              :   {}
    5694              : 
    5695              :   /* opt_pass methods: */
    5696       229960 :   bool gate (function *) final override { return flag_tm; }
    5697          400 :   unsigned int execute (function *) final override { return ipa_tm_execute (); }
    5698              : 
    5699              : }; // class pass_ipa_tm
    5700              : 
    5701              : } // anon namespace
    5702              : 
    5703              : simple_ipa_opt_pass *
    5704       285722 : make_pass_ipa_tm (gcc::context *ctxt)
    5705              : {
    5706       285722 :   return new pass_ipa_tm (ctxt);
    5707              : }
    5708              : 
    5709              : #include "gt-trans-mem.h"
        

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.