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,
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);
}
}
// 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);
}
-// 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);
}
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]>;
}
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)>;
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),
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
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)