1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 18:54:02 +01:00

[PowerPC] Implement trap and conversion builtins for XL compatibility

This patch implements trap and FP to and from double conversions. The builtins
generate code that mirror what is generated from the XL compiler. Intrinsics
are named conventionally with builtin_ppc, but are aliased to provide the same
builtin names as the XL compiler.

Differential Revision: https://reviews.llvm.org/D103668
This commit is contained in:
Albion Fung 2021-07-11 22:16:27 -05:00
parent 6ee8270ba3
commit 9cfb434c49
6 changed files with 428 additions and 1 deletions

View File

@ -112,9 +112,45 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.".
: GCCBuiltin<"__builtin_vsx_scalar_insert_exp_qp">, : GCCBuiltin<"__builtin_vsx_scalar_insert_exp_qp">,
Intrinsic <[llvm_f128_ty], [llvm_f128_ty, llvm_i64_ty], [IntrNoMem]>; Intrinsic <[llvm_f128_ty], [llvm_f128_ty, llvm_i64_ty], [IntrNoMem]>;
// Intrinsics defined to maintain XL compatibility
def int_ppc_tdw
: GCCBuiltin<"__builtin_ppc_tdw">,
Intrinsic <[], [llvm_i64_ty, llvm_i64_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
def int_ppc_tw
: GCCBuiltin<"__builtin_ppc_tw">,
Intrinsic <[], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], [ImmArg<ArgIndex<2>>]>;
def int_ppc_trapd
: GCCBuiltin<"__builtin_ppc_trapd">,
Intrinsic <[], [llvm_i64_ty], []>;
def int_ppc_trap
: GCCBuiltin<"__builtin_ppc_trap">,
Intrinsic <[], [llvm_i32_ty], []>;
def int_ppc_fcfid
: GCCBuiltin<"__builtin_ppc_fcfid">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fcfud
: GCCBuiltin<"__builtin_ppc_fcfud">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctid
: GCCBuiltin<"__builtin_ppc_fctid">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctidz
: GCCBuiltin<"__builtin_ppc_fctidz">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctiw
: GCCBuiltin<"__builtin_ppc_fctiw">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctiwz
: GCCBuiltin<"__builtin_ppc_fctiwz">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctudz
: GCCBuiltin<"__builtin_ppc_fctudz">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fctuwz
: GCCBuiltin<"__builtin_ppc_fctuwz">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
} }
let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.".
/// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics.
class PowerPC_Vec_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types, class PowerPC_Vec_Intrinsic<string GCCIntSuffix, list<LLVMType> ret_types,

View File

@ -1725,3 +1725,9 @@ def : Pat<(int_ppc_stdcx ForceXForm:$dst, g8rc:$A),
(STDCX g8rc:$A, ForceXForm:$dst)>; (STDCX g8rc:$A, ForceXForm:$dst)>;
def : Pat<(int_ppc_ldarx ForceXForm:$dst), def : Pat<(int_ppc_ldarx ForceXForm:$dst),
(LDARX ForceXForm:$dst)>; (LDARX ForceXForm:$dst)>;
def : Pat<(int_ppc_tdw g8rc:$A, g8rc:$B, i32:$IMM),
(TD $IMM, $A, $B)>;
// trapd
def : Pat<(int_ppc_trapd g8rc:$A),
(TDI 24, $A, 0)>;

View File

@ -5416,3 +5416,24 @@ def : Pat<(int_ppc_lwarx ForceXForm:$dst),
(LWARX ForceXForm:$dst)>; (LWARX ForceXForm:$dst)>;
def : Pat<(int_ppc_stwcx ForceXForm:$dst, gprc:$A), def : Pat<(int_ppc_stwcx ForceXForm:$dst, gprc:$A),
(STWCX gprc:$A, ForceXForm:$dst)>; (STWCX gprc:$A, ForceXForm:$dst)>;
def : Pat<(int_ppc_tw gprc:$A, gprc:$B, i32:$IMM),
(TW $IMM, $A, $B)>;
def : Pat<(int_ppc_trap gprc:$A),
(TWI 24, $A, 0)>;
def : Pat<(int_ppc_fcfid f64:$A),
(XSCVSXDDP $A)>;
def : Pat<(int_ppc_fcfud f64:$A),
(XSCVUXDDP $A)>;
def : Pat<(int_ppc_fctid f64:$A),
(FCTID $A)>;
def : Pat<(int_ppc_fctidz f64:$A),
(XSCVDPSXDS $A)>;
def : Pat<(int_ppc_fctiw f64:$A),
(FCTIW $A)>;
def : Pat<(int_ppc_fctiwz f64:$A),
(XSCVDPSXWS $A)>;
def : Pat<(int_ppc_fctudz f64:$A),
(XSCVDPUXDS $A)>;
def : Pat<(int_ppc_fctuwz f64:$A),
(XSCVDPUXWS $A)>;

