diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -47,6 +47,14 @@ BUILTIN(__builtin_ppc_icbt, "vv*", "") BUILTIN(__builtin_ppc_compare_and_swap, "iiD*i*i", "") BUILTIN(__builtin_ppc_compare_and_swaplp, "iLiD*Li*Li", "") +BUILTIN(__builtin_ppc_fetch_and_add, "UiUiD*Ui", "") +BUILTIN(__builtin_ppc_fetch_and_addlp, "ULiULiD*ULi", "") +BUILTIN(__builtin_ppc_fetch_and_and, "UiUiD*Ui", "") +BUILTIN(__builtin_ppc_fetch_and_andlp, "ULiULiD*ULi", "") +BUILTIN(__builtin_ppc_fetch_and_or, "UiUiD*Ui", "") +BUILTIN(__builtin_ppc_fetch_and_orlp, "ULiULiD*ULi", "") +BUILTIN(__builtin_ppc_fetch_and_swap, "UiUiD*Ui", "") +BUILTIN(__builtin_ppc_fetch_and_swaplp, "ULiULiD*ULi", "") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -100,6 +100,14 @@ Builder.defineMacro("__compare_and_swap", "__builtin_ppc_compare_and_swap"); Builder.defineMacro("__compare_and_swaplp", "__builtin_ppc_compare_and_swaplp"); + Builder.defineMacro("__fetch_and_add", "__builtin_ppc_fetch_and_add"); + Builder.defineMacro("__fetch_and_addlp", "__builtin_ppc_fetch_and_addlp"); + Builder.defineMacro("__fetch_and_and", "__builtin_ppc_fetch_and_and"); + Builder.defineMacro("__fetch_and_andlp", "__builtin_ppc_fetch_and_andlp"); + Builder.defineMacro("__fetch_and_or", "__builtin_ppc_fetch_and_or"); + Builder.defineMacro("__fetch_and_orlp", "__builtin_ppc_fetch_and_orlp"); + Builder.defineMacro("__fetch_and_swap", "__builtin_ppc_fetch_and_swap"); + Builder.defineMacro("__fetch_and_swaplp", "__builtin_ppc_fetch_and_swaplp"); } /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -15440,6 +15440,27 @@ llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Monotonic, true); return Pair.second; } + case PPC::BI__builtin_ppc_fetch_and_add: + case PPC::BI__builtin_ppc_fetch_and_addlp: { + return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E, + llvm::AtomicOrdering::Monotonic); + } + case PPC::BI__builtin_ppc_fetch_and_and: + case PPC::BI__builtin_ppc_fetch_and_andlp: { + return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E, + llvm::AtomicOrdering::Monotonic); + } + + case PPC::BI__builtin_ppc_fetch_and_or: + case PPC::BI__builtin_ppc_fetch_and_orlp: { + return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E, + llvm::AtomicOrdering::Monotonic); + } + case PPC::BI__builtin_ppc_fetch_and_swap: + case PPC::BI__builtin_ppc_fetch_and_swaplp: { + return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, + llvm::AtomicOrdering::Monotonic); + } } } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-fetch-error.c b/clang/test/CodeGen/builtins-ppc-xlcompat-fetch-error.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-fetch-error.c @@ -0,0 +1,17 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -target-cpu pwr8 \ +// RUN: -verify %s + +void test_builtin_ppc_fetch_and_add2() { + volatile int a = 0; + unsigned int b = 0; + + __fetch_and_add(&a, b); // expected-warning {{passing 'volatile int *' to parameter of type 'volatile unsigned int *' converts between pointers to integer types with different sign}} +} + +void test_builtin_ppc_fetch_and_addlp() { + volatile long a = 0; + unsigned long b = 0; + + __fetch_and_addlp(&a, b); // expected-warning {{passing 'volatile long *' to parameter of type 'volatile unsigned long *' converts between pointers to integer types with different sign}} +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-fetch.c b/clang/test/CodeGen/builtins-ppc-xlcompat-fetch.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-fetch.c @@ -0,0 +1,120 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s + +// CHECK-LABEL: @test_builtin_ppc_fetch_and_add( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_add(unsigned int a, unsigned int b) { + __fetch_and_add(&a, b); +} + +// CHECK-LABEL: @test_builtin_ppc_fetch_and_addlp( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 +// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_addlp(unsigned long a, unsigned long b) { + __fetch_and_addlp(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_and( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_and(unsigned int a, unsigned int b) { + __fetch_and_and(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_andlp( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 +// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_andlp(unsigned long a, unsigned long b) { + __fetch_and_andlp(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_or( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_or(unsigned int a, unsigned int b) { + __fetch_and_or(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_orlp( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 +// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_orlp(unsigned long a, unsigned long b) { + __fetch_and_orlp(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_swap( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4 +// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xchg i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_swap(unsigned int a, unsigned int b) { + __fetch_and_swap(&a, b); +} +// CHECK-LABEL: @test_builtin_ppc_fetch_and_swaplp( +// CHECK-NEXT: entry: +// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8 +// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8 +// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8 +// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xchg i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8 +// CHECK-NEXT: ret void +// +void test_builtin_ppc_fetch_and_swaplp(unsigned long a, unsigned long b) { + __fetch_and_swaplp(&a, b); +}