From: Chris Lattner Date: Sat, 9 Apr 2011 03:57:26 +0000 (+0000) Subject: add a __sync_swap builtin to fill out the rest of the __sync builtins. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=23aa9c8ca0bc441aab2a38a4c9fc7a1c9e9ac16a;p=clang 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 --- diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index 1cd77a1791..b16c38c768 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -56,6 +56,7 @@ td {
  • Target-Specific Extensions @@ -711,6 +712,36 @@ no arguments and produces a void result.

    Query for this feature with __has_builtin(__builtin_unreachable).

    + +

    __sync_swap

    + + +

    __sync_swap is used to atomically swap integers or pointers in +memory. +

    + +

    Syntax:

    + +
    +type __sync_swap(type *ptr, type value, ...)
    +
    + +

    Example of Use:

    + +
    +int old_value = __sync_swap(&value, new_value);
    +
    + +

    Description:

    + +

    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. +

    +

    Target-Specific Extensions

    diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3f97b787f6..9a4c768dc6 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -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. diff --git a/lib/CodeGen/CGBuiltin.cpp b/lib/CodeGen/CGBuiltin.cpp index 35507b9921..af8d37a221 100644 --- a/lib/CodeGen/CGBuiltin.cpp +++ b/lib/CodeGen/CGBuiltin.cpp @@ -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: diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 105fb52ddb..e1adfd4839 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -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 diff --git a/test/CodeGen/atomic.c b/test/CodeGen/atomic.c index 4a7c13f03c..8ce2d96043 100644 --- a/test/CodeGen/atomic.c +++ b/test/CodeGen/atomic.c @@ -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)