Skip to content

Commit eb237ff

Browse files
author
Jinsong Ji
committed
[PowerPC] Add XL Compat fetch builtins
Prototype ``` unsigned int __fetch_and_add (volatile unsigned int* addr, unsigned int val); unsigned long __fetch_and_addlp (volatile unsigned long* addr, unsigned long val); ``` Ref: https://www.ibm.com/docs/en/xl-c-and-cpp-linux/16.1.1?topic=functions-fetch Reviewed By: #powerpc, w2yehia, lkail Differential Revision: https://reviews.llvm.org/D104991
1 parent 0f32d00 commit eb237ff

File tree

5 files changed

+174
-0
lines changed

5 files changed

+174
-0
lines changed

clang/include/clang/Basic/BuiltinsPPC.def

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ BUILTIN(__builtin_ppc_dcbz, "vv*", "")
4747
BUILTIN(__builtin_ppc_icbt, "vv*", "")
4848
BUILTIN(__builtin_ppc_compare_and_swap, "iiD*i*i", "")
4949
BUILTIN(__builtin_ppc_compare_and_swaplp, "iLiD*Li*Li", "")
50+
BUILTIN(__builtin_ppc_fetch_and_add, "UiUiD*Ui", "")
51+
BUILTIN(__builtin_ppc_fetch_and_addlp, "ULiULiD*ULi", "")
52+
BUILTIN(__builtin_ppc_fetch_and_and, "UiUiD*Ui", "")
53+
BUILTIN(__builtin_ppc_fetch_and_andlp, "ULiULiD*ULi", "")
54+
BUILTIN(__builtin_ppc_fetch_and_or, "UiUiD*Ui", "")
55+
BUILTIN(__builtin_ppc_fetch_and_orlp, "ULiULiD*ULi", "")
56+
BUILTIN(__builtin_ppc_fetch_and_swap, "UiUiD*Ui", "")
57+
BUILTIN(__builtin_ppc_fetch_and_swaplp, "ULiULiD*ULi", "")
5058

5159
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")
5260

clang/lib/Basic/Targets/PPC.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,14 @@ static void defineXLCompatMacros(MacroBuilder &Builder) {
100100
Builder.defineMacro("__compare_and_swap", "__builtin_ppc_compare_and_swap");
101101
Builder.defineMacro("__compare_and_swaplp",
102102
"__builtin_ppc_compare_and_swaplp");
103+
Builder.defineMacro("__fetch_and_add", "__builtin_ppc_fetch_and_add");
104+
Builder.defineMacro("__fetch_and_addlp", "__builtin_ppc_fetch_and_addlp");
105+
Builder.defineMacro("__fetch_and_and", "__builtin_ppc_fetch_and_and");
106+
Builder.defineMacro("__fetch_and_andlp", "__builtin_ppc_fetch_and_andlp");
107+
Builder.defineMacro("__fetch_and_or", "__builtin_ppc_fetch_and_or");
108+
Builder.defineMacro("__fetch_and_orlp", "__builtin_ppc_fetch_and_orlp");
109+
Builder.defineMacro("__fetch_and_swap", "__builtin_ppc_fetch_and_swap");
110+
Builder.defineMacro("__fetch_and_swaplp", "__builtin_ppc_fetch_and_swaplp");
103111
}
104112

