Skip to content

Commit e416e16

Browse files
committed
[PowerPC] Add AMO load signed builtins
This commit adds two Clang builtins for AMO load signed operations: __builtin_amo_lwat_st for 32-bit signed operations __builtin_amo_ldat_s for 64-bit signed operations
1 parent 29edda1 commit e416e16

File tree

8 files changed

+205
-5
lines changed

8 files changed

+205
-5
lines changed

clang/include/clang/Basic/BuiltinsPPC.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,8 @@ TARGET_BUILTIN(__builtin_pack_vector_int128, "V1LLLiULLiULLi", "", "vsx")
10041004
// AMO builtins
10051005
TARGET_BUILTIN(__builtin_amo_lwat, "UiUi*UiIi", "", "isa-v30-instructions")
10061006
TARGET_BUILTIN(__builtin_amo_ldat, "ULiULi*ULiIi", "", "isa-v30-instructions")
1007+
TARGET_BUILTIN(__builtin_amo_lwat_s, "SiSi*SiIi", "", "isa-v30-instructions")
1008+
TARGET_BUILTIN(__builtin_amo_ldat_s, "SLiSLi*SLiIi", "", "isa-v30-instructions")
10071009

10081010
// Set the floating point rounding mode
10091011
BUILTIN(__builtin_setrnd, "di", "")

clang/lib/CodeGen/TargetBuiltins/PPC.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,5 +1359,20 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
13591359
{EmitScalarExpr(E->getArg(0))});
13601360
case PPC::BI__builtin_ppc_mffs:
13611361
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_readflm));
1362+
1363+
case PPC::BI__builtin_amo_lwat_s: {
1364+
Value *Op0 = EmitScalarExpr(E->getArg(0));
1365+
Value *Op1 = EmitScalarExpr(E->getArg(1));
1366+
Value *Op2 = EmitScalarExpr(E->getArg(2));
1367+
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_lwat),
1368+
{Op0, Op1, Op2});
1369+
}
1370+
case PPC::BI__builtin_amo_ldat_s: {
1371+
Value *Op0 = EmitScalarExpr(E->getArg(0));
1372+
Value *Op1 = EmitScalarExpr(E->getArg(1));
1373+
Value *Op2 = EmitScalarExpr(E->getArg(2));
1374+
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat),
1375+
{Op0, Op1, Op2});
1376+
}
13621377
}
13631378
}

clang/lib/Headers/amo.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,23 @@ static inline uint32_t amo_lwat_swap(uint32_t *ptr, uint32_t val) {
6161
return __builtin_amo_lwat(ptr, val, _AMO_LD_SWAP);
6262
}
6363

64+
/* 32-bit signed AMO load operations */
65+
static inline int32_t amo_lwat_sadd(int32_t *ptr, int32_t val) {
66+
return __builtin_amo_lwat_s(ptr, val, _AMO_LD_ADD);
67+
}
68+
69+
static inline int32_t amo_lwat_smax(int32_t *ptr, int32_t val) {
70+
return __builtin_amo_lwat_s(ptr, val, _AMO_LD_SMAX);
71+
}
72+
73+
static inline int32_t amo_lwat_smin(int32_t *ptr, int32_t val) {
74+
return __builtin_amo_lwat_s(ptr, val, _AMO_LD_SMIN);
75+
}
76+
77+
static inline int32_t amo_lwat_sswap(int32_t *ptr, int32_t val) {
78+
return __builtin_amo_lwat_s(ptr, val, _AMO_LD_SWAP);
79+
}
80+
6481
/* 64-bit unsigned AMO load operations */
6582
static inline uint64_t amo_ldat_add(uint64_t *ptr, uint64_t val) {
6683
return __builtin_amo_ldat(ptr, val, _AMO_LD_ADD);
@@ -90,6 +107,23 @@ static inline uint64_t amo_ldat_swap(uint64_t *ptr, uint64_t val) {
90107
return __builtin_amo_ldat(ptr, val, _AMO_LD_SWAP);
91108
}
92109

110+
/* 64-bit signed AMO load operations */
111+
static inline int64_t amo_ldat_sadd(int64_t *ptr, int64_t val) {
112+
return __builtin_amo_ldat_s(ptr, val, _AMO_LD_ADD);
113+
}
114+
115+
static inline int64_t amo_ldat_smax(int64_t *ptr, int64_t val) {
116+
return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SMAX);
117+
}
118+
119+
static inline int64_t amo_ldat_smin(int64_t *ptr, int64_t val) {
120+
return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SMIN);
121+
}
122+
123+
static inline int64_t amo_ldat_sswap(int64_t *ptr, int64_t val) {
124+
return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SWAP);
125+
}
126+
93127
#ifdef __cplusplus
94128
}
95129
#endif

