This introduces the atomic operation intrinsics into the documentation. This is

a preview for the intrinsics that are going to be implemented over the next few 
weeks.

llvm-svn: 40115
This commit is contained in:
Chandler Carruth 2007-07-20 19:34:37 +00:00
parent 74f833bce1
commit 6a5f6bf685
1 changed files with 305 additions and 0 deletions

View File

@ -191,6 +191,15 @@
</li>
<li><a href="#int_debugger">Debugger intrinsics</a></li>
<li><a href="#int_eh">Exception Handling intrinsics</a></li>
<li><a href="#int_atomics">Atomic Operations and Synchronization Intrinsics</a>
<ol>
<li><a href="#int_lcs">'<tt>llvm.atomic.lcs.*</tt>' Intrinsic</a></li>
<li><a href="#int_ls">'<tt>llvm.atomic.ls.*</tt>' Intrinsic</a></li>
<li><a href="#int_las">'<tt>llvm.atomic.las.*</tt>' Intrinsic</a></li>
<li><a href="#int_lss">'<tt>llvm.atomic.lss.*</tt>' Intrinsic</a></li>
<li><a href="#int_memory_barrier">'<tt>llvm.memory.barrier</tt>' Intrinsic</a></li>
</ol>
</li>
<li><a href="#int_general">General intrinsics</a></li>
<ol>
<li><a href="#int_var_annotation">'<tt>llvm.var.annotation</tt>'
@ -4820,6 +4829,302 @@ href="ExceptionHandling.html#format_common_intrinsics">LLVM Exception
Handling</a> document. </p>
</div>
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="int_atomics">Atomic Operations and Synchronization Intrinsics</a>
</div>
<div class="doc_text">
<p>
These intrinsic functions expand the "universal IR" of LLVM to represent
hardware constructs for atomic operations and memory synchronization. This
provides an interface to the hardware, not an interface to the programmer. It
is aimed at a low enough level to allow any programming models or APIs which
need atomic behaviors to map cleanly onto it. It is also modeled primarily on
hardware behavior. Just as hardware provides a "unviresal IR" for source
languages, it also provides a starting point for developing a "universal"
atomic operation and synchronization IR.
</p>
<p>
These do <em>not</em> form an API such as high-level threading libraries,
software transaction memory systems, atomic primitives, and intrinsic
functionss as found in BSD, GNU libc, atomic_ops, APR, and other system and
application libraries. The hardware interface provided by LLVM should allow
a clean implementation of all of these APIs and parallel programming models.
No one model or paradigm should be selected above others unless the hardware
itself ubiquitously does so.
</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="int_lcs">'<tt>llvm.atomic.lcs.*</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<p>
This is an overloaded intrinsic. You can use <tt>llvm.atomic.lcs</tt> on any
integer bit width. Not all targets support all bit widths however.
<pre>
declare i8 @llvm.atomic.lcs.i8.i8p.i8.i8( i8* &lt;ptr&gt;, i8 &lt;cmp&gt;, i8 &lt;val&gt; )
declare i16 @llvm.atomic.lcs.i16.i16p.i16.i16( i16* &lt;ptr&gt;, i16 &lt;cmp&gt;, i16 &lt;val&gt; )
declare i32 @llvm.atomic.lcs.i32.i32p.i32.i32( i32* &lt;ptr&gt;, i32 &lt;cmp&gt;, i32 &lt;val&gt; )
declare i64 @llvm.atomic.lcs.i64.i64p.i64.i64( i64* &lt;ptr&gt;, i64 &lt;cmp&gt;, i64 &lt;val&gt; )
</pre>
</p>
<h5>Overview:</h5>
<p>
This loads a value in shared memory and compares it to a given value. If they
are equal, it stores a new value into the shared memory.
</p>
<h5>Arguments:</h5>
<p>
The <tt>llvm.atomic.lcs</tt> intrinsic takes three arguments. The result as
well as both <tt>cmp</tt> and <tt>val</tt> must be integer values with the
same bit width. The <tt>ptr</tt> argument must be a pointer to a value of
this integer type. While any bit width integer may be used, targets may only
lower representations they support in hardware.
</p>
<h5>Semantics:</h5>
<p>
This entire intrinsic must be executed atomically. It first loads the value
in shared memory pointed to by <tt>ptr</tt> and compares it with the value
<tt>cmp</tt>. If they are equal, <tt>val</tt> is stored into the shared
memory. The loaded value is yielded in all cases. This provides the
equivalent of an atomic compare-and-swap operation within the SSA framework.
</p>
<h5>Examples:</h5>
<pre>
%ptr = malloc i32
store i32 4, %ptr
%val1 = add i32 4, 4
%result1 = call i32 @llvm.atomic.lcs( i32* %ptr, i32 4, %val1 )
<i>; yields {i32}:result1 = 4</i>
%stored1 = icmp eq i32 %result1, 4 <i>; yields {i1}:stored1 = true</i>
%memval1 = load i32* %ptr <i>; yields {i32}:memval1 = 8</i>
%val2 = add i32 1, 1
%result2 = call i32 @llvm.atomic.lcs( i32* %ptr, i32 5, %val2 )
<i>; yields {i32}:result2 = 8</i>
%stored2 = icmp eq i32 %result2, 5 <i>; yields {i1}:stored2 = false</i>
%memval2 = load i32* %ptr <i>; yields {i32}:memval2 = 8</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="int_ls">'<tt>llvm.atomic.ls.*</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<p>
This is an overloaded intrinsic. You can use <tt>llvm.atomic.ls</tt> on any
integer bit width. Not all targets support all bit widths however.
<pre>
declare i8 @llvm.atomic.ls.i8.i8p.i8( i8* &lt;ptr&gt;, i8 &lt;val&gt; )
declare i16 @llvm.atomic.ls.i16.i16p.i16( i16* &lt;ptr&gt;, i16 &lt;val&gt; )
declare i32 @llvm.atomic.ls.i32.i32p.i32( i32* &lt;ptr&gt;, i32 &lt;val&gt; )
declare i64 @llvm.atomic.ls.i64.i64p.i64( i64* &lt;ptr&gt;, i64 &lt;val&gt; )
</pre>
</p>
<h5>Overview:</h5>
<p>
This intrinsic loads the value stored in shared memory at <tt>ptr</tt> and
yields the value from memory. It then stores the value in <tt>val</tt> in the
shared memory at <tt>ptr</tt>.
</p>
<h5>Arguments:</h5>
<p>
The <tt>llvm.atomic.ls</tt> intrinsic takes two arguments. Both the
<tt>val</tt> argument and the result must be integers of the same bit width.
The first argument, <tt>ptr</tt>, must be a pointer to a value of this
integer type. The targets may only lower integer representations they
support.
</p>
<h5>Semantics:</h5>
<p>
This intrinsic loads the value pointed to by <tt>ptr</tt>, yields it, and
stores <tt>val</tt> back into <tt>ptr</tt> atomically. This provides the
equivalent of an atomic swap operation within the SSA framework.
</p>
<h5>Examples:</h5>
<pre>
%ptr = malloc i32
store i32 4, %ptr
%val1 = add i32 4, 4
%result1 = call i32 @llvm.atomic.ls( i32* %ptr, i32 %val1 )
<i>; yields {i32}:result1 = 4</i>
%stored1 = icmp eq i32 %result1, 4 <i>; yields {i1}:stored1 = true</i>
%memval1 = load i32* %ptr <i>; yields {i32}:memval1 = 8</i>
%val2 = add i32 1, 1
%result2 = call i32 @llvm.atomic.ls( i32* %ptr, i32 %val2 )
<i>; yields {i32}:result2 = 8</i>
%stored2 = icmp eq i32 %result2, 8 <i>; yields {i1}:stored2 = true</i>
%memval2 = load i32* %ptr <i>; yields {i32}:memval2 = 2</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="int_las">'<tt>llvm.atomic.las.*</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<p>
This is an overloaded intrinsic. You can use <tt>llvm.atomic.las</tt> on any
integer bit width. Not all targets support all bit widths however.
<pre>
declare i8 @llvm.atomic.las.i8.i8p.i8( i8* &lt;ptr&gt;, i8 &lt;delta&gt; )
declare i16 @llvm.atomic.las.i16.i16p.i16( i16* &lt;ptr&gt;, i16 &lt;delta&gt; )
declare i32 @llvm.atomic.las.i32.i32p.i32( i32* &lt;ptr&gt;, i32 &lt;delta&gt; )
declare i64 @llvm.atomic.las.i64.i64p.i64( i64* &lt;ptr&gt;, i64 &lt;delta&gt; )
</pre>
</p>
<h5>Overview:</h5>
<p>
This intrinsic adds <tt>delta</tt> to the value stored in shared memory at
<tt>ptr</tt>. It yields the original value at <tt>ptr</tt>.
</p>
<h5>Arguments:</h5>
<p>
The intrinsic takes two arguments, the first a pointer to an integer value
and the second an integer value. The result is also an integer value. These
integer types can have any bit width, but they must all have the same bit
width. The targets may only lower integer representations they support.
</p>
<h5>Semantics:</h5>
<p>
This intrinsic does a series of operations atomically. It first loads the
value stored at <tt>ptr</tt>. It then adds <tt>delta</tt>, stores the result
to <tt>ptr</tt>. It yields the original value stored at <tt>ptr</tt>.
</p>
<h5>Examples:</h5>
<pre>
%ptr = malloc i32
store i32 4, %ptr
%result1 = call i32 @llvm.atomic.las( i32* %ptr, i32 4 )
<i>; yields {i32}:result1 = 4</i>
%result2 = call i32 @llvm.atomic.las( i32* %ptr, i32 2 )
<i>; yields {i32}:result2 = 8</i>
%result3 = call i32 @llvm.atomic.las( i32* %ptr, i32 5 )
<i>; yields {i32}:result3 = 10</i>
%memval = load i32* %ptr <i>; yields {i32}:memval1 = 15</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="int_lss">'<tt>llvm.atomic.lss.*</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<p>
This is an overloaded intrinsic. You can use <tt>llvm.atomic.lss</tt> on any
integer bit width. Not all targets support all bit widths however.
<pre>
declare i8 @llvm.atomic.lss.i8.i8.i8( i8* &lt;ptr&gt;, i8 &lt;delta&gt; )
declare i16 @llvm.atomic.lss.i16.i16.i16( i16* &lt;ptr&gt;, i16 &lt;delta&gt; )
declare i32 @llvm.atomic.lss.i32.i32.i32( i32* &lt;ptr&gt;, i32 &lt;delta&gt; )
declare i64 @llvm.atomic.lss.i64.i64.i64( i64* &lt;ptr&gt;, i64 &lt;delta&gt; )
</pre>
</p>
<h5>Overview:</h5>
<p>
This intrinsic subtracts <tt>delta</tt> from the value stored in shared
memory at <tt>ptr</tt>. It yields the original value at <tt>ptr</tt>.
</p>
<h5>Arguments:</h5>
<p>
The intrinsic takes two arguments, the first a pointer to an integer value
and the second an integer value. The result is also an integer value. These
integer types can have any bit width, but they must all have the same bit
width. The targets may only lower integer representations they support.
</p>
<h5>Semantics:</h5>
<p>
This intrinsic does a series of operations atomically. It first loads the
value stored at <tt>ptr</tt>. It then subtracts <tt>delta</tt>,
stores the result to <tt>ptr</tt>. It yields the original value stored
at <tt>ptr</tt>.
</p>
<h5>Examples:</h5>
<pre>
%ptr = malloc i32
store i32 32, %ptr
%result1 = call i32 @llvm.atomic.lss( i32* %ptr, i32 4 )
<i>; yields {i32}:result1 = 32</i>
%result2 = call i32 @llvm.atomic.lss( i32* %ptr, i32 2 )
<i>; yields {i32}:result2 = 28</i>
%result3 = call i32 @llvm.atomic.lss( i32* %ptr, i32 5 )
<i>; yields {i32}:result3 = 26</i>
%memval = load i32* %ptr <i>; yields {i32}:memval1 = 21</i>
</pre>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
<a name="int_memory_barrier">'<tt>llvm.memory.barrier</tt>' Intrinsic</a>
</div>
<div class="doc_text">
<h5>Syntax:</h5>
<p>
<pre>
declare void @llvm.memory.barrier( i1 &lt;ll&gt;, i1 &lt;ls&gt;, i1 &lt;sl&gt;, i1 &lt;ss&gt; )
</pre>
</p>
<h5>Overview:</h5>
<p>
The <tt>llvm.memory.barrier</tt> intrinsic guarantees ordering between
specific pairs of memory access types.
</p>
<h5>Arguments:</h5>
<p>
The <tt>llvm.memory.barrier</tt> intrinsic requires four boolean arguments.
Each argument enables a specific barrier as listed below.
<ul>
<li><tt>ll</tt>: load-load barrier</li>
<li><tt>ls</tt>: load-store barrier</li>
<li><tt>sl</tt>: store-load barrier</li>
<li><tt>ss</tt>: store-store barrier</li>
</ul>
</p>
<h5>Semantics:</h5>
<p>
This intrinsic causes the system to enforce some ordering constraints upon
the loads and stores of the program. This barrier does not indicate
<em>when</em> any events will occur, it only enforces an <em>order</em> in
which they occur. For any of the specified pairs of load and store operations
(f.ex. load-load, or store-load), all of the first operations preceding the
barrier will complete before any of the second operations succeeding the
barrier begin. Specifically the semantics for each pairing is as follows:
<ul>
<li><tt>ll</tt>: All loads before the barrier must complete before any load
after the barrier begins.</li>
<li><tt>ls</tt>: All loads before the barrier must complete before any
store after the barrier begins.</li>
<li><tt>ss</tt>: All stores before the barrier must complete before any
store after the barrier begins.</li>
<li><tt>sl</tt>: All stores before the barrier must complete before any
load after the barrier begins.</li>
</ul>
These semantics are applied with a logical "and" behavior when more than one
is enabled in a single memory barrier intrinsic.
</p>
<h5>Example:</h5>
<pre>
%ptr = malloc i32
store i32 4, %ptr
%result1 = load i32* %ptr <i>; yields {i32}:result1 = 4</i>
call void @llvm.memory.barrier( i1 false, i1 true, i1 false, i1 false )
<i>; guarantee the above finishes</i>
store i32 8, %ptr <i>; before this begins</i>
</pre>
</div>
<!-- ======================================================================= -->
<div class="doc_subsection">
<a name="int_general">General Intrinsics</a>