LCOV - code coverage report
Current view: top level - gcc - tsan.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 258 367 70.3 %
Date: 2020-04-04 11:58:09 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /* GCC instrumentation plugin for ThreadSanitizer.
       2                 :            :    Copyright (C) 2011-2020 Free Software Foundation, Inc.
       3                 :            :    Contributed by Dmitry Vyukov <dvyukov@google.com>
       4                 :            : 
       5                 :            : This file is part of GCC.
       6                 :            : 
       7                 :            : GCC is free software; you can redistribute it and/or modify it under
       8                 :            : the terms of the GNU General Public License as published by the Free
       9                 :            : Software Foundation; either version 3, or (at your option) any later
      10                 :            : version.
      11                 :            : 
      12                 :            : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :            : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :            : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :            : for more details.
      16                 :            : 
      17                 :            : You should have received a copy of the GNU General Public License
      18                 :            : along with GCC; see the file COPYING3.  If not see
      19                 :            : <http://www.gnu.org/licenses/>.  */
      20                 :            : 
      21                 :            : 
      22                 :            : #include "config.h"
      23                 :            : #include "system.h"
      24                 :            : #include "coretypes.h"
      25                 :            : #include "backend.h"
      26                 :            : #include "rtl.h"
      27                 :            : #include "tree.h"
      28                 :            : #include "memmodel.h"
      29                 :            : #include "gimple.h"
      30                 :            : #include "tree-pass.h"
      31                 :            : #include "ssa.h"
      32                 :            : #include "cgraph.h"
      33                 :            : #include "fold-const.h"
      34                 :            : #include "gimplify.h"
      35                 :            : #include "gimple-iterator.h"
      36                 :            : #include "gimplify-me.h"
      37                 :            : #include "tree-cfg.h"
      38                 :            : #include "tree-iterator.h"
      39                 :            : #include "tree-ssa-propagate.h"
      40                 :            : #include "tree-ssa-loop-ivopts.h"
      41                 :            : #include "tree-eh.h"
      42                 :            : #include "tsan.h"
      43                 :            : #include "stringpool.h"
      44                 :            : #include "attribs.h"
      45                 :            : #include "asan.h"
      46                 :            : #include "builtins.h"
      47                 :            : #include "target.h"
      48                 :            : 
      49                 :            : /* Number of instrumented memory accesses in the current function.  */
      50                 :            : 
      51                 :            : /* Builds the following decl
      52                 :            :    void __tsan_read/writeX (void *addr);  */
      53                 :            : 
      54                 :            : static tree
      55                 :        676 : get_memory_access_decl (bool is_write, unsigned size)
      56                 :            : {
      57                 :        676 :   enum built_in_function fcode;
      58                 :            : 
      59                 :        676 :   if (size <= 1)
      60                 :          4 :     fcode = is_write ? BUILT_IN_TSAN_WRITE1
      61                 :            :                      : BUILT_IN_TSAN_READ1;
      62                 :        672 :   else if (size <= 3)
      63                 :          4 :     fcode = is_write ? BUILT_IN_TSAN_WRITE2
      64                 :            :                      : BUILT_IN_TSAN_READ2;
      65                 :        668 :   else if (size <= 7)
      66                 :        241 :     fcode = is_write ? BUILT_IN_TSAN_WRITE4
      67                 :            :                      : BUILT_IN_TSAN_READ4;
      68                 :        427 :   else if (size <= 15)
      69                 :        421 :     fcode = is_write ? BUILT_IN_TSAN_WRITE8
      70                 :            :                      : BUILT_IN_TSAN_READ8;
      71                 :            :   else
      72                 :          6 :     fcode = is_write ? BUILT_IN_TSAN_WRITE16
      73                 :            :                      : BUILT_IN_TSAN_READ16;
      74                 :            : 
      75                 :        676 :   return builtin_decl_implicit (fcode);
      76                 :            : }
      77                 :            : 
      78                 :            : /* Check as to whether EXPR refers to a store to vptr.  */
      79                 :            : 
      80                 :            : static tree
      81                 :        700 : is_vptr_store (gimple *stmt, tree expr, bool is_write)
      82                 :            : {
      83                 :        700 :   if (is_write == true
      84                 :        944 :       && gimple_assign_single_p (stmt)
      85                 :        944 :       && TREE_CODE (expr) == COMPONENT_REF)
      86                 :            :     {
      87                 :         30 :       tree field = TREE_OPERAND (expr, 1);
      88                 :         30 :       if (TREE_CODE (field) == FIELD_DECL
      89                 :         60 :           && DECL_VIRTUAL_P (field))
      90                 :         18 :         return gimple_assign_rhs1 (stmt);
      91                 :            :     }
      92                 :            :   return NULL;
      93                 :            : }
      94                 :            : 
      95                 :            : /* Instruments EXPR if needed. If any instrumentation is inserted,
      96                 :            :    return true.  */
      97                 :            : 
      98                 :            : static bool
      99                 :        761 : instrument_expr (gimple_stmt_iterator gsi, tree expr, bool is_write)
     100                 :            : {
     101                 :        761 :   tree base, rhs, expr_ptr, builtin_decl;
     102                 :        761 :   basic_block bb;
     103                 :        761 :   HOST_WIDE_INT size;
     104                 :        761 :   gimple *stmt, *g;
     105                 :        761 :   gimple_seq seq;
     106                 :        761 :   location_t loc;
     107                 :        761 :   unsigned int align;
     108                 :            : 
     109                 :        761 :   size = int_size_in_bytes (TREE_TYPE (expr));
     110                 :        761 :   if (size <= 0)
     111                 :            :     return false;
     112                 :            : 
     113                 :        760 :   poly_int64 unused_bitsize, unused_bitpos;
     114                 :        760 :   tree offset;
     115                 :        760 :   machine_mode mode;
     116                 :        760 :   int unsignedp, reversep, volatilep = 0;
     117                 :        760 :   base = get_inner_reference (expr, &unused_bitsize, &unused_bitpos, &offset,
     118                 :            :                               &mode, &unsignedp, &reversep, &volatilep);
     119                 :            : 
     120                 :            :   /* No need to instrument accesses to decls that don't escape,
     121                 :            :      they can't escape to other threads then.  */
     122                 :        760 :   if (DECL_P (base) && !is_global_var (base))
     123                 :            :     {
     124                 :        197 :       struct pt_solution pt;
     125                 :        197 :       memset (&pt, 0, sizeof (pt));
     126                 :        197 :       pt.escaped = 1;
     127                 :        197 :       pt.ipa_escaped = flag_ipa_pta != 0;
     128                 :        197 :       if (!pt_solution_includes (&pt, base))
     129                 :         59 :         return false;
     130                 :        168 :       if (!may_be_aliased (base))
     131                 :            :         return false;
     132                 :            :     }
     133                 :            : 
     134                 :        701 :   if (TREE_READONLY (base) || (VAR_P (base) && DECL_HARD_REGISTER (base)))
     135                 :            :     return false;
     136                 :            : 
     137                 :        700 :   stmt = gsi_stmt (gsi);
     138                 :        700 :   loc = gimple_location (stmt);
     139                 :        700 :   rhs = is_vptr_store (stmt, expr, is_write);
     140                 :            : 
     141                 :        700 :   if ((TREE_CODE (expr) == COMPONENT_REF
     142                 :         47 :        && DECL_BIT_FIELD_TYPE (TREE_OPERAND (expr, 1)))
     143                 :        735 :       || TREE_CODE (expr) == BIT_FIELD_REF)
     144                 :            :     {
     145                 :         12 :       HOST_WIDE_INT bitpos, bitsize;
     146                 :         12 :       base = TREE_OPERAND (expr, 0);
     147                 :         12 :       if (TREE_CODE (expr) == COMPONENT_REF)
     148                 :            :         {
     149                 :         12 :           expr = TREE_OPERAND (expr, 1);
     150                 :         20 :           if (is_write && DECL_BIT_FIELD_REPRESENTATIVE (expr))
     151                 :         12 :             expr = DECL_BIT_FIELD_REPRESENTATIVE (expr);
     152                 :         12 :           if (!tree_fits_uhwi_p (DECL_FIELD_OFFSET (expr))
     153                 :         12 :               || !tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (expr))
     154                 :         24 :               || !tree_fits_uhwi_p (DECL_SIZE (expr)))
     155                 :            :             return false;
     156                 :         12 :           bitpos = tree_to_uhwi (DECL_FIELD_OFFSET (expr)) * BITS_PER_UNIT
     157                 :         12 :                    + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (expr));
     158                 :         12 :           bitsize = tree_to_uhwi (DECL_SIZE (expr));
     159                 :            :         }
     160                 :            :       else
     161                 :            :         {
     162                 :          0 :           if (!tree_fits_uhwi_p (TREE_OPERAND (expr, 2))
     163                 :          0 :               || !tree_fits_uhwi_p (TREE_OPERAND (expr, 1)))
     164                 :            :             return false;
     165                 :          0 :           bitpos = tree_to_uhwi (TREE_OPERAND (expr, 2));
     166                 :          0 :           bitsize = tree_to_uhwi (TREE_OPERAND (expr, 1));
     167                 :            :         }
     168                 :         12 :       if (bitpos < 0 || bitsize <= 0)
     169                 :            :         return false;
     170                 :         12 :       size = (bitpos % BITS_PER_UNIT + bitsize + BITS_PER_UNIT - 1)
     171                 :         12 :              / BITS_PER_UNIT;
     172                 :         12 :       if (may_be_nonaddressable_p (base))
     173                 :            :         return false;
     174                 :         12 :       align = get_object_alignment (base);
     175                 :         12 :       if (align < BITS_PER_UNIT)
     176                 :            :         return false;
     177                 :         12 :       bitpos = bitpos & ~(BITS_PER_UNIT - 1);
     178                 :         12 :       if ((align - 1) & bitpos)
     179                 :            :         {
     180                 :          0 :           align = (align - 1) & bitpos;
     181                 :          0 :           align = least_bit_hwi (align);
     182                 :            :         }
     183                 :         12 :       expr = build_fold_addr_expr (unshare_expr (base));
     184                 :         12 :       expr = build2 (MEM_REF, char_type_node, expr,
     185                 :         12 :                      build_int_cst (TREE_TYPE (expr), bitpos / BITS_PER_UNIT));
     186                 :         12 :       expr_ptr = build_fold_addr_expr (expr);
     187                 :            :     }
     188                 :            :   else
     189                 :            :     {
     190                 :        688 :       if (may_be_nonaddressable_p (expr))
     191                 :            :         return false;
     192                 :        688 :       align = get_object_alignment (expr);
     193                 :        688 :       if (align < BITS_PER_UNIT)
     194                 :            :         return false;
     195                 :        688 :       expr_ptr = build_fold_addr_expr (unshare_expr (expr));
     196                 :            :     }
     197                 :        700 :   expr_ptr = force_gimple_operand (expr_ptr, &seq, true, NULL_TREE);
     198                 :        700 :   if ((size & (size - 1)) != 0 || size > 16
     199                 :        698 :       || align < MIN (size, 8) * BITS_PER_UNIT)
     200                 :            :     {
     201                 :          8 :       builtin_decl = builtin_decl_implicit (is_write
     202                 :            :                                             ? BUILT_IN_TSAN_WRITE_RANGE
     203                 :            :                                             : BUILT_IN_TSAN_READ_RANGE);
     204                 :          6 :       g = gimple_build_call (builtin_decl, 2, expr_ptr, size_int (size));
     205                 :            :     }
     206                 :        694 :   else if (rhs == NULL)
     207                 :        676 :     g = gimple_build_call (get_memory_access_decl (is_write, size),
     208                 :            :                            1, expr_ptr);
     209                 :            :   else
     210                 :            :     {
     211                 :         18 :       builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_VPTR_UPDATE);
     212                 :         18 :       g = gimple_build_call (builtin_decl, 2, expr_ptr, unshare_expr (rhs));
     213                 :            :     }
     214                 :        700 :   gimple_set_location (g, loc);
     215                 :        700 :   gimple_seq_add_stmt_without_update (&seq, g);
     216                 :            :   /* Instrumentation for assignment of a function result
     217                 :            :      must be inserted after the call.  Instrumentation for
     218                 :            :      reads of function arguments must be inserted before the call.
     219                 :            :      That's because the call can contain synchronization.  */
     220                 :        700 :   if (is_gimple_call (stmt) && is_write)
     221                 :            :     {
     222                 :            :       /* If the call can throw, it must be the last stmt in
     223                 :            :          a basic block, so the instrumented stmts need to be
     224                 :            :          inserted in successor bbs.  */
     225                 :          0 :       if (is_ctrl_altering_stmt (stmt))
     226                 :            :         {
     227                 :          0 :           edge e;
     228                 :            : 
     229                 :          0 :           bb = gsi_bb (gsi);
     230                 :          0 :           e = find_fallthru_edge (bb->succs);
     231                 :          0 :           if (e)
     232                 :          0 :             gsi_insert_seq_on_edge_immediate (e, seq);
     233                 :            :         }
     234                 :            :       else
     235                 :          0 :         gsi_insert_seq_after (&gsi, seq, GSI_NEW_STMT);
     236                 :            :     }
     237                 :            :   else
     238                 :        700 :     gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT);
     239                 :            : 
     240                 :            :   return true;
     241                 :            : }
     242                 :            : 
     243                 :            : /* Actions for sync/atomic builtin transformations.  */
     244                 :            : enum tsan_atomic_action
     245                 :            : {
     246                 :            :   check_last, add_seq_cst, add_acquire, weak_cas, strong_cas,
     247                 :            :   bool_cas, val_cas, lock_release, fetch_op, fetch_op_seq_cst,
     248                 :            :   bool_clear, bool_test_and_set
     249                 :            : };
     250                 :            : 
     251                 :            : /* Table how to map sync/atomic builtins to their corresponding
     252                 :            :    tsan equivalents.  */
     253                 :            : static const struct tsan_map_atomic
     254                 :            : {
     255                 :            :   enum built_in_function fcode, tsan_fcode;
     256                 :            :   enum tsan_atomic_action action;
     257                 :            :   enum tree_code code;
     258                 :            : } tsan_atomic_table[] =
     259                 :            : {
     260                 :            : #define TRANSFORM(fcode, tsan_fcode, action, code) \
     261                 :            :   { BUILT_IN_##fcode, BUILT_IN_##tsan_fcode, action, code }
     262                 :            : #define CHECK_LAST(fcode, tsan_fcode) \
     263                 :            :   TRANSFORM (fcode, tsan_fcode, check_last, ERROR_MARK)
     264                 :            : #define ADD_SEQ_CST(fcode, tsan_fcode) \
     265                 :            :   TRANSFORM (fcode, tsan_fcode, add_seq_cst, ERROR_MARK)
     266                 :            : #define ADD_ACQUIRE(fcode, tsan_fcode) \
     267                 :            :   TRANSFORM (fcode, tsan_fcode, add_acquire, ERROR_MARK)
     268                 :            : #define WEAK_CAS(fcode, tsan_fcode) \
     269                 :            :   TRANSFORM (fcode, tsan_fcode, weak_cas, ERROR_MARK)
     270                 :            : #define STRONG_CAS(fcode, tsan_fcode) \
     271                 :            :   TRANSFORM (fcode, tsan_fcode, strong_cas, ERROR_MARK)
     272                 :            : #define BOOL_CAS(fcode, tsan_fcode) \
     273                 :            :   TRANSFORM (fcode, tsan_fcode, bool_cas, ERROR_MARK)
     274                 :            : #define VAL_CAS(fcode, tsan_fcode) \
     275                 :            :   TRANSFORM (fcode, tsan_fcode, val_cas, ERROR_MARK)
     276                 :            : #define LOCK_RELEASE(fcode, tsan_fcode) \
     277                 :            :   TRANSFORM (fcode, tsan_fcode, lock_release, ERROR_MARK)
     278                 :            : #define FETCH_OP(fcode, tsan_fcode, code) \
     279                 :            :   TRANSFORM (fcode, tsan_fcode, fetch_op, code)
     280                 :            : #define FETCH_OPS(fcode, tsan_fcode, code) \
     281                 :            :   TRANSFORM (fcode, tsan_fcode, fetch_op_seq_cst, code)
     282                 :            : #define BOOL_CLEAR(fcode, tsan_fcode) \
     283                 :            :   TRANSFORM (fcode, tsan_fcode, bool_clear, ERROR_MARK)
     284                 :            : #define BOOL_TEST_AND_SET(fcode, tsan_fcode) \
     285                 :            :   TRANSFORM (fcode, tsan_fcode, bool_test_and_set, ERROR_MARK)
     286                 :            : 
     287                 :            :   CHECK_LAST (ATOMIC_LOAD_1, TSAN_ATOMIC8_LOAD),
     288                 :            :   CHECK_LAST (ATOMIC_LOAD_2, TSAN_ATOMIC16_LOAD),
     289                 :            :   CHECK_LAST (ATOMIC_LOAD_4, TSAN_ATOMIC32_LOAD),
     290                 :            :   CHECK_LAST (ATOMIC_LOAD_8, TSAN_ATOMIC64_LOAD),
     291                 :            :   CHECK_LAST (ATOMIC_LOAD_16, TSAN_ATOMIC128_LOAD),
     292                 :            :   CHECK_LAST (ATOMIC_STORE_1, TSAN_ATOMIC8_STORE),
     293                 :            :   CHECK_LAST (ATOMIC_STORE_2, TSAN_ATOMIC16_STORE),
     294                 :            :   CHECK_LAST (ATOMIC_STORE_4, TSAN_ATOMIC32_STORE),
     295                 :            :   CHECK_LAST (ATOMIC_STORE_8, TSAN_ATOMIC64_STORE),
     296                 :            :   CHECK_LAST (ATOMIC_STORE_16, TSAN_ATOMIC128_STORE),
     297                 :            :   CHECK_LAST (ATOMIC_EXCHANGE_1, TSAN_ATOMIC8_EXCHANGE),
     298                 :            :   CHECK_LAST (ATOMIC_EXCHANGE_2, TSAN_ATOMIC16_EXCHANGE),
     299                 :            :   CHECK_LAST (ATOMIC_EXCHANGE_4, TSAN_ATOMIC32_EXCHANGE),
     300                 :            :   CHECK_LAST (ATOMIC_EXCHANGE_8, TSAN_ATOMIC64_EXCHANGE),
     301                 :            :   CHECK_LAST (ATOMIC_EXCHANGE_16, TSAN_ATOMIC128_EXCHANGE),
     302                 :            :   CHECK_LAST (ATOMIC_FETCH_ADD_1, TSAN_ATOMIC8_FETCH_ADD),
     303                 :            :   CHECK_LAST (ATOMIC_FETCH_ADD_2, TSAN_ATOMIC16_FETCH_ADD),
     304                 :            :   CHECK_LAST (ATOMIC_FETCH_ADD_4, TSAN_ATOMIC32_FETCH_ADD),
     305                 :            :   CHECK_LAST (ATOMIC_FETCH_ADD_8, TSAN_ATOMIC64_FETCH_ADD),
     306                 :            :   CHECK_LAST (ATOMIC_FETCH_ADD_16, TSAN_ATOMIC128_FETCH_ADD),
     307                 :            :   CHECK_LAST (ATOMIC_FETCH_SUB_1, TSAN_ATOMIC8_FETCH_SUB),
     308                 :            :   CHECK_LAST (ATOMIC_FETCH_SUB_2, TSAN_ATOMIC16_FETCH_SUB),
     309                 :            :   CHECK_LAST (ATOMIC_FETCH_SUB_4, TSAN_ATOMIC32_FETCH_SUB),
     310                 :            :   CHECK_LAST (ATOMIC_FETCH_SUB_8, TSAN_ATOMIC64_FETCH_SUB),
     311                 :            :   CHECK_LAST (ATOMIC_FETCH_SUB_16, TSAN_ATOMIC128_FETCH_SUB),
     312                 :            :   CHECK_LAST (ATOMIC_FETCH_AND_1, TSAN_ATOMIC8_FETCH_AND),
     313                 :            :   CHECK_LAST (ATOMIC_FETCH_AND_2, TSAN_ATOMIC16_FETCH_AND),
     314                 :            :   CHECK_LAST (ATOMIC_FETCH_AND_4, TSAN_ATOMIC32_FETCH_AND),
     315                 :            :   CHECK_LAST (ATOMIC_FETCH_AND_8, TSAN_ATOMIC64_FETCH_AND),
     316                 :            :   CHECK_LAST (ATOMIC_FETCH_AND_16, TSAN_ATOMIC128_FETCH_AND),
     317                 :            :   CHECK_LAST (ATOMIC_FETCH_OR_1, TSAN_ATOMIC8_FETCH_OR),
     318                 :            :   CHECK_LAST (ATOMIC_FETCH_OR_2, TSAN_ATOMIC16_FETCH_OR),
     319                 :            :   CHECK_LAST (ATOMIC_FETCH_OR_4, TSAN_ATOMIC32_FETCH_OR),
     320                 :            :   CHECK_LAST (ATOMIC_FETCH_OR_8, TSAN_ATOMIC64_FETCH_OR),
     321                 :            :   CHECK_LAST (ATOMIC_FETCH_OR_16, TSAN_ATOMIC128_FETCH_OR),
     322                 :            :   CHECK_LAST (ATOMIC_FETCH_XOR_1, TSAN_ATOMIC8_FETCH_XOR),
     323                 :            :   CHECK_LAST (ATOMIC_FETCH_XOR_2, TSAN_ATOMIC16_FETCH_XOR),
     324                 :            :   CHECK_LAST (ATOMIC_FETCH_XOR_4, TSAN_ATOMIC32_FETCH_XOR),
     325                 :            :   CHECK_LAST (ATOMIC_FETCH_XOR_8, TSAN_ATOMIC64_FETCH_XOR),
     326                 :            :   CHECK_LAST (ATOMIC_FETCH_XOR_16, TSAN_ATOMIC128_FETCH_XOR),
     327                 :            :   CHECK_LAST (ATOMIC_FETCH_NAND_1, TSAN_ATOMIC8_FETCH_NAND),
     328                 :            :   CHECK_LAST (ATOMIC_FETCH_NAND_2, TSAN_ATOMIC16_FETCH_NAND),
     329                 :            :   CHECK_LAST (ATOMIC_FETCH_NAND_4, TSAN_ATOMIC32_FETCH_NAND),
     330                 :            :   CHECK_LAST (ATOMIC_FETCH_NAND_8, TSAN_ATOMIC64_FETCH_NAND),
     331                 :            :   CHECK_LAST (ATOMIC_FETCH_NAND_16, TSAN_ATOMIC128_FETCH_NAND),
     332                 :            : 
     333                 :            :   CHECK_LAST (ATOMIC_THREAD_FENCE, TSAN_ATOMIC_THREAD_FENCE),
     334                 :            :   CHECK_LAST (ATOMIC_SIGNAL_FENCE, TSAN_ATOMIC_SIGNAL_FENCE),
     335                 :            : 
     336                 :            :   FETCH_OP (ATOMIC_ADD_FETCH_1, TSAN_ATOMIC8_FETCH_ADD, PLUS_EXPR),
     337                 :            :   FETCH_OP (ATOMIC_ADD_FETCH_2, TSAN_ATOMIC16_FETCH_ADD, PLUS_EXPR),
     338                 :            :   FETCH_OP (ATOMIC_ADD_FETCH_4, TSAN_ATOMIC32_FETCH_ADD, PLUS_EXPR),
     339                 :            :   FETCH_OP (ATOMIC_ADD_FETCH_8, TSAN_ATOMIC64_FETCH_ADD, PLUS_EXPR),
     340                 :            :   FETCH_OP (ATOMIC_ADD_FETCH_16, TSAN_ATOMIC128_FETCH_ADD, PLUS_EXPR),
     341                 :            :   FETCH_OP (ATOMIC_SUB_FETCH_1, TSAN_ATOMIC8_FETCH_SUB, MINUS_EXPR),
     342                 :            :   FETCH_OP (ATOMIC_SUB_FETCH_2, TSAN_ATOMIC16_FETCH_SUB, MINUS_EXPR),
     343                 :            :   FETCH_OP (ATOMIC_SUB_FETCH_4, TSAN_ATOMIC32_FETCH_SUB, MINUS_EXPR),
     344                 :            :   FETCH_OP (ATOMIC_SUB_FETCH_8, TSAN_ATOMIC64_FETCH_SUB, MINUS_EXPR),
     345                 :            :   FETCH_OP (ATOMIC_SUB_FETCH_16, TSAN_ATOMIC128_FETCH_SUB, MINUS_EXPR),
     346                 :            :   FETCH_OP (ATOMIC_AND_FETCH_1, TSAN_ATOMIC8_FETCH_AND, BIT_AND_EXPR),
     347                 :            :   FETCH_OP (ATOMIC_AND_FETCH_2, TSAN_ATOMIC16_FETCH_AND, BIT_AND_EXPR),
     348                 :            :   FETCH_OP (ATOMIC_AND_FETCH_4, TSAN_ATOMIC32_FETCH_AND, BIT_AND_EXPR),
     349                 :            :   FETCH_OP (ATOMIC_AND_FETCH_8, TSAN_ATOMIC64_FETCH_AND, BIT_AND_EXPR),
     350                 :            :   FETCH_OP (ATOMIC_AND_FETCH_16, TSAN_ATOMIC128_FETCH_AND, BIT_AND_EXPR),
     351                 :            :   FETCH_OP (ATOMIC_OR_FETCH_1, TSAN_ATOMIC8_FETCH_OR, BIT_IOR_EXPR),
     352                 :            :   FETCH_OP (ATOMIC_OR_FETCH_2, TSAN_ATOMIC16_FETCH_OR, BIT_IOR_EXPR),
     353                 :            :   FETCH_OP (ATOMIC_OR_FETCH_4, TSAN_ATOMIC32_FETCH_OR, BIT_IOR_EXPR),
     354                 :            :   FETCH_OP (ATOMIC_OR_FETCH_8, TSAN_ATOMIC64_FETCH_OR, BIT_IOR_EXPR),
     355                 :            :   FETCH_OP (ATOMIC_OR_FETCH_16, TSAN_ATOMIC128_FETCH_OR, BIT_IOR_EXPR),
     356                 :            :   FETCH_OP (ATOMIC_XOR_FETCH_1, TSAN_ATOMIC8_FETCH_XOR, BIT_XOR_EXPR),
     357                 :            :   FETCH_OP (ATOMIC_XOR_FETCH_2, TSAN_ATOMIC16_FETCH_XOR, BIT_XOR_EXPR),
     358                 :            :   FETCH_OP (ATOMIC_XOR_FETCH_4, TSAN_ATOMIC32_FETCH_XOR, BIT_XOR_EXPR),
     359                 :            :   FETCH_OP (ATOMIC_XOR_FETCH_8, TSAN_ATOMIC64_FETCH_XOR, BIT_XOR_EXPR),
     360                 :            :   FETCH_OP (ATOMIC_XOR_FETCH_16, TSAN_ATOMIC128_FETCH_XOR, BIT_XOR_EXPR),
     361                 :            :   FETCH_OP (ATOMIC_NAND_FETCH_1, TSAN_ATOMIC8_FETCH_NAND, BIT_NOT_EXPR),
     362                 :            :   FETCH_OP (ATOMIC_NAND_FETCH_2, TSAN_ATOMIC16_FETCH_NAND, BIT_NOT_EXPR),
     363                 :            :   FETCH_OP (ATOMIC_NAND_FETCH_4, TSAN_ATOMIC32_FETCH_NAND, BIT_NOT_EXPR),
     364                 :            :   FETCH_OP (ATOMIC_NAND_FETCH_8, TSAN_ATOMIC64_FETCH_NAND, BIT_NOT_EXPR),
     365                 :            :   FETCH_OP (ATOMIC_NAND_FETCH_16, TSAN_ATOMIC128_FETCH_NAND, BIT_NOT_EXPR),
     366                 :            : 
     367                 :            :   ADD_ACQUIRE (SYNC_LOCK_TEST_AND_SET_1, TSAN_ATOMIC8_EXCHANGE),
     368                 :            :   ADD_ACQUIRE (SYNC_LOCK_TEST_AND_SET_2, TSAN_ATOMIC16_EXCHANGE),
     369                 :            :   ADD_ACQUIRE (SYNC_LOCK_TEST_AND_SET_4, TSAN_ATOMIC32_EXCHANGE),
     370                 :            :   ADD_ACQUIRE (SYNC_LOCK_TEST_AND_SET_8, TSAN_ATOMIC64_EXCHANGE),
     371                 :            :   ADD_ACQUIRE (SYNC_LOCK_TEST_AND_SET_16, TSAN_ATOMIC128_EXCHANGE),
     372                 :            : 
     373                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_ADD_1, TSAN_ATOMIC8_FETCH_ADD),
     374                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_ADD_2, TSAN_ATOMIC16_FETCH_ADD),
     375                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_ADD_4, TSAN_ATOMIC32_FETCH_ADD),
     376                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_ADD_8, TSAN_ATOMIC64_FETCH_ADD),
     377                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_ADD_16, TSAN_ATOMIC128_FETCH_ADD),
     378                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_SUB_1, TSAN_ATOMIC8_FETCH_SUB),
     379                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_SUB_2, TSAN_ATOMIC16_FETCH_SUB),
     380                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_SUB_4, TSAN_ATOMIC32_FETCH_SUB),
     381                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_SUB_8, TSAN_ATOMIC64_FETCH_SUB),
     382                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_SUB_16, TSAN_ATOMIC128_FETCH_SUB),
     383                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_AND_1, TSAN_ATOMIC8_FETCH_AND),
     384                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_AND_2, TSAN_ATOMIC16_FETCH_AND),
     385                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_AND_4, TSAN_ATOMIC32_FETCH_AND),
     386                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_AND_8, TSAN_ATOMIC64_FETCH_AND),
     387                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_AND_16, TSAN_ATOMIC128_FETCH_AND),
     388                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_OR_1, TSAN_ATOMIC8_FETCH_OR),
     389                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_OR_2, TSAN_ATOMIC16_FETCH_OR),
     390                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_OR_4, TSAN_ATOMIC32_FETCH_OR),
     391                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_OR_8, TSAN_ATOMIC64_FETCH_OR),
     392                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_OR_16, TSAN_ATOMIC128_FETCH_OR),
     393                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_XOR_1, TSAN_ATOMIC8_FETCH_XOR),
     394                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_XOR_2, TSAN_ATOMIC16_FETCH_XOR),
     395                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_XOR_4, TSAN_ATOMIC32_FETCH_XOR),
     396                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_XOR_8, TSAN_ATOMIC64_FETCH_XOR),
     397                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_XOR_16, TSAN_ATOMIC128_FETCH_XOR),
     398                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_NAND_1, TSAN_ATOMIC8_FETCH_NAND),
     399                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_NAND_2, TSAN_ATOMIC16_FETCH_NAND),
     400                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_NAND_4, TSAN_ATOMIC32_FETCH_NAND),
     401                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_NAND_8, TSAN_ATOMIC64_FETCH_NAND),
     402                 :            :   ADD_SEQ_CST (SYNC_FETCH_AND_NAND_16, TSAN_ATOMIC128_FETCH_NAND),
     403                 :            : 
     404                 :            :   ADD_SEQ_CST (SYNC_SYNCHRONIZE, TSAN_ATOMIC_THREAD_FENCE),
     405                 :            : 
     406                 :            :   FETCH_OPS (SYNC_ADD_AND_FETCH_1, TSAN_ATOMIC8_FETCH_ADD, PLUS_EXPR),
     407                 :            :   FETCH_OPS (SYNC_ADD_AND_FETCH_2, TSAN_ATOMIC16_FETCH_ADD, PLUS_EXPR),
     408                 :            :   FETCH_OPS (SYNC_ADD_AND_FETCH_4, TSAN_ATOMIC32_FETCH_ADD, PLUS_EXPR),
     409                 :            :   FETCH_OPS (SYNC_ADD_AND_FETCH_8, TSAN_ATOMIC64_FETCH_ADD, PLUS_EXPR),
     410                 :            :   FETCH_OPS (SYNC_ADD_AND_FETCH_16, TSAN_ATOMIC128_FETCH_ADD, PLUS_EXPR),
     411                 :            :   FETCH_OPS (SYNC_SUB_AND_FETCH_1, TSAN_ATOMIC8_FETCH_SUB, MINUS_EXPR),
     412                 :            :   FETCH_OPS (SYNC_SUB_AND_FETCH_2, TSAN_ATOMIC16_FETCH_SUB, MINUS_EXPR),
     413                 :            :   FETCH_OPS (SYNC_SUB_AND_FETCH_4, TSAN_ATOMIC32_FETCH_SUB, MINUS_EXPR),
     414                 :            :   FETCH_OPS (SYNC_SUB_AND_FETCH_8, TSAN_ATOMIC64_FETCH_SUB, MINUS_EXPR),
     415                 :            :   FETCH_OPS (SYNC_SUB_AND_FETCH_16, TSAN_ATOMIC128_FETCH_SUB, MINUS_EXPR),
     416                 :            :   FETCH_OPS (SYNC_AND_AND_FETCH_1, TSAN_ATOMIC8_FETCH_AND, BIT_AND_EXPR),
     417                 :            :   FETCH_OPS (SYNC_AND_AND_FETCH_2, TSAN_ATOMIC16_FETCH_AND, BIT_AND_EXPR),
     418                 :            :   FETCH_OPS (SYNC_AND_AND_FETCH_4, TSAN_ATOMIC32_FETCH_AND, BIT_AND_EXPR),
     419                 :            :   FETCH_OPS (SYNC_AND_AND_FETCH_8, TSAN_ATOMIC64_FETCH_AND, BIT_AND_EXPR),
     420                 :            :   FETCH_OPS (SYNC_AND_AND_FETCH_16, TSAN_ATOMIC128_FETCH_AND, BIT_AND_EXPR),
     421                 :            :   FETCH_OPS (SYNC_OR_AND_FETCH_1, TSAN_ATOMIC8_FETCH_OR, BIT_IOR_EXPR),
     422                 :            :   FETCH_OPS (SYNC_OR_AND_FETCH_2, TSAN_ATOMIC16_FETCH_OR, BIT_IOR_EXPR),
     423                 :            :   FETCH_OPS (SYNC_OR_AND_FETCH_4, TSAN_ATOMIC32_FETCH_OR, BIT_IOR_EXPR),
     424                 :            :   FETCH_OPS (SYNC_OR_AND_FETCH_8, TSAN_ATOMIC64_FETCH_OR, BIT_IOR_EXPR),
     425                 :            :   FETCH_OPS (SYNC_OR_AND_FETCH_16, TSAN_ATOMIC128_FETCH_OR, BIT_IOR_EXPR),
     426                 :            :   FETCH_OPS (SYNC_XOR_AND_FETCH_1, TSAN_ATOMIC8_FETCH_XOR, BIT_XOR_EXPR),
     427                 :            :   FETCH_OPS (SYNC_XOR_AND_FETCH_2, TSAN_ATOMIC16_FETCH_XOR, BIT_XOR_EXPR),
     428                 :            :   FETCH_OPS (SYNC_XOR_AND_FETCH_4, TSAN_ATOMIC32_FETCH_XOR, BIT_XOR_EXPR),
     429                 :            :   FETCH_OPS (SYNC_XOR_AND_FETCH_8, TSAN_ATOMIC64_FETCH_XOR, BIT_XOR_EXPR),
     430                 :            :   FETCH_OPS (SYNC_XOR_AND_FETCH_16, TSAN_ATOMIC128_FETCH_XOR, BIT_XOR_EXPR),
     431                 :            :   FETCH_OPS (SYNC_NAND_AND_FETCH_1, TSAN_ATOMIC8_FETCH_NAND, BIT_NOT_EXPR),
     432                 :            :   FETCH_OPS (SYNC_NAND_AND_FETCH_2, TSAN_ATOMIC16_FETCH_NAND, BIT_NOT_EXPR),
     433                 :            :   FETCH_OPS (SYNC_NAND_AND_FETCH_4, TSAN_ATOMIC32_FETCH_NAND, BIT_NOT_EXPR),
     434                 :            :   FETCH_OPS (SYNC_NAND_AND_FETCH_8, TSAN_ATOMIC64_FETCH_NAND, BIT_NOT_EXPR),
     435                 :            :   FETCH_OPS (SYNC_NAND_AND_FETCH_16, TSAN_ATOMIC128_FETCH_NAND, BIT_NOT_EXPR),
     436                 :            : 
     437                 :            :   WEAK_CAS (ATOMIC_COMPARE_EXCHANGE_1, TSAN_ATOMIC8_COMPARE_EXCHANGE_WEAK),
     438                 :            :   WEAK_CAS (ATOMIC_COMPARE_EXCHANGE_2, TSAN_ATOMIC16_COMPARE_EXCHANGE_WEAK),
     439                 :            :   WEAK_CAS (ATOMIC_COMPARE_EXCHANGE_4, TSAN_ATOMIC32_COMPARE_EXCHANGE_WEAK),
     440                 :            :   WEAK_CAS (ATOMIC_COMPARE_EXCHANGE_8, TSAN_ATOMIC64_COMPARE_EXCHANGE_WEAK),
     441                 :            :   WEAK_CAS (ATOMIC_COMPARE_EXCHANGE_16, TSAN_ATOMIC128_COMPARE_EXCHANGE_WEAK),
     442                 :            : 
     443                 :            :   STRONG_CAS (ATOMIC_COMPARE_EXCHANGE_1, TSAN_ATOMIC8_COMPARE_EXCHANGE_STRONG),
     444                 :            :   STRONG_CAS (ATOMIC_COMPARE_EXCHANGE_2,
     445                 :            :               TSAN_ATOMIC16_COMPARE_EXCHANGE_STRONG),
     446                 :            :   STRONG_CAS (ATOMIC_COMPARE_EXCHANGE_4,
     447                 :            :               TSAN_ATOMIC32_COMPARE_EXCHANGE_STRONG),
     448                 :            :   STRONG_CAS (ATOMIC_COMPARE_EXCHANGE_8,
     449                 :            :               TSAN_ATOMIC64_COMPARE_EXCHANGE_STRONG),
     450                 :            :   STRONG_CAS (ATOMIC_COMPARE_EXCHANGE_16,
     451                 :            :               TSAN_ATOMIC128_COMPARE_EXCHANGE_STRONG),
     452                 :            : 
     453                 :            :   BOOL_CAS (SYNC_BOOL_COMPARE_AND_SWAP_1,
     454                 :            :             TSAN_ATOMIC8_COMPARE_EXCHANGE_STRONG),
     455                 :            :   BOOL_CAS (SYNC_BOOL_COMPARE_AND_SWAP_2,
     456                 :            :             TSAN_ATOMIC16_COMPARE_EXCHANGE_STRONG),
     457                 :            :   BOOL_CAS (SYNC_BOOL_COMPARE_AND_SWAP_4,
     458                 :            :             TSAN_ATOMIC32_COMPARE_EXCHANGE_STRONG),
     459                 :            :   BOOL_CAS (SYNC_BOOL_COMPARE_AND_SWAP_8,
     460                 :            :             TSAN_ATOMIC64_COMPARE_EXCHANGE_STRONG),
     461                 :            :   BOOL_CAS (SYNC_BOOL_COMPARE_AND_SWAP_16,
     462                 :            :             TSAN_ATOMIC128_COMPARE_EXCHANGE_STRONG),
     463                 :            : 
     464                 :            :   VAL_CAS (SYNC_VAL_COMPARE_AND_SWAP_1, TSAN_ATOMIC8_COMPARE_EXCHANGE_STRONG),
     465                 :            :   VAL_CAS (SYNC_VAL_COMPARE_AND_SWAP_2, TSAN_ATOMIC16_COMPARE_EXCHANGE_STRONG),
     466                 :            :   VAL_CAS (SYNC_VAL_COMPARE_AND_SWAP_4, TSAN_ATOMIC32_COMPARE_EXCHANGE_STRONG),
     467                 :            :   VAL_CAS (SYNC_VAL_COMPARE_AND_SWAP_8, TSAN_ATOMIC64_COMPARE_EXCHANGE_STRONG),
     468                 :            :   VAL_CAS (SYNC_VAL_COMPARE_AND_SWAP_16,
     469                 :            :            TSAN_ATOMIC128_COMPARE_EXCHANGE_STRONG),
     470                 :            : 
     471                 :            :   LOCK_RELEASE (SYNC_LOCK_RELEASE_1, TSAN_ATOMIC8_STORE),
     472                 :            :   LOCK_RELEASE (SYNC_LOCK_RELEASE_2, TSAN_ATOMIC16_STORE),
     473                 :            :   LOCK_RELEASE (SYNC_LOCK_RELEASE_4, TSAN_ATOMIC32_STORE),
     474                 :            :   LOCK_RELEASE (SYNC_LOCK_RELEASE_8, TSAN_ATOMIC64_STORE),
     475                 :            :   LOCK_RELEASE (SYNC_LOCK_RELEASE_16, TSAN_ATOMIC128_STORE),
     476                 :            : 
     477                 :            :   BOOL_CLEAR (ATOMIC_CLEAR, TSAN_ATOMIC8_STORE),
     478                 :            : 
     479                 :            :   BOOL_TEST_AND_SET (ATOMIC_TEST_AND_SET, TSAN_ATOMIC8_EXCHANGE)
     480                 :            : };
     481                 :            : 
     482                 :            : /* Instrument an atomic builtin.  */
     483                 :            : 
     484                 :            : static void
     485                 :         50 : instrument_builtin_call (gimple_stmt_iterator *gsi)
     486                 :            : {
     487                 :         50 :   gimple *stmt = gsi_stmt (*gsi), *g;
     488                 :         50 :   tree callee = gimple_call_fndecl (stmt), last_arg, args[6], t, lhs;
     489                 :         50 :   enum built_in_function fcode = DECL_FUNCTION_CODE (callee);
     490                 :         50 :   unsigned int i, num = gimple_call_num_args (stmt), j;
     491                 :        119 :   for (j = 0; j < 6 && j < num; j++)
     492                 :         69 :     args[j] = gimple_call_arg (stmt, j);
     493                 :       6974 :   for (i = 0; i < ARRAY_SIZE (tsan_atomic_table); i++)
     494                 :       6942 :     if (fcode != tsan_atomic_table[i].fcode)
     495                 :       6924 :       continue;
     496                 :            :     else
     497                 :            :       {
     498                 :         18 :         tree decl = builtin_decl_implicit (tsan_atomic_table[i].tsan_fcode);
     499                 :         18 :         if (decl == NULL_TREE)
     500                 :         18 :           return;
     501                 :         18 :         switch (tsan_atomic_table[i].action)
     502                 :            :           {
     503                 :         10 :           case check_last:
     504                 :         10 :           case fetch_op:
     505                 :         10 :             last_arg = gimple_call_arg (stmt, num - 1);
     506                 :         10 :             if (tree_fits_uhwi_p (last_arg)
     507                 :         10 :                 && memmodel_base (tree_to_uhwi (last_arg)) >= MEMMODEL_LAST)
     508                 :            :               return;
     509                 :         10 :             gimple_call_set_fndecl (stmt, decl);
     510                 :         10 :             update_stmt (stmt);
     511                 :         10 :             maybe_clean_eh_stmt (stmt);
     512                 :         10 :             if (tsan_atomic_table[i].action == fetch_op)
     513                 :            :               {
     514                 :          0 :                 args[1] = gimple_call_arg (stmt, 1);
     515                 :          0 :                 goto adjust_result;
     516                 :            :               }
     517                 :            :             return;
     518                 :          0 :           case add_seq_cst:
     519                 :          0 :           case add_acquire:
     520                 :          0 :           case fetch_op_seq_cst:
     521                 :          0 :             gcc_assert (num <= 2);
     522                 :          0 :             for (j = 0; j < num; j++)
     523                 :          0 :               args[j] = gimple_call_arg (stmt, j);
     524                 :          0 :             for (; j < 2; j++)
     525                 :          0 :               args[j] = NULL_TREE;
     526                 :          0 :             args[num] = build_int_cst (NULL_TREE,
     527                 :            :                                        tsan_atomic_table[i].action
     528                 :            :                                        != add_acquire
     529                 :          0 :                                        ? MEMMODEL_SEQ_CST
     530                 :            :                                        : MEMMODEL_ACQUIRE);
     531                 :          0 :             update_gimple_call (gsi, decl, num + 1, args[0], args[1], args[2]);
     532                 :          0 :             maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     533                 :          0 :             stmt = gsi_stmt (*gsi);
     534                 :          0 :             if (tsan_atomic_table[i].action == fetch_op_seq_cst)
     535                 :            :               {
     536                 :          0 :               adjust_result:
     537                 :          0 :                 lhs = gimple_call_lhs (stmt);
     538                 :          0 :                 if (lhs == NULL_TREE)
     539                 :            :                   return;
     540                 :          0 :                 if (!useless_type_conversion_p (TREE_TYPE (lhs),
     541                 :          0 :                                                 TREE_TYPE (args[1])))
     542                 :            :                   {
     543                 :          0 :                     tree var = make_ssa_name (TREE_TYPE (lhs));
     544                 :          0 :                     g = gimple_build_assign (var, NOP_EXPR, args[1]);
     545                 :          0 :                     gsi_insert_after (gsi, g, GSI_NEW_STMT);
     546                 :          0 :                     args[1] = var;
     547                 :            :                   }
     548                 :          0 :                 gimple_call_set_lhs (stmt, make_ssa_name (TREE_TYPE (lhs)));
     549                 :            :                 /* BIT_NOT_EXPR stands for NAND.  */
     550                 :          0 :                 if (tsan_atomic_table[i].code == BIT_NOT_EXPR)
     551                 :            :                   {
     552                 :          0 :                     tree var = make_ssa_name (TREE_TYPE (lhs));
     553                 :          0 :                     g = gimple_build_assign (var, BIT_AND_EXPR,
     554                 :            :                                              gimple_call_lhs (stmt), args[1]);
     555                 :          0 :                     gsi_insert_after (gsi, g, GSI_NEW_STMT);
     556                 :          0 :                     g = gimple_build_assign (lhs, BIT_NOT_EXPR, var);
     557                 :            :                   }
     558                 :            :                 else
     559                 :          0 :                   g = gimple_build_assign (lhs, tsan_atomic_table[i].code,
     560                 :            :                                            gimple_call_lhs (stmt), args[1]);
     561                 :          0 :                 update_stmt (stmt);
     562                 :          0 :                 gsi_insert_after (gsi, g, GSI_NEW_STMT);
     563                 :            :               }
     564                 :          0 :             return;
     565                 :          0 :           case weak_cas:
     566                 :          0 :             if (!integer_nonzerop (gimple_call_arg (stmt, 3)))
     567                 :          0 :               continue;
     568                 :            :             /* FALLTHRU */
     569                 :          0 :           case strong_cas:
     570                 :          0 :             gcc_assert (num == 6);
     571                 :          0 :             for (j = 0; j < 6; j++)
     572                 :          0 :               args[j] = gimple_call_arg (stmt, j);
     573                 :          0 :             if (tree_fits_uhwi_p (args[4])
     574                 :          0 :                 && memmodel_base (tree_to_uhwi (args[4])) >= MEMMODEL_LAST)
     575                 :            :               return;
     576                 :          0 :             if (tree_fits_uhwi_p (args[5])
     577                 :          0 :                 && memmodel_base (tree_to_uhwi (args[5])) >= MEMMODEL_LAST)
     578                 :            :               return;
     579                 :          0 :             update_gimple_call (gsi, decl, 5, args[0], args[1], args[2],
     580                 :            :                                 args[4], args[5]);
     581                 :          0 :             maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     582                 :          0 :             return;
     583                 :          0 :           case bool_cas:
     584                 :          0 :           case val_cas:
     585                 :          0 :             gcc_assert (num == 3);
     586                 :          0 :             for (j = 0; j < 3; j++)
     587                 :          0 :               args[j] = gimple_call_arg (stmt, j);
     588                 :          0 :             t = TYPE_ARG_TYPES (TREE_TYPE (decl));
     589                 :          0 :             t = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (t)));
     590                 :          0 :             t = create_tmp_var (t);
     591                 :          0 :             mark_addressable (t);
     592                 :          0 :             if (!useless_type_conversion_p (TREE_TYPE (t),
     593                 :          0 :                                             TREE_TYPE (args[1])))
     594                 :            :               {
     595                 :          0 :                 g = gimple_build_assign (make_ssa_name (TREE_TYPE (t)),
     596                 :            :                                          NOP_EXPR, args[1]);
     597                 :          0 :                 gsi_insert_before (gsi, g, GSI_SAME_STMT);
     598                 :          0 :                 args[1] = gimple_assign_lhs (g);
     599                 :            :               }
     600                 :          0 :             g = gimple_build_assign (t, args[1]);
     601                 :          0 :             gsi_insert_before (gsi, g, GSI_SAME_STMT);
     602                 :          0 :             lhs = gimple_call_lhs (stmt);
     603                 :          0 :             update_gimple_call (gsi, decl, 5, args[0],
     604                 :            :                                 build_fold_addr_expr (t), args[2],
     605                 :            :                                 build_int_cst (NULL_TREE,
     606                 :          0 :                                                MEMMODEL_SEQ_CST),
     607                 :            :                                 build_int_cst (NULL_TREE,
     608                 :          0 :                                                MEMMODEL_SEQ_CST));
     609                 :          0 :             maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     610                 :          0 :             if (tsan_atomic_table[i].action == val_cas && lhs)
     611                 :            :               {
     612                 :          0 :                 tree cond;
     613                 :          0 :                 stmt = gsi_stmt (*gsi);
     614                 :          0 :                 g = gimple_build_assign (make_ssa_name (TREE_TYPE (t)), t);
     615                 :          0 :                 gsi_insert_after (gsi, g, GSI_NEW_STMT);
     616                 :          0 :                 t = make_ssa_name (TREE_TYPE (TREE_TYPE (decl)), stmt);
     617                 :          0 :                 cond = build2 (NE_EXPR, boolean_type_node, t,
     618                 :          0 :                                build_int_cst (TREE_TYPE (t), 0));
     619                 :          0 :                 g = gimple_build_assign (lhs, COND_EXPR, cond, args[1],
     620                 :            :                                          gimple_assign_lhs (g));
     621                 :          0 :                 gimple_call_set_lhs (stmt, t);
     622                 :          0 :                 update_stmt (stmt);
     623                 :          0 :                 gsi_insert_after (gsi, g, GSI_NEW_STMT);
     624                 :            :               }
     625                 :          0 :             return;
     626                 :          0 :           case lock_release:
     627                 :          0 :             gcc_assert (num == 1);
     628                 :          0 :             t = TYPE_ARG_TYPES (TREE_TYPE (decl));
     629                 :          0 :             t = TREE_VALUE (TREE_CHAIN (t));
     630                 :          0 :             update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
     631                 :          0 :                                 build_int_cst (t, 0),
     632                 :            :                                 build_int_cst (NULL_TREE,
     633                 :          0 :                                                MEMMODEL_RELEASE));
     634                 :          0 :             maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     635                 :          0 :             return;
     636                 :          8 :           case bool_clear:
     637                 :          8 :           case bool_test_and_set:
     638                 :          8 :             if (BOOL_TYPE_SIZE != 8)
     639                 :            :               {
     640                 :            :                 decl = NULL_TREE;
     641                 :            :                 for (j = 1; j < 5; j++)
     642                 :            :                   if (BOOL_TYPE_SIZE == (8 << j))
     643                 :            :                     {
     644                 :            :                       enum built_in_function tsan_fcode
     645                 :            :                         = (enum built_in_function)
     646                 :            :                           (tsan_atomic_table[i].tsan_fcode + j);
     647                 :            :                       decl = builtin_decl_implicit (tsan_fcode);
     648                 :            :                       break;
     649                 :            :                     }
     650                 :            :                 if (decl == NULL_TREE)
     651                 :            :                   return;
     652                 :            :               }
     653                 :          8 :             last_arg = gimple_call_arg (stmt, num - 1);
     654                 :          8 :             if (tree_fits_uhwi_p (last_arg)
     655                 :          8 :                 && memmodel_base (tree_to_uhwi (last_arg)) >= MEMMODEL_LAST)
     656                 :            :               return;
     657                 :          8 :             t = TYPE_ARG_TYPES (TREE_TYPE (decl));
     658                 :          8 :             t = TREE_VALUE (TREE_CHAIN (t));
     659                 :          8 :             if (tsan_atomic_table[i].action == bool_clear)
     660                 :            :               {
     661                 :          4 :                 update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
     662                 :          4 :                                     build_int_cst (t, 0), last_arg);
     663                 :          4 :                 maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     664                 :          4 :                 return;
     665                 :            :               }
     666                 :          4 :             t = build_int_cst (t, targetm.atomic_test_and_set_trueval);
     667                 :          4 :             update_gimple_call (gsi, decl, 3, gimple_call_arg (stmt, 0),
     668                 :            :                                 t, last_arg);
     669                 :          4 :             maybe_clean_or_replace_eh_stmt (stmt, gsi_stmt (*gsi));
     670                 :          4 :             stmt = gsi_stmt (*gsi);
     671                 :          4 :             lhs = gimple_call_lhs (stmt);
     672                 :          4 :             if (lhs == NULL_TREE)
     673                 :            :               return;
     674                 :          4 :             if (targetm.atomic_test_and_set_trueval != 1
     675                 :          8 :                 || !useless_type_conversion_p (TREE_TYPE (lhs),
     676                 :          4 :                                                TREE_TYPE (t)))
     677                 :            :               {
     678                 :          4 :                 tree new_lhs = make_ssa_name (TREE_TYPE (t));
     679                 :          4 :                 gimple_call_set_lhs (stmt, new_lhs);
     680                 :          4 :                 if (targetm.atomic_test_and_set_trueval != 1)
     681                 :          0 :                   g = gimple_build_assign (lhs, NE_EXPR, new_lhs,
     682                 :          0 :                                            build_int_cst (TREE_TYPE (t), 0));
     683                 :            :                 else
     684                 :          4 :                   g = gimple_build_assign (lhs, NOP_EXPR, new_lhs);
     685                 :          4 :                 gsi_insert_after (gsi, g, GSI_NEW_STMT);
     686                 :          4 :                 update_stmt (stmt);
     687                 :            :               }
     688                 :          4 :             return;
     689                 :          0 :           default:
     690                 :          0 :             continue;
     691                 :            :           }
     692                 :            :       }
     693                 :            : }
     694                 :            : 
     695                 :            : /* Instruments the gimple pointed to by GSI. Return
     696                 :            :    true if func entry/exit should be instrumented.  */
     697                 :            : 
     698                 :            : static bool
     699                 :       6188 : instrument_gimple (gimple_stmt_iterator *gsi)
     700                 :            : {
     701                 :       6188 :   gimple *stmt;
     702                 :       6188 :   tree rhs, lhs;
     703                 :       6188 :   bool instrumented = false;
     704                 :            : 
     705                 :       6188 :   stmt = gsi_stmt (*gsi);
     706                 :       6188 :   if (is_gimple_call (stmt)
     707                 :       6188 :       && (gimple_call_fndecl (stmt)
     708                 :       1371 :           != builtin_decl_implicit (BUILT_IN_TSAN_INIT)))
     709                 :            :     {
     710                 :            :       /* All functions with function call will have exit instrumented,
     711                 :            :          therefore no function calls other than __tsan_func_exit
     712                 :            :          shall appear in the functions.  */
     713                 :       1184 :       gimple_call_set_tail (as_a <gcall *> (stmt), false);
     714                 :       1184 :       if (gimple_call_builtin_p (stmt, BUILT_IN_NORMAL))
     715                 :         50 :         instrument_builtin_call (gsi);
     716                 :       1184 :       return true;
     717                 :            :     }
     718                 :       5004 :   else if (is_gimple_assign (stmt)
     719                 :       5004 :            && !gimple_clobber_p (stmt))
     720                 :            :     {
     721                 :       1364 :       if (gimple_store_p (stmt))
     722                 :            :         {
     723                 :        270 :           lhs = gimple_assign_lhs (stmt);
     724                 :        270 :           instrumented = instrument_expr (*gsi, lhs, true);
     725                 :            :         }
     726                 :       1364 :       if (gimple_assign_load_p (stmt))
     727                 :            :         {
     728                 :        491 :           rhs = gimple_assign_rhs1 (stmt);
     729                 :        491 :           instrumented = instrument_expr (*gsi, rhs, false);
     730                 :            :         }
     731                 :            :     }
     732                 :            :   return instrumented;
     733                 :            : }
     734                 :            : 
     735                 :            : /* Replace TSAN_FUNC_EXIT internal call with function exit tsan builtin.  */
     736                 :            : 
     737                 :            : static void
     738                 :        541 : replace_func_exit (gimple *stmt)
     739                 :            : {
     740                 :        541 :   tree builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
     741                 :        541 :   gimple *g = gimple_build_call (builtin_decl, 0);
     742                 :        541 :   gimple_set_location (g, cfun->function_end_locus);
     743                 :        541 :   gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
     744                 :        541 :   gsi_replace (&gsi, g, true);
     745                 :        541 : }
     746                 :            : 
     747                 :            : /* Instrument function exit.  Used when TSAN_FUNC_EXIT does not exist.  */
     748                 :            : 
     749                 :            : static void
     750                 :          3 : instrument_func_exit (void)
     751                 :            : {
     752                 :          3 :   location_t loc;
     753                 :          3 :   basic_block exit_bb;
     754                 :          3 :   gimple_stmt_iterator gsi;
     755                 :          3 :   gimple *stmt, *g;
     756                 :          3 :   tree builtin_decl;
     757                 :          3 :   edge e;
     758                 :          3 :   edge_iterator ei;
     759                 :            : 
     760                 :            :   /* Find all function exits.  */
     761                 :          3 :   exit_bb = EXIT_BLOCK_PTR_FOR_FN (cfun);
     762                 :          6 :   FOR_EACH_EDGE (e, ei, exit_bb->preds)
     763                 :            :     {
     764                 :          3 :       gsi = gsi_last_bb (e->src);
     765                 :          3 :       stmt = gsi_stmt (gsi);
     766                 :          3 :       gcc_assert (gimple_code (stmt) == GIMPLE_RETURN
     767                 :            :                   || gimple_call_builtin_p (stmt, BUILT_IN_RETURN));
     768                 :          3 :       loc = gimple_location (stmt);
     769                 :          3 :       builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_EXIT);
     770                 :          3 :       g = gimple_build_call (builtin_decl, 0);
     771                 :          3 :       gimple_set_location (g, loc);
     772                 :          3 :       gsi_insert_before (&gsi, g, GSI_SAME_STMT);
     773                 :            :     }
     774                 :          3 : }
     775                 :            : 
     776                 :            : /* Instruments all interesting memory accesses in the current function.
     777                 :            :    Return true if func entry/exit should be instrumented.  */
     778                 :            : 
     779                 :            : static bool
     780                 :        713 : instrument_memory_accesses (bool *cfg_changed)
     781                 :            : {
     782                 :        713 :   basic_block bb;
     783                 :        713 :   gimple_stmt_iterator gsi;
     784                 :        713 :   bool fentry_exit_instrument = false;
     785                 :        713 :   bool func_exit_seen = false;
     786                 :        713 :   auto_vec<gimple *> tsan_func_exits;
     787                 :            : 
     788                 :       2497 :   FOR_EACH_BB_FN (bb, cfun)
     789                 :            :     {
     790                 :      10582 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     791                 :            :         {
     792                 :       7014 :           gimple *stmt = gsi_stmt (gsi);
     793                 :       7014 :           if (gimple_call_internal_p (stmt, IFN_TSAN_FUNC_EXIT))
     794                 :            :             {
     795                 :        826 :               if (fentry_exit_instrument)
     796                 :        539 :                 replace_func_exit (stmt);
     797                 :            :               else
     798                 :        287 :                 tsan_func_exits.safe_push (stmt);
     799                 :            :               func_exit_seen = true;
     800                 :            :             }
     801                 :            :           else
     802                 :       6188 :             fentry_exit_instrument |= instrument_gimple (&gsi);
     803                 :            :         }
     804                 :       1784 :       if (gimple_purge_dead_eh_edges (bb))
     805                 :          2 :         *cfg_changed = true;
     806                 :            :     }
     807                 :            :   unsigned int i;
     808                 :            :   gimple *stmt;
     809                 :       1000 :   FOR_EACH_VEC_ELT (tsan_func_exits, i, stmt)
     810                 :        287 :     if (fentry_exit_instrument)
     811                 :          2 :       replace_func_exit (stmt);
     812                 :            :     else
     813                 :            :       {
     814                 :        285 :         gsi = gsi_for_stmt (stmt);
     815                 :        285 :         gsi_remove (&gsi, true);
     816                 :            :       }
     817                 :        713 :   if (fentry_exit_instrument && !func_exit_seen)
     818                 :          3 :     instrument_func_exit ();
     819                 :        713 :   return fentry_exit_instrument;
     820                 :            : }
     821                 :            : 
     822                 :            : /* Instruments function entry.  */
     823                 :            : 
     824                 :            : static void
     825                 :        425 : instrument_func_entry (void)
     826                 :            : {
     827                 :        425 :   tree ret_addr, builtin_decl;
     828                 :        425 :   gimple *g;
     829                 :        425 :   gimple_seq seq = NULL;
     830                 :            : 
     831                 :        425 :   builtin_decl = builtin_decl_implicit (BUILT_IN_RETURN_ADDRESS);
     832                 :        425 :   g = gimple_build_call (builtin_decl, 1, integer_zero_node);
     833                 :        425 :   ret_addr = make_ssa_name (ptr_type_node);
     834                 :        425 :   gimple_call_set_lhs (g, ret_addr);
     835                 :        425 :   gimple_set_location (g, cfun->function_start_locus);
     836                 :        425 :   gimple_seq_add_stmt_without_update (&seq, g);
     837                 :            : 
     838                 :        425 :   builtin_decl = builtin_decl_implicit (BUILT_IN_TSAN_FUNC_ENTRY);
     839                 :        425 :   g = gimple_build_call (builtin_decl, 1, ret_addr);
     840                 :        425 :   gimple_set_location (g, cfun->function_start_locus);
     841                 :        425 :   gimple_seq_add_stmt_without_update (&seq, g);
     842                 :            : 
     843                 :        425 :   edge e = single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun));
     844                 :        425 :   gsi_insert_seq_on_edge_immediate (e, seq);
     845                 :        425 : }
     846                 :            : 
     847                 :            : /* ThreadSanitizer instrumentation pass.  */
     848                 :            : 
     849                 :            : static unsigned
     850                 :        713 : tsan_pass (void)
     851                 :            : {
     852                 :        713 :   initialize_sanitizer_builtins ();
     853                 :        713 :   bool cfg_changed = false;
     854                 :        713 :   if (instrument_memory_accesses (&cfg_changed))
     855                 :        425 :     instrument_func_entry ();
     856                 :        713 :   return cfg_changed ? TODO_cleanup_cfg : 0;
     857                 :            : }
     858                 :            : 
     859                 :            : /* Inserts __tsan_init () into the list of CTORs.  */
     860                 :            : 
     861                 :            : void
     862                 :        187 : tsan_finish_file (void)
     863                 :            : {
     864                 :        187 :   tree ctor_statements = NULL_TREE;
     865                 :            : 
     866                 :        187 :   initialize_sanitizer_builtins ();
     867                 :        187 :   tree init_decl = builtin_decl_implicit (BUILT_IN_TSAN_INIT);
     868                 :        187 :   append_to_statement_list (build_call_expr (init_decl, 0),
     869                 :            :                             &ctor_statements);
     870                 :        187 :   cgraph_build_static_cdtor ('I', ctor_statements,
     871                 :            :                              MAX_RESERVED_INIT_PRIORITY - 1);
     872                 :        187 : }
     873                 :            : 
     874                 :            : /* The pass descriptor.  */
     875                 :            : 
     876                 :            : namespace {
     877                 :            : 
     878                 :            : const pass_data pass_data_tsan =
     879                 :            : {
     880                 :            :   GIMPLE_PASS, /* type */
     881                 :            :   "tsan", /* name */
     882                 :            :   OPTGROUP_NONE, /* optinfo_flags */
     883                 :            :   TV_NONE, /* tv_id */
     884                 :            :   ( PROP_ssa | PROP_cfg ), /* properties_required */
     885                 :            :   0, /* properties_provided */
     886                 :            :   0, /* properties_destroyed */
     887                 :            :   0, /* todo_flags_start */
     888                 :            :   TODO_update_ssa, /* todo_flags_finish */
     889                 :            : };
     890                 :            : 
     891                 :            : class pass_tsan : public gimple_opt_pass
     892                 :            : {
     893                 :            : public:
     894                 :     401546 :   pass_tsan (gcc::context *ctxt)
     895                 :     803092 :     : gimple_opt_pass (pass_data_tsan, ctxt)
     896                 :            :   {}
     897                 :            : 
     898                 :            :   /* opt_pass methods: */
     899                 :     200773 :   opt_pass * clone () { return new pass_tsan (m_ctxt); }
     900                 :     688738 :   virtual bool gate (function *)
     901                 :            : {
     902                 :     688738 :   return sanitize_flags_p (SANITIZE_THREAD);
     903                 :            : }
     904                 :            : 
     905                 :        297 :   virtual unsigned int execute (function *) { return tsan_pass (); }
     906                 :            : 
     907                 :            : }; // class pass_tsan
     908                 :            : 
     909                 :            : } // anon namespace
     910                 :            : 
     911                 :            : gimple_opt_pass *
     912                 :     200773 : make_pass_tsan (gcc::context *ctxt)
     913                 :            : {
     914                 :     200773 :   return new pass_tsan (ctxt);
     915                 :            : }
     916                 :            : 
     917                 :            : namespace {
     918                 :            : 
     919                 :            : const pass_data pass_data_tsan_O0 =
     920                 :            : {
     921                 :            :   GIMPLE_PASS, /* type */
     922                 :            :   "tsan0", /* name */
     923                 :            :   OPTGROUP_NONE, /* optinfo_flags */
     924                 :            :   TV_NONE, /* tv_id */
     925                 :            :   ( PROP_ssa | PROP_cfg ), /* properties_required */
     926                 :            :   0, /* properties_provided */
     927                 :            :   0, /* properties_destroyed */
     928                 :            :   0, /* todo_flags_start */
     929                 :            :   TODO_update_ssa, /* todo_flags_finish */
     930                 :            : };
     931                 :            : 
     932                 :            : class pass_tsan_O0 : public gimple_opt_pass
     933                 :            : {
     934                 :            : public:
     935                 :     200773 :   pass_tsan_O0 (gcc::context *ctxt)
     936                 :     401546 :     : gimple_opt_pass (pass_data_tsan_O0, ctxt)
     937                 :            :   {}
     938                 :            : 
     939                 :            :   /* opt_pass methods: */
     940                 :     944512 :   virtual bool gate (function *)
     941                 :            :     {
     942                 :     944512 :       return (sanitize_flags_p (SANITIZE_THREAD) && !optimize);
     943                 :            :     }
     944                 :            : 
     945                 :        416 :   virtual unsigned int execute (function *) { return tsan_pass (); }
     946                 :            : 
     947                 :            : }; // class pass_tsan_O0
     948                 :            : 
     949                 :            : } // anon namespace
     950                 :            : 
     951                 :            : gimple_opt_pass *
     952                 :     200773 : make_pass_tsan_O0 (gcc::context *ctxt)
     953                 :            : {
     954                 :     200773 :   return new pass_tsan_O0 (ctxt);
     955                 :            : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.