View File

@ -0,0 +1,89 @@
; 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
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr7 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
; RUN: -mcpu=pwr7 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
; RUN: -mcpu=pwr7 < %s | FileCheck %s
declare double @llvm.ppc.fcfid(double %a)
define dso_local double @test_fcfid(double %a) {
; CHECK-LABEL: test_fcfid:
; CHECK: # %bb.0:
; CHECK-NEXT: xscvsxddp 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fcfid(double %a)
ret double %1
}
declare double @llvm.ppc.fcfud(double %a)
define dso_local double @test_fcfud(double %a) {
; CHECK-LABEL: test_fcfud:
; CHECK: # %bb.0:
; CHECK-NEXT: xscvuxddp 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fcfud(double %a)
ret double %1
}
declare double @llvm.ppc.fctid(double %a)
define dso_local double @test_fctid(double %a) {
; CHECK-LABEL: test_fctid:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}
declare double @llvm.ppc.fctidz(double %a)
define dso_local double @test_fctidz(double %a) {
; CHECK-LABEL: test_fctidz:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}
declare double @llvm.ppc.fctiw(double %a)
define dso_local double @test_fctiw(double %a) {
; CHECK-LABEL: test_fctiw:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}
declare double @llvm.ppc.fctiwz(double %a)
define dso_local double @test_fctiwz(double %a) {
; CHECK-LABEL: test_fctiwz:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}
declare double @llvm.ppc.fctudz(double %a)
define dso_local double @test_fctudz(double %a) {
; CHECK-LABEL: test_fctudz:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}
declare double @llvm.ppc.fctuwz(double %a)
define dso_local double @test_fctuwz(double %a) {
; CHECK-LABEL: test_fctuwz:
; CHECK: # %bb.0:
; CHECK-NEXT: fctid 1, 1
; CHECK-NEXT: blr
%1 = call double @llvm.ppc.fctid(double %a)
ret double %1
}

View File

@ -0,0 +1,136 @@
; 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
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr7 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
; RUN: -mcpu=pwr8 < %s | FileCheck %s
; tdw
declare void @llvm.ppc.tdw(i64 %a, i64 %b, i32 immarg)
define dso_local void @test__tdwlgt(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwlgt:
; CHECK: # %bb.0:
; CHECK-NEXT: tdlgt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 1)
ret void
}
define dso_local void @test__tdwllt(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwllt:
; CHECK: # %bb.0:
; CHECK-NEXT: tdllt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 2)
ret void
}
define dso_local void @test__tdw3(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdw3:
; CHECK: # %bb.0:
; CHECK-NEXT: td 3, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 3)
ret void
}
define dso_local void @test__tdweq(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdweq:
; CHECK: # %bb.0:
; CHECK-NEXT: tdeq 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 4)
ret void
}
define dso_local void @test__tdwlge(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwlge:
; CHECK: # %bb.0:
; CHECK-NEXT: td 5, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 5)
ret void
}
define dso_local void @test__tdwlle(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwlle:
; CHECK: # %bb.0:
; CHECK-NEXT: td 6, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 6)
ret void
}
define dso_local void @test__tdwgt(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwgt:
; CHECK: # %bb.0:
; CHECK-NEXT: tdgt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 8)
ret void
}
define dso_local void @test__tdwge(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwge:
; CHECK: # %bb.0:
; CHECK-NEXT: td 12, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 12)
ret void
}
define dso_local void @test__tdwlt(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwlt:
; CHECK: # %bb.0:
; CHECK-NEXT: tdlt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 16)
ret void
}
define dso_local void @test__tdwle(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwle:
; CHECK: # %bb.0:
; CHECK-NEXT: td 20, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 20)
ret void
}
define dso_local void @test__tdwne24(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdwne24:
; CHECK: # %bb.0:
; CHECK-NEXT: tdne 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 24)
ret void
}
define dso_local void @test__tdw31(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdw31:
; CHECK: # %bb.0:
; CHECK-NEXT: tdu 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 31)
ret void
}
define dso_local void @test__tdw_no_match(i64 %a, i64 %b) {
; CHECK-LABEL: test__tdw_no_match:
; CHECK: # %bb.0:
; CHECK-NEXT: td 13, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tdw(i64 %a, i64 %b, i32 13)
ret void
}
; trapd
declare void @llvm.ppc.trapd(i64 %a)
define dso_local void @test__trapd(i64 %a) {
; CHECK-LABEL: test__trapd:
; CHECK: # %bb.0:
; CHECK-NEXT: tdnei 3, 0
; CHECK-NEXT: blr
call void @llvm.ppc.trapd(i64 %a)
ret void
}