105113
/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15440,6 +15440,27 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
1544015440
llvm::AtomicOrdering::Monotonic, llvm::AtomicOrdering::Monotonic, true);
1544115441
return Pair.second;
1544215442
}
15443+
case PPC::BI__builtin_ppc_fetch_and_add:
15444+
case PPC::BI__builtin_ppc_fetch_and_addlp: {
15445+
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Add, E,
15446+
llvm::AtomicOrdering::Monotonic);
15447+
}
15448+
case PPC::BI__builtin_ppc_fetch_and_and:
15449+
case PPC::BI__builtin_ppc_fetch_and_andlp: {
15450+
return MakeBinaryAtomicValue(*this, AtomicRMWInst::And, E,
15451+
llvm::AtomicOrdering::Monotonic);
15452+
}
15453+
15454+
case PPC::BI__builtin_ppc_fetch_and_or:
15455+
case PPC::BI__builtin_ppc_fetch_and_orlp: {
15456+
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Or, E,
15457+
llvm::AtomicOrdering::Monotonic);
15458+
}
15459+
case PPC::BI__builtin_ppc_fetch_and_swap:
15460+
case PPC::BI__builtin_ppc_fetch_and_swaplp: {
15461+
return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E,
15462+
llvm::AtomicOrdering::Monotonic);
15463+
}
1544315464
}
1544415465
}
1544515466

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// REQUIRES: powerpc-registered-target
2+
// RUN: %clang_cc1 -triple powerpc64-unknown-aix -target-cpu pwr8 \
3+
// RUN: -verify %s
4+
5+
void test_builtin_ppc_fetch_and_add2() {
6+
volatile int a = 0;
7+
unsigned int b = 0;
8+
9+
__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}}
10+
}
11+
12+
void test_builtin_ppc_fetch_and_addlp() {
13+
volatile long a = 0;
14+
unsigned long b = 0;
15+
16+
__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}}
17+
}
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
2+
// REQUIRES: powerpc-registered-target
3+
// RUN: %clang_cc1 -triple powerpc64-unknown-unknown \
4+
// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s
5+
// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \
6+
// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s
7+
8+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_add(
9+
// CHECK-NEXT: entry:
10+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
11+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
12+
// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
13+
// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4
14+
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4
15+
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4
16+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4
17+
// CHECK-NEXT: ret void
18+
//
19+
void test_builtin_ppc_fetch_and_add(unsigned int a, unsigned int b) {
20+
__fetch_and_add(&a, b);
21+
}
22+
23+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_addlp(
24+
// CHECK-NEXT: entry:
25+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
26+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8
27+
// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8
28+
// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8
29+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8
30+
// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8
31+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw add i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8
32+
// CHECK-NEXT: ret void
33+
//
34+
void test_builtin_ppc_fetch_and_addlp(unsigned long a, unsigned long b) {
35+
__fetch_and_addlp(&a, b);
36+
}
37+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_and(
38+
// CHECK-NEXT: entry:
39+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
40+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
41+
// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
42+
// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4
43+
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4
44+
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4
45+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4
46+
// CHECK-NEXT: ret void
47+
//
48+
void test_builtin_ppc_fetch_and_and(unsigned int a, unsigned int b) {
49+
__fetch_and_and(&a, b);
50+
}
51+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_andlp(
52+
// CHECK-NEXT: entry:
53+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
54+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8
55+
// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8
56+
// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8
57+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8
58+
// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8
59+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw and i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8
60+
// CHECK-NEXT: ret void
61+
//
62+
void test_builtin_ppc_fetch_and_andlp(unsigned long a, unsigned long b) {
63+
__fetch_and_andlp(&a, b);
64+
}
65+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_or(
66+
// CHECK-NEXT: entry:
67+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
68+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
69+
// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
70+
// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4
71+
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4
72+
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4
73+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4
74+
// CHECK-NEXT: ret void
75+
//
76+
void test_builtin_ppc_fetch_and_or(unsigned int a, unsigned int b) {
77+
__fetch_and_or(&a, b);
78+
}
79+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_orlp(
80+
// CHECK-NEXT: entry:
81+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
82+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8
83+
// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8
84+
// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8
85+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8
86+
// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8
87+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw or i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8
88+
// CHECK-NEXT: ret void
89+
//
90+
void test_builtin_ppc_fetch_and_orlp(unsigned long a, unsigned long b) {
91+
__fetch_and_orlp(&a, b);
92+
}
93+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_swap(
94+
// CHECK-NEXT: entry:
95+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i32, align 4
96+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i32, align 4
97+
// CHECK-NEXT: store i32 [[A:%.*]], i32* [[A_ADDR]], align 4
98+
// CHECK-NEXT: store i32 [[B:%.*]], i32* [[B_ADDR]], align 4
99+
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[B_ADDR]], align 4
100+
// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[B_ADDR]], align 4
101+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xchg i32* [[A_ADDR]], i32 [[TMP1]] monotonic, align 4
102+
// CHECK-NEXT: ret void
103+
//
104+
void test_builtin_ppc_fetch_and_swap(unsigned int a, unsigned int b) {
105+
__fetch_and_swap(&a, b);
106+
}
107+
// CHECK-LABEL: @test_builtin_ppc_fetch_and_swaplp(
108+
// CHECK-NEXT: entry:
109+
// CHECK-NEXT: [[A_ADDR:%.*]] = alloca i64, align 8
110+
// CHECK-NEXT: [[B_ADDR:%.*]] = alloca i64, align 8
111+
// CHECK-NEXT: store i64 [[A:%.*]], i64* [[A_ADDR]], align 8
112+
// CHECK-NEXT: store i64 [[B:%.*]], i64* [[B_ADDR]], align 8
113+
// CHECK-NEXT: [[TMP0:%.*]] = load i64, i64* [[B_ADDR]], align 8
114+
// CHECK-NEXT: [[TMP1:%.*]] = load i64, i64* [[B_ADDR]], align 8
115+
// CHECK-NEXT: [[TMP2:%.*]] = atomicrmw xchg i64* [[A_ADDR]], i64 [[TMP1]] monotonic, align 8
116+
// CHECK-NEXT: ret void
117+
//
118+
void test_builtin_ppc_fetch_and_swaplp(unsigned long a, unsigned long b) {
119+
__fetch_and_swaplp(&a, b);
120+
}

0 commit comments

Comments
 (0)