Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions clang/include/clang/Basic/BuiltinsPPC.def
Original file line number Diff line number Diff line change
Expand Up @@ -1010,6 +1010,11 @@ TARGET_BUILTIN(__builtin_amo_lwat_cond, "UiUi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat_cond, "ULiULi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_lwat_cond_s, "SiSi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_ldat_cond_s, "SLiSLi*Ii", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_stwat, "vUi*UiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_stdat, "vULi*ULiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_stwat_s, "vSi*SiIi", "", "isa-v30-instructions")
TARGET_BUILTIN(__builtin_amo_stdat_s, "vSLi*SLiIi", "", "isa-v30-instructions")


// Set the floating point rounding mode
BUILTIN(__builtin_setrnd, "di", "")
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CodeGen/TargetBuiltins/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1386,5 +1386,19 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID,
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_ldat_cond),
{Op0, Op1});
}
case PPC::BI__builtin_amo_stwat_s: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stwat),
{Op0, Op1, Op2});
}
case PPC::BI__builtin_amo_stdat_s: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
Value *Op1 = EmitScalarExpr(E->getArg(1));
Value *Op2 = EmitScalarExpr(E->getArg(2));
return Builder.CreateCall(CGM.getIntrinsic(Intrinsic::ppc_amo_stdat),
{Op0, Op1, Op2});
}
}
}
89 changes: 89 additions & 0 deletions clang/lib/Headers/amo.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,95 @@ static inline int64_t amo_ldat_sswap(int64_t *ptr, int64_t val) {
return __builtin_amo_ldat_s(ptr, val, _AMO_LD_SWAP);
}

/* AMO Store Operation Codes (FC values) */
enum _AMO_ST {
_AMO_ST_ADD = 0x00, /* Store Add */
_AMO_ST_XOR = 0x01, /* Store Xor */
_AMO_ST_IOR = 0x02, /* Store Ior */
_AMO_ST_AND = 0x03, /* Store And */
_AMO_ST_UMAX = 0x04, /* Store Unsigned Maximum */
_AMO_ST_SMAX = 0x05, /* Store Signed Maximum */
_AMO_ST_UMIN = 0x06, /* Store Unsigned Minimum */
_AMO_ST_SMIN = 0x07, /* Store Signed Minimum */
_AMO_ST_TWIN = 0x18 /* Store Twin */
};

/* 32-bit unsigned AMO store operations */
static inline void amo_stwat_add(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_ADD);
}

static inline void amo_stwat_xor(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_XOR);
}

static inline void amo_stwat_ior(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_IOR);
}

static inline void amo_stwat_and(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_AND);
}

static inline void amo_stwat_umax(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_UMAX);
}

static inline void amo_stwat_umin(uint32_t *ptr, uint32_t val) {
__builtin_amo_stwat(ptr, val, _AMO_ST_UMIN);
}

/* 32-bit signed AMO store operations */
static inline void amo_stwat_sadd(int32_t *ptr, int32_t val) {
__builtin_amo_stwat_s(ptr, val, _AMO_ST_ADD);
}

static inline void amo_stwat_smax(int32_t *ptr, int32_t val) {
__builtin_amo_stwat_s(ptr, val, _AMO_ST_SMAX);
}

static inline void amo_stwat_smin(int32_t *ptr, int32_t val) {
__builtin_amo_stwat_s(ptr, val, _AMO_ST_SMIN);
}

/* 64-bit unsigned AMO store operations */
static inline void amo_stdat_add(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_ADD);
}

static inline void amo_stdat_xor(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_XOR);
}

static inline void amo_stdat_ior(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_IOR);
}

static inline void amo_stdat_and(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_AND);
}

static inline void amo_stdat_umax(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_UMAX);
}

static inline void amo_stdat_umin(uint64_t *ptr, uint64_t val) {
__builtin_amo_stdat(ptr, val, _AMO_ST_UMIN);
}

/* 64-bit signed AMO store operations */
static inline void amo_stdat_sadd(int64_t *ptr, int64_t val) {
__builtin_amo_stdat_s(ptr, val, _AMO_ST_ADD);
}

static inline void amo_stdat_smax(int64_t *ptr, int64_t val) {
__builtin_amo_stdat_s(ptr, val, _AMO_ST_SMAX);
}

static inline void amo_stdat_smin(int64_t *ptr, int64_t val) {
__builtin_amo_stdat_s(ptr, val, _AMO_ST_SMIN);
}

