diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -994,6 +994,46 @@ ShiftedByte, llvm::ConstantInt::get(CGF.Int8Ty, 1), "bittest.res"); } +static llvm::Value *emitPPCLoadReserveIntrinsic(CodeGenFunction &CGF, + unsigned BuiltinID, + const CallExpr *E) { + Value *Addr = CGF.EmitScalarExpr(E->getArg(0)); + + SmallString<64> Asm; + raw_svector_ostream AsmOS(Asm); + llvm::IntegerType *RetType = CGF.Int32Ty; + + switch (BuiltinID) { + case clang::PPC::BI__builtin_ppc_ldarx: + AsmOS << "ldarx "; + RetType = CGF.Int64Ty; + break; + case clang::PPC::BI__builtin_ppc_lwarx: + AsmOS << "lwarx "; + RetType = CGF.Int32Ty; + break; + default: + llvm_unreachable("Expected only PowerPC load reserve intrinsics"); + } + + AsmOS << "$0, ${1:y}"; + + std::string Constraints = "=r,*Z,~{memory}"; + std::string MachineClobbers = CGF.getTarget().getClobbers(); + if (!MachineClobbers.empty()) { + Constraints += ','; + Constraints += MachineClobbers; + } + + llvm::Type *IntPtrType = RetType->getPointerTo(); + llvm::FunctionType *FTy = + llvm::FunctionType::get(RetType, {IntPtrType}, false); + + llvm::InlineAsm *IA = + llvm::InlineAsm::get(FTy, Asm, Constraints, /*hasSideEffects=*/true); + return CGF.Builder.CreateCall(IA, {Addr}); +} + namespace { enum class MSVCSetJmpKind { _setjmpex, @@ -15532,6 +15572,9 @@ return MakeBinaryAtomicValue(*this, AtomicRMWInst::Xchg, E, llvm::AtomicOrdering::Monotonic); } + case PPC::BI__builtin_ppc_ldarx: + case PPC::BI__builtin_ppc_lwarx: + return emitPPCLoadReserveIntrinsic(*this, BuiltinID, E); } } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c --- a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c @@ -1,27 +1,23 @@ // RUN: not %clang_cc1 -triple=powerpc-unknown-aix -emit-llvm %s -o - 2>&1 |\ // RUN: FileCheck %s --check-prefix=CHECK32-ERROR -// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s --check-prefix=CHECK64 -// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s --check-prefix=CHECK64 -// RUN: %clang_cc1 -triple=powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s --check-prefix=CHECK64 long test_ldarx(volatile long* a) { // CHECK64-LABEL: @test_ldarx - // CHECK64: %0 = load i64*, i64** %a.addr, align 8 - // CHECK64: %1 = bitcast i64* %0 to i8* - // CHECK64: %2 = call i64 @llvm.ppc.ldarx(i8* %1) + // CHECK64: %0 = tail call i64 asm sideeffect "ldarx $0, ${1:y}", "=r,*Z,~{memory}"(i64* %a) // CHECK32-ERROR: error: this builtin is only available on 64-bit targets return __ldarx(a); } int test_stdcx(volatile long* addr, long val) { // CHECK64-LABEL: @test_stdcx - // CHECK64: %0 = load i64*, i64** %addr.addr, align 8 - // CHECK64: %1 = bitcast i64* %0 to i8* - // CHECK64: %2 = load i64, i64* %val.addr, align 8 - // CHECK64: %3 = call i32 @llvm.ppc.stdcx(i8* %1, i64 %2) + // CHECK64: %0 = bitcast i64* %addr to i8* + // CHECK64: %1 = tail call i32 @llvm.ppc.stdcx(i8* %0, i64 %val) // CHECK32-ERROR: error: this builtin is only available on 64-bit targets return __stdcx(addr, val); } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c --- a/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c @@ -1,22 +1,20 @@ -// RUN: %clang_cc1 -triple=powerpc-unknown-aix -emit-llvm %s -o - | \ +// RUN: %clang_cc1 -O2 -triple=powerpc-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ // RUN: FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s -// RUN: %clang_cc1 -triple=powerpc64-unknown-unknown -emit-llvm %s \ +// RUN: %clang_cc1 -O2 -triple=powerpc64-unknown-unknown -emit-llvm %s \ // RUN: -o - | FileCheck %s int test_lwarx(volatile int* a) { // CHECK: @test_lwarx - // CHECK: %1 = bitcast i32* %0 to i8* - // CHECK: %2 = call i32 @llvm.ppc.lwarx(i8* %1) + // CHECK: %0 = tail call i32 asm sideeffect "lwarx $0, ${1:y}", "=r,*Z,~{memory}"(i32* %a) return __lwarx(a); } int test_stwcx(volatile int* a, int val) { // CHECK: @test_stwcx - // CHECK: %1 = bitcast i32* %0 to i8* - // CHECK: %2 = load i32, i32* %val.addr, align 4 - // CHECK: %3 = call i32 @llvm.ppc.stwcx(i8* %1, i32 %2) + // CHECK: %0 = bitcast i32* %a to i8* + // CHECK: %1 = tail call i32 @llvm.ppc.stwcx(i8* %0, i32 %val) return __stwcx(a, val); } 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 @@ -1565,9 +1565,5 @@ def int_ppc_stwcx : GCCBuiltin<"__builtin_ppc_stwcx">, Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], [IntrWriteMem]>; - def int_ppc_lwarx : GCCBuiltin<"__builtin_ppc_lwarx">, - Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; - def int_ppc_ldarx : GCCBuiltin<"__builtin_ppc_ldarx">, - Intrinsic<[llvm_i64_ty], [llvm_ptr_ty], [IntrNoMem]>; } diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td --- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td +++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td @@ -1723,8 +1723,6 @@ def : Pat<(int_ppc_stdcx ForceXForm:$dst, g8rc:$A), (STDCX g8rc:$A, ForceXForm:$dst)>; -def : Pat<(int_ppc_ldarx ForceXForm:$dst), - (LDARX ForceXForm:$dst)>; def : Pat<(int_ppc_tdw g8rc:$A, g8rc:$B, i32:$IMM), (TD $IMM, $A, $B)>; 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 @@ -5413,8 +5413,6 @@ def : Pat<(i64 (bitreverse i64:$A)), (OR8 (RLDICR DWBytes7654.DWord, 32, 31), DWBytes3210.DWord)>; -def : Pat<(int_ppc_lwarx ForceXForm:$dst), - (LWARX ForceXForm:$dst)>; def : Pat<(int_ppc_stwcx ForceXForm:$dst, gprc:$A), (STWCX gprc:$A, ForceXForm:$dst)>; def : Pat<(int_ppc_tw gprc:$A, gprc:$B, i32:$IMM), diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64bit-only.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64bit-only.ll --- a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64bit-only.ll +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64bit-only.ll @@ -10,17 +10,18 @@ define dso_local i64 @test_ldarx(i64* readnone %a) { ; CHECK-LABEL: test_ldarx: ; CHECK: # %bb.0: # %entry +; CHECK-NEXT: #APP ; CHECK-NEXT: ldarx 3, 0, 3 +; CHECK-NEXT: #NO_APP ; CHECK-NEXT: blr entry: - %0 = bitcast i64* %a to i8* - %1 = tail call i64 @llvm.ppc.ldarx(i8* %0) - ret i64 %1 + %0 = call i64 asm sideeffect "ldarx $0, ${1:y}", "=r,*Z,~{memory}"(i64* %a) + ret i64 %0 } declare i32 @llvm.ppc.stdcx(i8*, i64) -define dso_local i64 @test(i64* %a, i64 %b) { -; CHECK-LABEL: test: +define dso_local i64 @test_stdcx(i64* %a, i64 %b) { +; CHECK-LABEL: test_stdcx: ; CHECK: # %bb.0: # %entry ; CHECK-NEXT: stdcx. 4, 0, 3 ; CHECK-NEXT: mfocrf 3, 128 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 @@ -12,18 +12,21 @@ define dso_local signext i32 @test_lwarx(i32* readnone %a) { ; CHECK-64-LABEL: test_lwarx: ; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: #APP ; CHECK-64-NEXT: lwarx 3, 0, 3 +; CHECK-64-NEXT: #NO_APP ; CHECK-64-NEXT: extsw 3, 3 ; CHECK-64-NEXT: blr ; ; CHECK-32-LABEL: test_lwarx: ; CHECK-32: # %bb.0: # %entry +; CHECK-32-NEXT: #APP ; CHECK-32-NEXT: lwarx 3, 0, 3 +; CHECK-32-NEXT: #NO_APP ; CHECK-32-NEXT: blr entry: - %0 = bitcast i32* %a to i8* - %1 = tail call i32 @llvm.ppc.lwarx(i8* %0) - ret i32 %1 + %0 = call i32 asm sideeffect "lwarx $0, ${1:y}", "=r,*Z,~{memory}"(i32* %a) + ret i32 %0 } declare i32 @llvm.ppc.stwcx(i8*, i32)