clang/lib/Sema/SemaPPC.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -256,17 +256,27 @@ bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
256256
return BuiltinPPCMMACall(TheCall, BuiltinID, Types);
257257
#include "clang/Basic/BuiltinsPPC.def"
258258
case PPC::BI__builtin_amo_lwat:
259-
case PPC::BI__builtin_amo_ldat: {
259+
case PPC::BI__builtin_amo_ldat:
260+
case PPC::BI__builtin_amo_lwat_s:
261+
case PPC::BI__builtin_amo_ldat_s: {
260262
llvm::APSInt Result;
261263
if (SemaRef.BuiltinConstantArg(TheCall, 2, Result))
262264
return true;
263265
unsigned Val = Result.getZExtValue();
264-
static constexpr unsigned ValidFC[] = {0, 1, 2, 3, 4, 6, 8};
265-
if (llvm::is_contained(ValidFC, Val))
266+
267+
bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_lwat ||
268+
BuiltinID == PPC::BI__builtin_amo_ldat);
269+
270+
bool IsValid = IsUnsigned ? llvm::is_contained({0, 1, 2, 3, 4, 6, 8}, Val)
271+
: llvm::is_contained({0, 5, 7, 8}, Val);
272+
273+
if (IsValid)
266274
return false;
275+
267276
Expr *Arg = TheCall->getArg(2);
268277
return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
269-
<< toString(Result, 10) << "0-4, 6" << "8" << Arg->getSourceRange();
278+
<< toString(Result, 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7") << "8"
279+
<< Arg->getSourceRange();
270280
}
271281
}
272282
llvm_unreachable("must return from switch");

clang/test/CodeGen/PowerPC/builtins-amo-err.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,16 @@ void test_amo() {
1515
__builtin_amo_ldat(ptr2, value2, 3);
1616
// FC-ERROR: error: argument value 26 is outside the valid range [0-4, 6, 8]
1717
__builtin_amo_ldat(ptr2, value2, 26);
18+
19+
signed int *ptr3, value3;
20+
// AIX32-ERROR: error: this builtin is only available on 64-bit targets
21+
__builtin_amo_lwat_s(ptr3, value3, 0);
22+
// FC-ERROR: argument value 2 is outside the valid range [0, 5, 7, 8]
23+
__builtin_amo_lwat_s(ptr3, value3, 2);
24+
25+
unsigned long int *ptr4, value4;
26+
// AIX32-ERROR: error: this builtin is only available on 64-bit targets
27+
__builtin_amo_ldat_s(ptr4, value4, 3);
28+
// FC-ERROR: error: argument value 6 is outside the valid range [0, 5, 7, 8]
29+
__builtin_amo_ldat_s(ptr4, value4, 6);
1830
}

