-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[PowerPC] Add support for AMO store builtins #170933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: users/maryammo/amo3
Are you sure you want to change the base?
Conversation
|
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-clang Author: Maryam Moghadas (maryammo) ChangesThis commit adds 4 Clang builtins for PowerPC AMO store operations: __builtin_amo_stwat for 32-bit unsigned operations and maps GCC's AMO store functions to these Clang builtins for compatibility. Patch is 21.21 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170933.diff 12 Files Affected:
diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def
index 7689daf00e6a7..f518429136e3c 100644
--- a/clang/include/clang/Basic/BuiltinsPPC.def
+++ b/clang/include/clang/Basic/BuiltinsPPC.def
@@ -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", "")
diff --git a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
index bccb6acdb4e06..6568959351a5d 100644
--- a/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/PPC.cpp
@@ -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});
+ }
}
}
diff --git a/clang/lib/Headers/amo.h b/clang/lib/Headers/amo.h
index 97eff35e9c5dc..c7563f203d1f8 100644
--- a/clang/lib/Headers/amo.h
+++ b/clang/lib/Headers/amo.h
@@ -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
diff --git a/clang/lib/Sema/SemaPPC.cpp b/clang/lib/Sema/SemaPPC.cpp
index a7e76a9917372..1bf806d996887 100644
--- a/clang/lib/Sema/SemaPPC.cpp
+++ b/clang/lib/Sema/SemaPPC.cpp
@@ -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;
@@ -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");
}
diff --git a/clang/test/CodeGen/PowerPC/builtins-amo-err.c b/clang/test/CodeGen/PowerPC/builtins-amo-err.c
index ad6be9e867856..f99efd0505818 100644
--- a/clang/test/CodeGen/PowerPC/builtins-amo-err.c
+++ b/clang/test/CodeGen/PowerPC/builtins-amo-err.c
@@ -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);
}
diff --git a/clang/test/CodeGen/PowerPC/builtins-ppc-amo.c b/clang/test/CodeGen/PowerPC/builtins-ppc-amo.c
index 0bf28e85730e1..ffbedd8c50202 100644
--- a/clang/test/CodeGen/PowerPC/builtins-ppc-amo.c
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-amo.c
@@ -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}
diff --git a/clang/test/CodeGen/PowerPC/ppc-amo-header.c b/clang/test/CodeGen/PowerPC/ppc-amo-header.c
index ffc87561fa3c4..e0acbf2dd8fa2 100644
--- a/clang/test/CodeGen/PowerPC/ppc-amo-header.c
+++ b/clang/test/CodeGen/PowerPC/ppc-amo-header.c
@@ -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);
+}
diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
index e13f40454fba2..ce27e9163560b 100644
--- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td
+++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td
@@ -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>>]>;
}
diff --git a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
index 2ddd991f5e997..bcb7d5cceb0f0 100644
--- a/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/llvm/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -11482,6 +11482,30 @@ SDValue PPCTargetLowering::LowerINTRINSIC_VOID(SDValue Op,
return DAG.getStore(DAG.getEntryNode(), DL, Op.getOperand(ArgStart + 2),
Op.getOperand(ArgStart + 1), MachinePointerInfo());
}
+ case Intrinsic::ppc_amo_stwat:
+ case Intrinsic::ppc_amo_stdat: {
+ SDLoc dl(Op);
+ SDValue Chain = Op.getOperand(0);
+ SDValue Ptr = Op.getOperand(ArgStart + 1);
+ SDValue Val = Op.getOperand(ArgStart + 2);
+ SDValue FC = Op.getOperand(ArgStart + 3);
+
+ bool IsStwat =
+ Op.getConstantOperandVal(ArgStart) == Intrinsic::ppc_amo_stwat;
+ if (isa<ConstantSDNode>(Val)) {
+ MVT VT = IsStwat ? MVT::i32 : MVT::i64;
+ MachineFunction &MF = DAG.getMachineFunction();
+ MachineRegisterInfo &MRI = MF.getRegInfo();
+ Register ValReg = MRI.createVirtualRegister(getRegClassFor(VT));
+
+ // Materialize constant Val using CopyToReg/CopyFromReg.
+ SDValue CopyChain = DAG.getCopyToReg(Chain, dl, ValReg, Val);
+ Val = DAG.getCopyFromReg(CopyChain, dl, ValReg, VT);
+ }
+ MachineSDNode *MNode = DAG.getMachineNode(IsStwat ? PPC::STWAT : PPC::STDAT,
+ dl, MVT::Other, {Val, Ptr, FC});
+ return SDValue(MNode, 0);
+ }
default:
break;
}
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 9fa284716dc71..45614923d9477 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -412,7 +412,7 @@ def : Pat<(int_ppc_cmpxchg_i128 ForceXForm:$ptr,
g8rc:$new_hi))>;
let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
-def STDAT : X_RD5_RS5_IM5<31, 742, (outs), (ins g8rc:$RST, g8rc:$RA, u5imm:$RB),
+def STDAT : X_RD5_RS5_IM5<31, 742, (outs), (ins g8rc:$RST, ptr_rc_nor0:$RA, u5imm:$RB),
"stdat $RST, $RA, $RB", IIC_LdStStore>, isPPC64,
Requires<[IsISA3_0]>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index 67bbed63bfc13..b7b687fe197a1 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -2157,7 +2157,7 @@ def STWCX : XForm_1_memOp<31, 150, (outs), (ins gprc:$RST, (memrr $RA, $RB):$add
}
let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
-def STWAT : X_RD5_RS5_IM5<31, 710, (outs), (ins gprc:$RST, gprc:$RA, u5imm:$RB),
+def STWAT : X_RD5_RS5_IM5<31, 710, (outs), (ins gprc:$RST, ptr_rc_nor0:$RA, u5imm:$RB),
"stwat $RST, $RA, $RB", IIC_LdStStore>,
Requires<[IsISA3_0]>;
diff --git a/llvm/test/CodeGen/PowerPC/amo-enable.ll b/llvm/test/CodeGen/PowerPC/amo-enable.ll
index 4e80d95b38e3f..760952a9a4c4c 100644
--- a/llvm/test/CodeGen/PowerPC/amo-e...
[truncated]
|
This commit adds 4 Clang builtins for PowerPC AMO store operations:
__builtin_amo_stwat for 32-bit unsigned operations
__builtin_amo_stdat for 64-bit unsigned operations
__builtin_amo_stwat_s for 32-bit signed operations
__builtin_amo_stdat_s for 64-bit signed operations
and maps GCC's AMO store functions to these Clang builtins for compatibility.