#ifdef __cplusplus
}
#endif
Expand Down
28 changes: 28 additions & 0 deletions clang/lib/Sema/SemaPPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_amo_ldat_cond:
case PPC::BI__builtin_amo_lwat_cond_s:
case PPC::BI__builtin_amo_ldat_cond_s:
case PPC::BI__builtin_amo_stwat:
case PPC::BI__builtin_amo_stdat:
case PPC::BI__builtin_amo_stwat_s:
case PPC::BI__builtin_amo_stdat_s:
return true;
}
return false;
Expand Down Expand Up @@ -300,6 +304,30 @@ bool SemaPPC::CheckPPCBuiltinFunctionCall(const TargetInfo &TI,
return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
<< toString(Result, 10) << "24, 25" << "28" << Arg->getSourceRange();
}
case PPC::BI__builtin_amo_stwat:
case PPC::BI__builtin_amo_stdat:
case PPC::BI__builtin_amo_stwat_s:
case PPC::BI__builtin_amo_stdat_s: {
llvm::APSInt Result;
if (SemaRef.BuiltinConstantArg(TheCall, 2, Result))
return true;
unsigned Val = Result.getZExtValue();

bool IsUnsigned = (BuiltinID == PPC::BI__builtin_amo_stwat ||
BuiltinID == PPC::BI__builtin_amo_stdat);

bool IsValid = IsUnsigned
? llvm::is_contained({0u, 1u, 2u, 3u, 4u, 6u, 24u}, Val)
: llvm::is_contained({0u, 5u, 7u, 24u}, Val);

if (IsValid)
return false;

Expr *Arg = TheCall->getArg(2);
return SemaRef.Diag(Arg->getBeginLoc(), diag::err_argument_invalid_range)
<< toString(Result, 10) << (IsUnsigned ? "0-4, 6" : "0, 5, 7")
<< "24" << Arg->getSourceRange();
}
}
llvm_unreachable("must return from switch");
}
Expand Down
24 changes: 24 additions & 0 deletions clang/test/CodeGen/PowerPC/builtins-amo-err.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,28 @@ void test_amo() {
__builtin_amo_ldat_cond_s(ptr6, 28);
// FC-ERROR: argument value 0 is outside the valid range [24, 25, 28]
__builtin_amo_ldat_cond_s(ptr6, 0);

unsigned int *ptr9, value9;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_stwat(ptr9, value9, 0);
// FC-ERROR: error: argument value 5 is outside the valid range [0-4, 6, 24]
__builtin_amo_stwat(ptr9, value9, 5);

unsigned long int *ptr10, value10;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_stdat(ptr10, value10, 24);
// FC-ERROR: error: argument value 10 is outside the valid range [0-4, 6, 24]
__builtin_amo_stdat(ptr10, value10, 10);

signed int *ptr11, value11;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_stwat_s(ptr11, value11, 0);
// FC-ERROR: error: argument value 1 is outside the valid range [0, 5, 7, 24]
__builtin_amo_stwat_s(ptr11, value11, 1);

signed long int *ptr12, value12;
// AIX32-ERROR-COUNT-2: error: this builtin is only available on 64-bit targets
__builtin_amo_stdat_s(ptr12, value12, 24);
// FC-ERROR: error: argument value 6 is outside the valid range [0, 5, 7, 24]
__builtin_amo_stdat_s(ptr12, value12, 6);
}
63 changes: 63 additions & 0 deletions clang/test/CodeGen/PowerPC/builtins-ppc-amo.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,69 @@ void test_signed_ldat_cond(long int *ptr, long int * resp) {
*resp = res;
}

// CHECK-LABEL: define dso_local void @test_unsigned_stwat(
// CHECK-SAME: ptr noundef [[PTR:%.*]], i32 noundef zeroext [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call void @llvm.ppc.amo.stwat(ptr [[PTR]], i32 [[VALUE]], i32 24)
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_unsigned_stwat(
// AIX-SAME: ptr noundef [[PTR:%.*]], i32 noundef zeroext [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: tail call void @llvm.ppc.amo.stwat(ptr [[PTR]], i32 [[VALUE]], i32 24)
// AIX-NEXT: ret void
//
void test_unsigned_stwat(unsigned int *ptr, unsigned int value, unsigned int * resp) {
__builtin_amo_stwat(ptr, value, 24);
}

// CHECK-LABEL: define dso_local void @test_unsigned_stdat(
// CHECK-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call void @llvm.ppc.amo.stdat(ptr [[PTR]], i64 [[VALUE]], i32 3)
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_unsigned_stdat(
// AIX-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: tail call void @llvm.ppc.amo.stdat(ptr [[PTR]], i64 [[VALUE]], i32 3)
// AIX-NEXT: ret void
//
void test_unsigned_stdat(unsigned long int *ptr, unsigned long int value, unsigned long int * resp) {
__builtin_amo_stdat(ptr, value, 3);
}

// CHECK-LABEL: define dso_local void @test_signed_stwat(
// CHECK-SAME: ptr noundef [[PTR:%.*]], i32 noundef signext [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call void @llvm.ppc.amo.stwat(ptr [[PTR]], i32 [[VALUE]], i32 24)
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_signed_stwat(
// AIX-SAME: ptr noundef [[PTR:%.*]], i32 noundef signext [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: tail call void @llvm.ppc.amo.stwat(ptr [[PTR]], i32 [[VALUE]], i32 24)
// AIX-NEXT: ret void
//
void test_signed_stwat(int *ptr, int value, int * resp) {
__builtin_amo_stwat_s(ptr, value, 24);
}

// CHECK-LABEL: define dso_local void @test_signed_stdat(
// CHECK-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// CHECK-NEXT: [[ENTRY:.*:]]
// CHECK-NEXT: tail call void @llvm.ppc.amo.stdat(ptr [[PTR]], i64 [[VALUE]], i32 5)
// CHECK-NEXT: ret void
//
// AIX-LABEL: define void @test_signed_stdat(
// AIX-SAME: ptr noundef [[PTR:%.*]], i64 noundef [[VALUE:%.*]], ptr noundef readnone captures(none) [[RESP:%.*]]) local_unnamed_addr #[[ATTR0]] {
// AIX-NEXT: [[ENTRY:.*:]]
// AIX-NEXT: tail call void @llvm.ppc.amo.stdat(ptr [[PTR]], i64 [[VALUE]], i32 5)
// AIX-NEXT: ret void
//
void test_signed_stdat(long int *ptr, long int value, long int * resp) {
__builtin_amo_stdat_s(ptr, value, 5);
}
//.
// CHECK: [[INT_TBAA2]] = !{[[META3:![0-9]+]], [[META3]], i64 0}
// CHECK: [[META3]] = !{!"int", [[META4:![0-9]+]], i64 0}
Expand Down
108 changes: 108 additions & 0 deletions clang/test/CodeGen/PowerPC/ppc-amo-header.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,111 @@ int64_t test_ldat_sswap(int64_t *ptr, int64_t val) {
// CHECK: call i64 @llvm.ppc.amo.ldat(ptr %{{.*}}, i64 %{{.*}}, i32 8)
return amo_ldat_sswap(ptr, val);
}

void test_stwat_add(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_add
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 0)
return amo_stwat_add(ptr, val);
}

void test_stwat_xor(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_xor
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 1)
return amo_stwat_xor(ptr, val);
}

void test_stwat_ior(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_ior
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 2)
return amo_stwat_ior(ptr, val);
}

