зеркало из https://github.com/microsoft/clang.git
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:
Родитель
1246ba6f68
Коммит
23aa9c8ca0
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче