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 @@ -55,6 +55,10 @@ BUILTIN(__builtin_ppc_fetch_and_orlp, "ULiULiD*ULi", "") BUILTIN(__builtin_ppc_fetch_and_swap, "UiUiD*Ui", "") BUILTIN(__builtin_ppc_fetch_and_swaplp, "ULiULiD*ULi", "") +BUILTIN(__builtin_ppc_ldarx, "LiLiD*", "") +BUILTIN(__builtin_ppc_lwarx, "iiD*", "") +BUILTIN(__builtin_ppc_stdcx, "iLiD*Li", "") +BUILTIN(__builtin_ppc_stwcx, "iiD*i", "") BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n") 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 @@ -108,6 +108,10 @@ Builder.defineMacro("__fetch_and_orlp", "__builtin_ppc_fetch_and_orlp"); Builder.defineMacro("__fetch_and_swap", "__builtin_ppc_fetch_and_swap"); Builder.defineMacro("__fetch_and_swaplp", "__builtin_ppc_fetch_and_swaplp"); + Builder.defineMacro("__ldarx", "__builtin_ppc_ldarx"); + Builder.defineMacro("__lwarx", "__builtin_ppc_lwarx"); + Builder.defineMacro("__stdcx", "__builtin_ppc_stdcx"); + Builder.defineMacro("__stwcx", "__builtin_ppc_stwcx"); } /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific 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 @@ -3265,6 +3265,8 @@ case PPC::BI__builtin_divde: case PPC::BI__builtin_divdeu: case PPC::BI__builtin_bpermd: + case PPC::BI__builtin_ppc_ldarx: + case PPC::BI__builtin_ppc_stdcx: return true; } return false; 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 new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond-64bit-only.c @@ -0,0 +1,27 @@ +// 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: FileCheck %s --check-prefix=CHECK64 +// RUN: %clang_cc1 -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: -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) + // 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) + // 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 new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-LoadReseve-StoreCond.c @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -triple=powerpc-unknown-aix -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -emit-llvm %s -o - | \ +// RUN: FileCheck %s +// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -emit-llvm %s \ +// RUN: -o - | FileCheck %s +// RUN: %clang_cc1 -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) + 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) + return __stwcx(a, val); +} diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-error.c b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-error.c @@ -0,0 +1,17 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix -fsyntax-only \ +// RUN: -Wall -Werror -verify %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fsyntax-only \ +// RUN: -Wall -Werror -verify %s + +long long lla, llb; +int ia, ib; + +void test_trap(void) { + __tdw(lla, llb, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}} + __tw(ia, ib, 50); //expected-error {{argument value 50 is outside the valid range [0, 31]}} +} 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 @@ -1523,5 +1523,15 @@ Intrinsic<[],[],[]>; def int_ppc_iospace_eieio : GCCBuiltin<"__builtin_ppc_iospace_eieio">, Intrinsic<[],[],[]>; + def int_ppc_stdcx : GCCBuiltin<"__builtin_ppc_stdcx">, + Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i64_ty], + [IntrWriteMem]>; + 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 @@ -1720,3 +1720,8 @@ def SLBSYNC : XForm_0<31, 338, (outs), (ins), "slbsync", IIC_SprSLBSYNC, []>; } // IsISA3_0 + +def : Pat<(int_ppc_stdcx ForceXForm:$dst, g8rc:$A), + (STDCX g8rc:$A, ForceXForm:$dst)>; +def : Pat<(int_ppc_ldarx ForceXForm:$dst), + (LDARX ForceXForm:$dst)>; 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 @@ -5411,3 +5411,8 @@ // swap the high word and low word. 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)>; 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 new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64bit-only.ll @@ -0,0 +1,35 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK + +declare i64 @llvm.ppc.ldarx(i8*) +define dso_local i64 @test_ldarx(i64* readnone %a) { +; CHECK-LABEL: test_ldarx: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: ldarx 3, 0, 3 +; CHECK-NEXT: blr +entry: + %0 = bitcast i64* %a to i8* + %1 = tail call i64 @llvm.ppc.ldarx(i8* %0) + ret i64 %1 +} + +declare i32 @llvm.ppc.stdcx(i8*, i64) +define dso_local i64 @test(i64* %a, i64 %b) { +; CHECK-LABEL: test: +; CHECK: # %bb.0: # %entry +; CHECK-NEXT: stdcx. 4, 0, 3 +; CHECK-NEXT: mfocrf 3, 128 +; CHECK-NEXT: srwi 3, 3, 28 +; CHECK-NEXT: extsw 3, 3 +; CHECK-NEXT: blr +entry: + %0 = bitcast i64* %a to i8* + %1 = tail call i32 @llvm.ppc.stdcx(i8* %0, i64 %b) + %conv = sext i32 %1 to i64 + ret i64 %conv +} diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond.ll @@ -0,0 +1,49 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-64 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-64 +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-32 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-64 + +declare i32 @llvm.ppc.lwarx(i8*) +define dso_local signext i32 @test_lwarx(i32* readnone %a) { +; CHECK-64-LABEL: test_lwarx: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: lwarx 3, 0, 3 +; CHECK-64-NEXT: extsw 3, 3 +; CHECK-64-NEXT: blr +; +; CHECK-32-LABEL: test_lwarx: +; CHECK-32: # %bb.0: # %entry +; CHECK-32-NEXT: lwarx 3, 0, 3 +; CHECK-32-NEXT: blr +entry: + %0 = bitcast i32* %a to i8* + %1 = tail call i32 @llvm.ppc.lwarx(i8* %0) + ret i32 %1 +} + +declare i32 @llvm.ppc.stwcx(i8*, i32) +define dso_local signext i32 @test_stwcx(i32* %a, i32 signext %b) { +; CHECK-64-LABEL: test_stwcx: +; CHECK-64: # %bb.0: # %entry +; CHECK-64-NEXT: stwcx. 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_stwcx: +; CHECK-32: # %bb.0: # %entry +; CHECK-32-NEXT: stwcx. 4, 0, 3 +; CHECK-32-NEXT: mfocrf 3, 128 +; CHECK-32-NEXT: srwi 3, 3, 28 +; CHECK-32-NEXT: blr +entry: + %0 = bitcast i32* %a to i8* + %1 = tail call i32 @llvm.ppc.stwcx(i8* %0, i32 %b) + ret i32 %1 +}