void test_stwat_and(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_and
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 3)
return amo_stwat_and(ptr, val);
}

void test_stwat_umax(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_umax
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 4)
return amo_stwat_umax(ptr, val);
}

void test_stwat_umin(uint32_t *ptr, uint32_t val) {
// CHECK-LABEL: @test_stwat_umin
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 6)
return amo_stwat_umin(ptr, val);
}

void test_stwat_sadd(int32_t *ptr, int32_t val) {
// CHECK-LABEL: @test_stwat_sadd
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 0)
return amo_stwat_sadd(ptr, val);
}

void test_stwat_smax(int32_t *ptr, int32_t val) {
// CHECK-LABEL: @test_stwat_smax
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 5)
return amo_stwat_smax(ptr, val);
}

void test_stwat_smin(int32_t *ptr, int32_t val) {
// CHECK-LABEL: @test_stwat_smin
// CHECK: call void @llvm.ppc.amo.stwat(ptr %{{.*}}, i32 %{{.*}}, i32 7)
return amo_stwat_smin(ptr, val);
}

void test_stdat_add(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_add
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 0)
return amo_stdat_add(ptr, val);
}

void test_stdat_xor(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_xor
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 1)
return amo_stdat_xor(ptr, val);
}

void test_stdat_ior(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_ior
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 2)
return amo_stdat_ior(ptr, val);
}

void test_stdat_and(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_and
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 3)
return amo_stdat_and(ptr, val);
}

void test_stdat_umax(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_umax
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 4)
return amo_stdat_umax(ptr, val);
}

void test_stdat_umin(uint64_t *ptr, uint64_t val) {
// CHECK-LABEL: @test_stdat_umin
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 6)
return amo_stdat_umin(ptr, val);
}

void test_stdat_sadd(int64_t *ptr, int64_t val) {
// CHECK-LABEL: @test_stdat_sadd
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 0)
return amo_stdat_sadd(ptr, val);
}

void test_stdat_smax(int64_t *ptr, int64_t val) {
// CHECK-LABEL: @test_stdat_smax
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 5)
return amo_stdat_smax(ptr, val);
}

void test_stdat_smin(int64_t *ptr, int64_t val) {
// CHECK-LABEL: @test_stdat_smin
// CHECK: call void @llvm.ppc.amo.stdat(ptr %{{.*}}, i64 %{{.*}}, i32 7)
return amo_stdat_smin(ptr, val);
}
9 changes: 9 additions & 0 deletions llvm/include/llvm/IR/IntrinsicsPowerPC.td
Original file line number Diff line number Diff line change
Expand Up @@ -2158,4 +2158,13 @@ let TargetPrefix = "ppc" in {
DefaultAttrsIntrinsic<[llvm_i64_ty],[llvm_ptr_ty,
llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<1>>]>;

def int_ppc_amo_stwat : ClangBuiltin<"__builtin_amo_stwat">,
DefaultAttrsIntrinsic<[],[llvm_ptr_ty,
llvm_i32_ty, llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<2>>]>;
def int_ppc_amo_stdat : ClangBuiltin<"__builtin_amo_stdat">,
DefaultAttrsIntrinsic<[],[llvm_ptr_ty,
llvm_i64_ty, llvm_i32_ty],
[IntrArgMemOnly, ImmArg<ArgIndex<2>>]>;
}
Loading
Loading