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.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,38 @@ +// RUN: %clang_cc1 -triple=powerpc-unknown-aix -O2 -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefix=CHECK +// RUN: %clang_cc1 -triple=powerpc64-unknown-aix -O2 -S -emit-llvm %s -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,CHECK64 +// RUN: %clang_cc1 -triple=powerpc64le-unknown-unknown -O2 -S -emit-llvm %s \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,CHECK64 +// RUN: %clang_cc1 -triple=powerpc64-unknown-unknown -O2 -S -emit-llvm %s \ +// RUN: -o - | FileCheck %s --check-prefixes=CHECK,CHECK64 + +int test_lwarx(volatile int* a) { + // CHECK: entry: + // CHECK: %0 = bitcast i32* %a to i8* + // CHECK: %1 = tail call i32 @llvm.ppc.lwarx(i8* %0) + return __lwarx(a); +} +// CHECK64: def +int test_stwcx(volatile int* a, int val) { + // CHECK: entry: + // CHECK: %0 = bitcast i32* %a to i8* + // CHECK: %1 = tail call i32 @llvm.ppc.stwcx(i8* %0, i32 %val) + return __stwcx(a, val); +} + +#ifdef __PPC64__ +long test_ldarx(volatile long* a) { + // CHECK64: entry: + // CHECK64: %0 = bitcast i64* %a to i8* + // CHECK64: %1 = tail call i64 @llvm.ppc.ldarx(i8* %0) + return __ldarx(a); +} + +int test_stdcx(volatile long* addr, long val) { + // CHECK64: entry: + // CHECK64: %0 = bitcast i64* %addr to i8* + // CHECK64: %1 = tail call i32 @llvm.ppc.stdcx(i8* %0, i64 %val) + return __stdcx(addr, val); +} +#endif 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,18 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc-unknown-aix -fsyntax-only \ +// RUN: -Wall -Werror -verify %s + +volatile long *lva; +volatile int *iva; +int ia; +long la; + +#ifndef __PPC64__ +void test_ldarx() { + long ret_la = __ldarx(lva); //expected-error {{this builtin is only available on 64-bit targets}} +} + +void test_stdcx() { + int ret_ia = __stdcx(lva, la); //expected-error {{this builtin is only available on 64-bit targets}} +} +#endif 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,13 @@ 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 xoaddr:$dst, g8rc:$A), + (STDCX g8rc:$A, xoaddr:$dst)>; +def : Pat<(int_ppc_ldarx xoaddr:$dst), + (LDARX xoaddr:$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 xoaddr:$dst), + (LWARX xoaddr:$dst)>; +def : Pat<(int_ppc_stwcx xoaddr:$dst, gprc:$A), + (STWCX gprc:$A, xoaddr:$dst)>; diff --git a/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64-only.ll b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64-only.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/builtins-ppc-xlcompat-LoadReserve-StoreCond-64-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) local_unnamed_addr #0 { +; 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) local_unnamed_addr #0 { +; 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) local_unnamed_addr #0 { +; 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) local_unnamed_addr #0 { +; 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 +}