clang/test/CodeGen/PowerPC/builtins-ppc-amo.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,46 @@ void test_unsigned_ldat(unsigned long int *ptr, unsigned long int value, unsigne
4141
unsigned long int res = __builtin_amo_ldat(ptr, value, 3);
4242
*resp = res;
4343
}
44+
45+
// CHECK-LABEL: define dso_local void @test_signed_lwat(
46+
// CHECK-SAME: ptr noundef [[PTR:%.*]], i32 noundef signext [[VALUE:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
47+
// CHECK-NEXT: [[ENTRY:.*:]]
48+
// CHECK-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat(ptr [[PTR]], i32 [[VALUE]], i32 5)
49+
// CHECK-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
50+
// CHECK-NEXT: ret void
51+
//
52+
// AIX-LABEL: define void @test_signed_lwat(
53+
// AIX-SAME: ptr noundef [[PTR:%.*]], i32 noundef signext [[VALUE:%.*]], ptr noundef writeonly captures(none) initializes((0, 4)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
54+
// AIX-NEXT: [[ENTRY:.*:]]
55+
// AIX-NEXT: [[TMP0:%.*]] = tail call i32 @llvm.ppc.amo.lwat(ptr [[PTR]], i32 [[VALUE]], i32 5)
56+
// AIX-NEXT: store i32 [[TMP0]], ptr [[RESP]], align 4, !tbaa [[INT_TBAA2]]
57+
// AIX-NEXT: ret void
58+
//
59+
void test_signed_lwat(int *ptr, int value, int * resp) {
60+
int res = __builtin_amo_lwat_s(ptr, value, 5);
61+
*resp = res;
62+
}
63+
64+
65+
// CHECK-LABEL: define dso_local void @test_signed_ldat(
66+
// CHECK-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
67+
// CHECK-NEXT: [[ENTRY:.*:]]
68+
// CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat(ptr [[PTR]], i64 [[VALUE]], i32 8)
69+
// CHECK-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
70+
// CHECK-NEXT: ret void
71+
//
72+
// AIX-LABEL: define void @test_signed_ldat(
73+
// AIX-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef writeonly captures(none) initializes((0, 8)) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
74+
// AIX-NEXT: [[ENTRY:.*:]]
75+
// AIX-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.ppc.amo.ldat(ptr [[PTR]], i64 [[VALUE]], i32 8)
76+
// AIX-NEXT: store i64 [[TMP0]], ptr [[RESP]], align 8, !tbaa [[LONG_TBAA6]]
77+
// AIX-NEXT: ret void
78+
//
79+
void test_signed_ldat(long int *ptr, long int value, long int * resp) {
80+
long int res = __builtin_amo_ldat_s(ptr, value, 8);
81+
*resp = res;
82+
}
83+
4484
//.
4585
// CHECK: [[INT_TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
4686
// CHECK: [[META3]] = !{!"int", [[META4:![0-9]+]], i64 0}

clang/test/CodeGen/PowerPC/ppc-amo-header.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,30 @@ uint32_t test_lwat_swap(uint32_t *ptr, uint32_t val) {
4848
return amo_lwat_swap(ptr, val);
4949
}
5050

