add a __sync_swap builtin to fill out the rest of the __sync builtins.

Patch by Dave Zarzycki!


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129189 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2011-04-09 03:57:26 +00:00
Родитель 1246ba6f68
Коммит 23aa9c8ca0
5 изменённых файлов: 55 добавлений и 1 удалений

Просмотреть файл

@ -56,6 +56,7 @@ td {
<ul>
<li><a href="#__builtin_shufflevector">__builtin_shufflevector</a></li>
<li><a href="#__builtin_unreachable">__builtin_unreachable</a></li>
<li><a href="#__sync_swap">__sync_swap</a></li>
</ul>
</li>
<li><a href="#targetspecific">Target-Specific Extensions</a>
@ -711,6 +712,36 @@ no arguments and produces a void result.
<p>Query for this feature with __has_builtin(__builtin_unreachable).</p>
<!-- ======================================================================= -->
<h3 id="__sync_swap">__sync_swap</h3>
<!-- ======================================================================= -->
<p><tt>__sync_swap</tt> is used to atomically swap integers or pointers in
memory.
</p>
<p><b>Syntax:</b></p>
<pre>
<i>type</i> __sync_swap(<i>type</i> *ptr, <i>type</i> value, ...)
</pre>
<p><b>Example of Use:</b></p>
<pre>
int old_value = __sync_swap(&value, new_value);
</pre>
<p><b>Description:</b></p>
<p>The __sync_swap() builtin extends the existing __sync_*() family of atomic
intrinsics to allow code to atomically swap the current value with the new
value. More importantly, it helps developers write more efficient and correct
code by avoiding expensive loops around __sync_bool_compare_and_swap() or
relying on the platform specific implementation details of
__sync_lock_test_and_set(). The __sync_swap() builtin is a full barrier.
</p>
<!-- ======================================================================= -->
<h2 id="targetspecific">Target-Specific Extensions</h2>

Просмотреть файл

@ -577,6 +577,13 @@ BUILTIN(__sync_lock_release_4, "viD*.", "n")
BUILTIN(__sync_lock_release_8, "vLLiD*.", "n")
BUILTIN(__sync_lock_release_16, "vLLLiD*.", "n")
BUILTIN(__sync_swap, "v.", "")
BUILTIN(__sync_swap_1, "ccD*c.", "n")
BUILTIN(__sync_swap_2, "ssD*s.", "n")
BUILTIN(__sync_swap_4, "iiD*i.", "n")
BUILTIN(__sync_swap_8, "LLiLLiD*LLi.", "n")
BUILTIN(__sync_swap_16, "LLLiLLLiD*LLLi.", "n")
// Non-overloaded atomic builtins.

Просмотреть файл

@ -721,6 +721,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_release:
case Builtin::BI__sync_swap:
assert(0 && "Shouldn't make it through sema");
case Builtin::BI__sync_fetch_and_add_1:
case Builtin::BI__sync_fetch_and_add_2:
@ -860,6 +861,13 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
return RValue::get(Result);
}
case Builtin::BI__sync_swap_1:
case Builtin::BI__sync_swap_2:
case Builtin::BI__sync_swap_4:
case Builtin::BI__sync_swap_8:
case Builtin::BI__sync_swap_16:
return EmitBinaryAtomic(*this, Intrinsic::atomic_swap, E);
case Builtin::BI__sync_lock_test_and_set_1:
case Builtin::BI__sync_lock_test_and_set_2:
case Builtin::BI__sync_lock_test_and_set_4:

Просмотреть файл

@ -180,6 +180,7 @@ Sema::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
case Builtin::BI__sync_bool_compare_and_swap:
case Builtin::BI__sync_lock_test_and_set:
case Builtin::BI__sync_lock_release:
case Builtin::BI__sync_swap:
return SemaBuiltinAtomicOverloaded(move(TheCallResult));
}
@ -415,7 +416,8 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
BUILTIN_ROW(__sync_val_compare_and_swap),
BUILTIN_ROW(__sync_bool_compare_and_swap),
BUILTIN_ROW(__sync_lock_test_and_set),
BUILTIN_ROW(__sync_lock_release)
BUILTIN_ROW(__sync_lock_release),
BUILTIN_ROW(__sync_swap)
};
#undef BUILTIN_ROW
@ -468,6 +470,7 @@ Sema::SemaBuiltinAtomicOverloaded(ExprResult TheCallResult) {
NumFixed = 0;
ResultType = Context.VoidTy;
break;
case Builtin::BI__sync_swap: BuiltinIndex = 14; break;
}
// Now that we know how many fixed arguments we expect, first check that we

Просмотреть файл

@ -44,6 +44,11 @@ int atomic(void) {
// CHECK: call i32 @llvm.atomic.swap.i32.p0i32(i32* %val, i32 7)
// CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
old = __sync_swap(&val, 8);
// CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
// CHECK: call i32 @llvm.atomic.swap.i32.p0i32(i32* %val, i32 8)
// CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
old = __sync_val_compare_and_swap(&val, 4, 1976);
// CHECK: call void @llvm.memory.barrier(i1 true, i1 true, i1 true, i1 true, i1 true)
// CHECK: call i32 @llvm.atomic.cmp.swap.i32.p0i32(i32* %val, i32 4, i32 1976)