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 @@ -79,6 +79,7 @@ BUILTIN(__builtin_ppc_stdcx, "iLiD*Li", "") BUILTIN(__builtin_ppc_stwcx, "iiD*i", "") BUILTIN(__builtin_ppc_sthcx, "isD*s", "") +BUILTIN(__builtin_ppc_stbcx, "icD*i", "") BUILTIN(__builtin_ppc_tdw, "vLLiLLiIUi", "") BUILTIN(__builtin_ppc_tw, "viiIUi", "") BUILTIN(__builtin_ppc_trap, "vi", "") 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 @@ -124,6 +124,7 @@ Builder.defineMacro("__stdcx", "__builtin_ppc_stdcx"); Builder.defineMacro("__stwcx", "__builtin_ppc_stwcx"); Builder.defineMacro("__sthcx", "__builtin_ppc_sthcx"); + Builder.defineMacro("__stbcx", "__builtin_ppc_stbcx"); Builder.defineMacro("__tdw", "__builtin_ppc_tdw"); Builder.defineMacro("__tw", "__builtin_ppc_tw"); Builder.defineMacro("__trap", "__builtin_ppc_trap"); diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -3434,9 +3434,8 @@ case PPC::BI__builtin_ppc_rdlam: return SemaValueIsRunOfOnes(TheCall, 2); case PPC::BI__builtin_ppc_icbt: - return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions", - diag::err_ppc_builtin_only_on_arch, "8"); case PPC::BI__builtin_ppc_sthcx: + case PPC::BI__builtin_ppc_stbcx: case PPC::BI__builtin_ppc_lharx: case PPC::BI__builtin_ppc_lbarx: return SemaFeatureCheck(*this, TheCall, "isa-v207-instructions", diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-pwr8.c b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr8.c --- a/clang/test/CodeGen/builtins-ppc-xlcompat-pwr8.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-pwr8.c @@ -15,6 +15,8 @@ // RUN: -target-cpu pwr7 -o - 2>&1 | FileCheck %s -check-prefix=CHECK-NOPWR8 extern void *a; +extern volatile char *c_addr; +extern char c; void test_icbt() { // CHECK-LABEL: @test_icbt( @@ -31,3 +33,14 @@ // CHECK-PWR8: call void @llvm.ppc.icbt(i8* %0) // CHECK-NOPWR8: error: this builtin is only valid on POWER8 or later CPUs } + +int test_builtin_ppc_stbcx() { +// CHECK-PWR8-LABEL: @test_builtin_ppc_stbcx( +// CHECK-PWR8: [[TMP0:%.*]] = load i8*, i8** @c_addr, align {{[0-9]+}} +// CHECK-PWR8-NEXT: [[TMP1:%.*]] = load i8, i8* @c, align 1 +// CHECK-PWR8-NEXT: [[TMP2:%.*]] = sext i8 [[TMP1]] to i32 +// CHECK-PWR8-NEXT: [[TMP3:%.*]] = call i32 @llvm.ppc.stbcx(i8* [[TMP0]], i32 [[TMP2]]) +// CHECK-PWR8-NEXT: ret i32 [[TMP3]] +// CHECK-NOPWR8: error: this builtin is only valid on POWER8 or later CPUs + return __builtin_ppc_stbcx(c_addr, c); +} diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -1566,6 +1566,9 @@ [IntrWriteMem]>; def int_ppc_sthcx : Intrinsic<[llvm_i32_ty], [ llvm_ptr_ty, llvm_i32_ty ], [IntrWriteMem]>; + def int_ppc_stbcx : GCCBuiltin<"__builtin_ppc_stbcx">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrWriteMem]>; def int_ppc_dcbtstt : GCCBuiltin<"__builtin_ppc_dcbtstt">, Intrinsic<[], [llvm_ptr_ty], [IntrArgMemOnly, NoCapture>]>; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -5463,6 +5463,8 @@ def : Pat<(int_ppc_stwcx ForceXForm:$dst, gprc:$A), (STWCX gprc:$A, ForceXForm:$dst)>; +def : Pat<(int_ppc_stbcx ForceXForm:$dst, gprc:$A), + (STBCX gprc:$A, ForceXForm:$dst)>; def : Pat<(int_ppc_tw gprc:$A, gprc:$B, i32:$IMM), (TW $IMM, $A, $B)>; def : Pat<(int_ppc_trap gprc:$A), diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll @@ -74,6 +74,28 @@ ret i32 %2 } +declare i32 @llvm.ppc.stbcx(i8*, i32) +define signext i32 @test_stbcx(i8* %addr, i8 signext %val) { +; CHECK-64-LABEL: test_stbcx: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: stbcx. 4, 0, 3 +; CHECK-64-NEXT: mfocrf 3, 128 +; CHECK-64-NEXT: srwi 3, 3, 28 +; CHECK-64-NEXT: extsw 3, 3 +; CHECK-64-NEXT: blr +; +; CHECK-32-LABEL: test_stbcx: +; CHECK-32: # %bb.0: # %entry +; CHECK-32-NEXT: stbcx. 4, 0, 3 +; CHECK-32-NEXT: mfocrf 3, 128 +; CHECK-32-NEXT: srwi 3, 3, 28 +; CHECK-32-NEXT: blr +entry: + %conv = sext i8 %val to i32 + %0 = tail call i32 @llvm.ppc.stbcx(i8* %addr, i32 %conv) + ret i32 %0 +} + define dso_local signext i16 @test_lharx(i16* %a) { ; CHECK-64-LABEL: test_lharx: ; CHECK-64: # %bb.0: # %entry