51+
int32_t test_lwat_sadd(int32_t *ptr, int32_t val) {
52+
// CHECK-LABEL: @test_lwat_sadd
53+
// CHECK: call i32 @llvm.ppc.amo.lwat(ptr %{{.*}}, i32 %{{.*}}, i32 0)
54+
return amo_lwat_sadd(ptr, val);
55+
}
56+
57+
int32_t test_lwat_smax(int32_t *ptr, int32_t val) {
58+
// CHECK-LABEL: @test_lwat_smax
59+
// CHECK: call i32 @llvm.ppc.amo.lwat(ptr %{{.*}}, i32 %{{.*}}, i32 5)
60+
return amo_lwat_smax(ptr, val);
61+
}
62+
63+
int32_t test_lwat_smin(int32_t *ptr, int32_t val) {
64+
// CHECK-LABEL: @test_lwat_smin
65+
// CHECK: call i32 @llvm.ppc.amo.lwat(ptr %{{.*}}, i32 %{{.*}}, i32 7)
66+
return amo_lwat_smin(ptr, val);
67+
}
68+
69+
int32_t test_lwat_sswap(int32_t *ptr, int32_t val) {
70+
// CHECK-LABEL: @test_lwat_sswap
71+
// CHECK: call i32 @llvm.ppc.amo.lwat(ptr %{{.*}}, i32 %{{.*}}, i32 8)
72+
return amo_lwat_sswap(ptr, val);
73+
}
74+
5175
uint64_t test_ldat_add(uint64_t *ptr, uint64_t val) {
5276
// CHECK-LABEL: @test_ldat_add
5377
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 0)
@@ -89,3 +113,27 @@ uint64_t test_ldat_swap(uint64_t *ptr, uint64_t val) {
89113
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 8)
90114
return amo_ldat_swap(ptr, val);
91115
}
116+
117+
int64_t test_ldat_sadd(int64_t *ptr, int64_t val) {
118+
// CHECK-LABEL: @test_ldat_sadd
119+
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 0)
120+
return amo_ldat_sadd(ptr, val);
121+
}
122+
123+
int64_t test_ldat_smax(int64_t *ptr, int64_t val) {
124+
// CHECK-LABEL: @test_ldat_smax
125+
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 5)
126+
return amo_ldat_smax(ptr, val);
127+
}
128+
129+
int64_t test_ldat_smin(int64_t *ptr, int64_t val) {
130+
// CHECK-LABEL: @test_ldat_smin
131+
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 7)
132+
return amo_ldat_smin(ptr, val);
133+
}
134+
135+
int64_t test_ldat_sswap(int64_t *ptr, int64_t val) {
136+
// CHECK-LABEL: @test_ldat_sswap
137+
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 8)
138+
return amo_ldat_sswap(ptr, val);
139+
}

llvm/test/CodeGen/PowerPC/amo-enable.ll

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,45 @@ entry:
4646
ret void
4747
}
4848

49+
define void @test_s_lwat(ptr noundef %ptr, i32 noundef %value, ptr nocapture %resp) {
50+
; CHECK-LABEL: test_s_lwat:
51+
; CHECK: # %bb.0: # %entry
52+
; CHECK-NEXT: mr r7, r4
53+
; CHECK-NEXT: lwat r6, r3, 0
54+
; CHECK-NEXT: stw r6, 0(r5)
55+
; CHECK-NEXT: blr
56+
;
57+
; CHECK-BE-LABEL: test_s_lwat:
58+
; CHECK-BE: # %bb.0: # %entry
59+
; CHECK-BE-NEXT: mr r7, r4
60+
; CHECK-BE-NEXT: lwat r6, r3, 0
61+
; CHECK-BE-NEXT: stw r6, 0(r5)
62+
; CHECK-BE-NEXT: blr
63+
entry:
64+
%0 = tail call i32 @llvm.ppc.amo.lwat(ptr %ptr, i32 %value, i32 0)
65+
store i32 %0, ptr %resp, align 4
66+
ret void
67+
}
68+
69+
define void @test_s_ldat(ptr noundef %ptr, i64 noundef %value, ptr nocapture %resp) {
70+
; CHECK-LABEL: test_s_ldat:
71+
; CHECK: # %bb.0: # %entry
72+
; CHECK-NEXT: mr r7, r4
73+
; CHECK-NEXT: ldat r6, r3, 5
74+
; CHECK-NEXT: std r6, 0(r5)
75+
; CHECK-NEXT: blr
76+
;
77+
; CHECK-BE-LABEL: test_s_ldat:
78+
; CHECK-BE: # %bb.0: # %entry
79+
; CHECK-BE-NEXT: mr r7, r4
80+
; CHECK-BE-NEXT: ldat r6, r3, 5
81+
; CHECK-BE-NEXT: std r6, 0(r5)
82+
; CHECK-BE-NEXT: blr
83+
entry:
84+
%0 = tail call i64 @llvm.ppc.amo.ldat(ptr %ptr, i64 %value, i32 5)
85+
store i64 %0, ptr %resp, align 8
86+
ret void
87+
}
88+
4989
declare i64 @llvm.ppc.amo.ldat(ptr, i64, i32 immarg)
5090
declare i32 @llvm.ppc.amo.lwat(ptr, i32, i32 immarg)
51-

0 commit comments

Comments
 (0)