View File

@ -0,0 +1,139 @@
; 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
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr7 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
; RUN: -mcpu=pwr8 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
; RUN: -mcpu=pwr8 < %s | FileCheck %s
; tw
declare void @llvm.ppc.tw(i32 %a, i32 %b, i32 %c)
define dso_local void @test__twlgt(i32 %a, i32 %b) {
; CHECK-LABEL: test__twlgt:
; CHECK: # %bb.0:
; CHECK-NEXT: twlgt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 1)
ret void
}
define dso_local void @test__twllt(i32 %a, i32 %b) {
; CHECK-LABEL: test__twllt:
; CHECK: # %bb.0:
; CHECK-NEXT: twllt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 2)
ret void
}
define dso_local void @test__tw3(i32 %a, i32 %b) {
; CHECK-LABEL: test__tw3:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 3, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 3)
ret void
}
define dso_local void @test__tweq(i32 %a, i32 %b) {
; CHECK-LABEL: test__tweq:
; CHECK: # %bb.0:
; CHECK-NEXT: tweq 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 4)
ret void
}
define dso_local void @test__twlge(i32 %a, i32 %b) {
; CHECK-LABEL: test__twlge:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 5, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 5)
ret void
}
define dso_local void @test__twlle(i32 %a, i32 %b) {
; CHECK-LABEL: test__twlle:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 6, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 6)
ret void
}
define dso_local void @test__twgt(i32 %a, i32 %b) {
; CHECK-LABEL: test__twgt:
; CHECK: # %bb.0:
; CHECK-NEXT: twgt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 8)
ret void
}
define dso_local void @test__twge(i32 %a, i32 %b) {
; CHECK-LABEL: test__twge:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 12, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 12)
ret void
}
define dso_local void @test__twlt(i32 %a, i32 %b) {
; CHECK-LABEL: test__twlt:
; CHECK: # %bb.0:
; CHECK-NEXT: twlt 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 16)
ret void
}
define dso_local void @test__twle(i32 %a, i32 %b) {
; CHECK-LABEL: test__twle:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 20, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 20)
ret void
}
define dso_local void @test__twne24(i32 %a, i32 %b) {
; CHECK-LABEL: test__twne24:
; CHECK: # %bb.0:
; CHECK-NEXT: twne 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 24)
ret void
}
define dso_local void @test__twu(i32 %a, i32 %b) {
; CHECK-LABEL: test__twu:
; CHECK: # %bb.0:
; CHECK-NEXT: twu 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 31)
ret void
}
define dso_local void @test__tw_no_match(i32 %a, i32 %b) {
; CHECK-LABEL: test__tw_no_match:
; CHECK: # %bb.0:
; CHECK-NEXT: tw 13, 3, 4
; CHECK-NEXT: blr
call void @llvm.ppc.tw(i32 %a, i32 %b, i32 13)
ret void
}
; trap
declare void @llvm.ppc.trap(i32 %a)
define dso_local void @test__trap(i32 %a) {
; CHECK-LABEL: test__trap:
; CHECK: # %bb.0:
; CHECK-NEXT: twnei 3, 0
; CHECK-NEXT: blr
call void @llvm.ppc.trap(i32 %a)
ret void
}