<head>
<title>LLVM Atomic Instructions and Concurrency Guide</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <link rel="stylesheet" href="llvm.css" type="text/css">
+ <link rel="stylesheet" href="_static/llvm.css" type="text/css">
</head>
<body>
</pre>
<p>However, LLVM is not allowed to transform the former to the latter: it could
- introduce undefined behavior if another thread can access x at the same time.
- (This example is particularly of interest because before the concurrency model
- was implemented, LLVM would perform this transformation.)</p>
+ indirectly introduce undefined behavior if another thread can access x at
+ the same time. (This example is particularly of interest because before the
+ concurrency model was implemented, LLVM would perform this
+ transformation.)</p>
<p>Note that speculative loads are allowed; a load which
is part of a race returns <code>undef</code>, but does not have undefined
<p>In order to achieve a balance between performance and necessary guarantees,
there are six levels of atomicity. They are listed in order of strength;
each level includes all the guarantees of the previous level except for
- Acquire/Release.</p>
+ Acquire/Release. (See also <a href="LangRef.html#ordering">LangRef</a>.)</p>
<!-- ======================================================================= -->
<h3>
<p>NotAtomic is the obvious, a load or store which is not atomic. (This isn't
really a level of atomicity, but is listed here for comparison.) This is
- essentially a regular load or store. If code accesses a memory location
- from multiple threads at the same time, the resulting loads return
- 'undef'.</p>
+ essentially a regular load or store. If there is a race on a given memory
+ location, loads from that location return undef.</p>
<dl>
<dt>Relevant standard</dt>
<dd>This is intended to match shared variables in C/C++, and to be used
in any other context where memory access is necessary, and
- a race is impossible.
+ a race is impossible. (The precise definition is in
+ <a href="LangRef.html#memmodel">LangRef</a>.)
<dt>Notes for frontends</dt>
<dd>The rule is essentially that all memory accessed with basic loads and
stores by multiple threads should be protected by a lock or other
which would make those optimizations useful.</dd>
<dt>Notes for code generation</dt>
<dd>Code generation is essentially the same as that for unordered for loads
- and stores. No fences is required. <code>cmpxchg</code> and
+ and stores. No fences are required. <code>cmpxchg</code> and
<code>atomicrmw</code> are required to appear as a single operation.</dd>
</dl>
SequentiallyConsistent operations may not be reordered.</dd>
<dt>Notes for code generation</dt>
<dd>SequentiallyConsistent loads minimally require the same barriers
- as Acquire operations and SequeuentiallyConsistent stores require
+ as Acquire operations and SequentiallyConsistent stores require
Release barriers. Additionally, the code generator must enforce
- ordering between SequeuentiallyConsistent stores followed by
- SequeuentiallyConsistent loads. This is usually done by emitting
+ ordering between SequentiallyConsistent stores followed by
+ SequentiallyConsistent loads. This is usually done by emitting
either a full fence before the loads or a full fence after the
stores; which is preferred varies by architecture.</dd>
</dl>