<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/77521>77521</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            TSan: question regarding early exit in `MemoryAccess` due to `GetIgnoreBit`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          ningvin
      </td>
    </tr>
</table>

<pre>
    TSan supports ignoring certain reads/writes by a begin/end style annotation mechanism. This is e.g. used by [Archer](https://github.com/llvm/llvm-project/blob/47605ffec8864e989905027b2f56277e2dc8b8fa/openmp/tools/archer/ompt-tsan.cpp#L173) to filter out provably race free regions in OpenMP code for the sake of performance.

Calling `AnnotateIgnoreWritesBegin` causes an ignore bit to be set in the current thread's local state, which lies in thread-local storage.

Looking at [`MemoryAccess`](https://github.com/llvm/llvm-project/blob/47605ffec8864e989905027b2f56277e2dc8b8fa/compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp#L420) in the TSan runtime (which as far as I can tell ends up being called for most instrumented reads/writes), I noticed that the "early" exit due to a set ignore bit happens later than I would have expected:

https://github.com/llvm/llvm-project/blob/47605ffec8864e989905027b2f56277e2dc8b8fa/compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp#L432-L442

The ignore bit is only evaluated after the shadow memory has already been loaded and the access has been deemed to not be already recorded.

In other situations ([`MemoryAccess16`](https://github.com/llvm/llvm-project/blob/47605ffec8864e989905027b2f56277e2dc8b8fa/compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp#L458) and [`UnalignedMemoryAccess`](https://github.com/llvm/llvm-project/blob/47605ffec8864e989905027b2f56277e2dc8b8fa/compiler-rt/lib/tsan/rtl/tsan_rtl_access.cpp#L495)), the ignore bit check is performed first thing.

I am curious as to why that is the case. Is access to the thread-local `ThreadState`/`FastState` more expensive than accessing and comparing the shadow memory?
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzUVkuP2zYQ_jX0ZbAGRevlgw_eBCoMJGiBbNFjMCJHEhuKVEnKjv99QSpGst1TL0VzsSGJj5nvRWIIerREJ1Y9s-r9Dtc4OX-y2o5XbXe9U_fTyye0ENZlcT4G0KN1XtsRJPmI2oInVIGJ7uZ1pAD9HRB6GrVloiOrIMS7IUBrXcSonYWZ5IRWh3kPL5MOoAPQftzDGkil6ax6Pns5kWfVeybaKcYlsMOZiY6JbtRxWvu9dDMTnTHXx9_T4t2fJCMTXW9cz0RXNjWvhoFk29YlHdvjkVdcNL0Yqlo0DQkl274dkInOLWTnhYkuOmdSL7jtLzo3L_EpBrR7uSxMHD4UzYGJI0QHgzaRPLg1wuLdFXtzB4-SYPBE4GnUzgbQFn5dyH78DaRTBIPzECeCgF8I3AAL-cH5Ga2kPePvGT9vv-_QmAQyq_l5Q44uCXj6I6P8nPGtOUhcAwVAu_FC0OuYiusJAsW0e9pNrt6TjRCnRBYTTQDjJBoIaWEm3sFt0nICoylsc9K4p8cY53F8Xd4H576k8jAmtljNP9Ls_P0sJYXAav6fMSfdvGhD_smn-Uan6YkuJjofzbeHzz6az5hre9BYCp5o_IZPVrhfbdQzARPthgYGGNCnvwtItBDJGCCrAqwL9JQ9gMaQyqzOLiS8Q_TrTDaS-ocxmDgmoC9gXdSSFMQJY96dCUHozZ0JAfRVR1ArJQ5xo_A7rxMuC9kABpPw4oQWLnBzq1Ew4ZWAvi4kI6kE-Q9k_Z9pOIinD2Upfiz3ZaIfm9YBnDV3oCuaFROuOGztE4QJlbvBnMUHEwZAk1C_Q09kwThUabxVefS2dR6WPyuiOfHgEiXJMY_JnqTzitQryV8suDiRh6DjmoMsJKm8lX9R_xQGqNpkgITN1sLvFk06CtRPZ-Vjlb2V7RVfi0dOJL8kCX3L2eRV7UPynbbja34B5xSU2q0heT46uE33zaU6bDGKgfZwCQ8lRZdfv0pLVvOX_PwpR2vNE2I17zDExxuYU3nJrDboK21G3pbMmWoVJCwwn7JvZM4O3U6dDup4OOKOTkXDy_ZQFodyN53atpKHpi9K7Knph4E3PS-qVhVN2R8HpJ0-CS5KXvCjKLgoyr2sSYpq4GVVc1kca1ZymlGbfaJz7_y40yGsdGqaShQ7gz2ZkO8KQli6Qf7IhEhXB3_KEujXMbCSGx1i-L5K1NFQvkmwwxn-Winkq4CnEb1KfeYE3OJPW3h7ojxCkdX8F4rbWfisI6v5bvXm9K_1mStP6Zw7-zsAAP__hKr3HA">