[PowerPC] Implament Load and Reserve and Store Conditional Builtins

This patch implaments the load and reserve and store conditional
builtins for the PowerPC target, in order to have feature parody with
xlC on AIX.

Differential revision: https://reviews.llvm.org/D105236
This commit is contained in:
Albion Fung 2021-07-05 21:34:37 -05:00 committed by Albion Fung
parent 21106388eb
commit 7d10dd60ce
11 changed files with 180 additions and 0 deletions

View File

@ -55,6 +55,10 @@ BUILTIN(__builtin_ppc_fetch_and_or, "UiUiD*Ui", "")
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")

View File

@ -108,6 +108,10 @@ static void defineXLCompatMacros(MacroBuilder &Builder) {
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

View File

@ -3265,6 +3265,8 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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]}}
}

View File

@ -1523,5 +1523,15 @@ let TargetPrefix = "ppc" in {
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]>;
}

View File

@ -1720,3 +1720,8 @@ def SLBIEG : XForm_26<31, 466, (outs), (ins gprc:$RS, gprc:$RB),
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)>;

View File

@ -5411,3 +5411,8 @@ def DWBytes3210 {
// 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)>;

View File

@ -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
}

View File

@ -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
}