[PowerPC] Implement XL compact math builtins

Implement a subset of builtins required for compatiblilty with AIX XL compiler.

Reviewed By: nemanjai

Differential Revision: https://reviews.llvm.org/D105930
This commit is contained in:
Lei Huang 2021-07-13 14:32:36 -05:00
parent b910a109f8
commit c8937b6cb9
13 changed files with 625 additions and 8 deletions

View File

@ -29,7 +29,7 @@
#define UNALIASED_CUSTOM_BUILTIN(ID, TYPES, ACCUMULATE) \
CUSTOM_BUILTIN(ID, ID, TYPES, ACCUMULATE)
// builtins for compatibility with the XL compiler
// XL Compatibility built-ins
BUILTIN(__builtin_ppc_popcntb, "ULiULi", "")
BUILTIN(__builtin_ppc_poppar4, "iUi", "")
BUILTIN(__builtin_ppc_poppar8, "iULLi", "")
@ -97,6 +97,21 @@ BUILTIN(__builtin_ppc_load8r, "ULLiULLi*", "")
BUILTIN(__builtin_ppc_store2r, "vUiUs*", "")
BUILTIN(__builtin_ppc_store4r, "vUiUi*", "")
BUILTIN(__builtin_ppc_store8r, "vULLiULLi*", "")
BUILTIN(__builtin_ppc_extract_exp, "Uid", "")
BUILTIN(__builtin_ppc_extract_sig, "ULLid", "")
BUILTIN(__builtin_ppc_mtfsb0, "vUIi", "")
BUILTIN(__builtin_ppc_mtfsb1, "vUIi", "")
BUILTIN(__builtin_ppc_mtfsf, "vUIiUi", "")
BUILTIN(__builtin_ppc_mtfsfi, "vUIiUIi", "")
BUILTIN(__builtin_ppc_insert_exp, "ddULLi", "")
BUILTIN(__builtin_ppc_fmsub, "dddd", "")
BUILTIN(__builtin_ppc_fmsubs, "ffff", "")
BUILTIN(__builtin_ppc_fnmadd, "dddd", "")
BUILTIN(__builtin_ppc_fnmadds, "ffff", "")
BUILTIN(__builtin_ppc_fnmsub, "dddd", "")
BUILTIN(__builtin_ppc_fnmsubs, "ffff", "")
BUILTIN(__builtin_ppc_fre, "dd", "")
BUILTIN(__builtin_ppc_fres, "ff", "")
BUILTIN(__builtin_ppc_get_timebase, "ULLi", "n")

View File

@ -151,6 +151,21 @@ static void defineXLCompatMacros(MacroBuilder &Builder) {
Builder.defineMacro("__store2r", "__builtin_ppc_store2r");
Builder.defineMacro("__store4r", "__builtin_ppc_store4r");
Builder.defineMacro("__store8r", "__builtin_ppc_store8r");
Builder.defineMacro("__extract_exp", "__builtin_ppc_extract_exp");
Builder.defineMacro("__extract_sig", "__builtin_ppc_extract_sig");
Builder.defineMacro("__mtfsb0", "__builtin_ppc_mtfsb0");
Builder.defineMacro("__mtfsb1", "__builtin_ppc_mtfsb1");
Builder.defineMacro("__mtfsf", "__builtin_ppc_mtfsf");
Builder.defineMacro("__mtfsfi", "__builtin_ppc_mtfsfi");
Builder.defineMacro("__insert_exp", "__builtin_ppc_insert_exp");
Builder.defineMacro("__fmsub", "__builtin_ppc_fmsub");
Builder.defineMacro("__fmsubs", "__builtin_ppc_fmsubs");
Builder.defineMacro("__fnmadd", "__builtin_ppc_fnmadd");
Builder.defineMacro("__fnmadds", "__builtin_ppc_fnmadds");
Builder.defineMacro("__fnmsub", "__builtin_ppc_fnmsub");
Builder.defineMacro("__fnmsubs", "__builtin_ppc_fnmsubs");
Builder.defineMacro("__fre", "__builtin_ppc_fre");
Builder.defineMacro("__fres", "__builtin_ppc_fres");
}
/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific

View File

@ -3278,6 +3278,8 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
case PPC::BI__builtin_ppc_maddld:
case PPC::BI__builtin_ppc_load8r:
case PPC::BI__builtin_ppc_store8r:
case PPC::BI__builtin_ppc_insert_exp:
case PPC::BI__builtin_ppc_extract_sig:
return true;
}
return false;
@ -3414,6 +3416,19 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo &TI, unsigned BuiltinID,
case PPC::BI__builtin_ppc_rldimi:
return SemaBuiltinConstantArg(TheCall, 2, Result) ||
SemaValueIsRunOfOnes(TheCall, 3);
case PPC::BI__builtin_ppc_extract_exp:
case PPC::BI__builtin_ppc_extract_sig:
case PPC::BI__builtin_ppc_insert_exp:
return SemaFeatureCheck(*this, TheCall, "power9-vector",
diag::err_ppc_builtin_only_on_arch, "9");
case PPC::BI__builtin_ppc_mtfsb0:
case PPC::BI__builtin_ppc_mtfsb1:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 31);
case PPC::BI__builtin_ppc_mtfsf:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 255);
case PPC::BI__builtin_ppc_mtfsfi:
return SemaBuiltinConstantArgRange(TheCall, 0, 0, 7) ||
SemaBuiltinConstantArgRange(TheCall, 1, 0, 15);
#define CUSTOM_BUILTIN(Name, Intr, Types, Acc) \
case PPC::BI__builtin_##Name: \
return SemaBuiltinPPCMMACall(TheCall, Types);

View File

@ -43,3 +43,20 @@ void test_builtin_ppc_rlwnm() {
res = __builtin_ppc_rlwnm(ui, 31, mask); // expected-error {{argument to '__builtin_ppc_rlwnm' must be a constant integer}}
res = __builtin_ppc_rlwnm(ui, 31, 0xFF0F0F00); // expected-error {{argument 2 value should represent a contiguous bit field}}
}
extern unsigned int usi;
extern double d;
extern float f;
void testMathBuiltin(void) {
__mtfsb0(usi); //expected-error {{argument to '__builtin_ppc_mtfsb0' must be a constant integer}}
__mtfsb0(32); //expected-error {{argument value 32 is outside the valid range [0, 31]}}
__mtfsb1(usi); //expected-error {{argument to '__builtin_ppc_mtfsb1' must be a constant integer}}
__mtfsb1(45); //expected-error {{argument value 45 is outside the valid range [0, 31]}}
__mtfsf(usi, usi); //expected-error {{argument to '__builtin_ppc_mtfsf' must be a constant integer}}
__mtfsf(350, usi); //expected-error {{argument value 350 is outside the valid range [0, 255]}}
__mtfsfi(usi, 0); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}}
__mtfsfi(0, usi); //expected-error {{argument to '__builtin_ppc_mtfsfi' must be a constant integer}}
__mtfsfi(8, 0); //expected-error {{argument value 8 is outside the valid range [0, 7]}}
__mtfsfi(5, 24); //expected-error {{argument value 24 is outside the valid range [0, 15]}}
}

View File

@ -0,0 +1,143 @@
// RUN: %clang_cc1 -triple powerpc64-unknown-unknown -emit-llvm %s \
// RUN: -target-cpu pwr7 -o - | FileCheck %s
// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown -emit-llvm %s \
// RUN: -target-cpu pwr8 -o - | FileCheck %s
// RUN: %clang_cc1 -triple powerpc64-unknown-aix -emit-llvm %s \
// RUN: -target-cpu pwr7 -o - | FileCheck %s
// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm %s \
// RUN: -target-cpu pwr7 -o - | FileCheck %s
// CHECK-LABEL: @mtfsb0(
// CHECK: call void @llvm.ppc.mtfsb0(i32 10)
// CHECK-NEXT: ret void
//
void mtfsb0 () {
__mtfsb0 (10);
}
// CHECK-LABEL: @mtfsb1(
// CHECK: call void @llvm.ppc.mtfsb1(i32 0)
// CHECK-NEXT: ret void
//
void mtfsb1 () {
__mtfsb1 (0);
}
// CHECK-LABEL: @mtfsf(
// CHECK: [[UI_ADDR:%.*]] = alloca i32, align 4
// CHECK-NEXT: store i32 [[UI:%.*]], i32* [[UI_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[UI_ADDR]], align 4
// CHECK-NEXT: call void @llvm.ppc.mtfsf(i32 8, i32 [[TMP0]])
// CHECK-NEXT: ret void
//
void mtfsf (unsigned int ui) {
__mtfsf (8, ui);
}
// CHECK-LABEL: @mtfsfi(
// CHECK: call void @llvm.ppc.mtfsfi(i32 7, i32 15)
// CHECK-NEXT: ret void
//
void mtfsfi () {
__mtfsfi (7, 15);
}
// CHECK-LABEL: @fmsub(
// CHECK: [[D_ADDR:%.*]] = alloca double, align 8
// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]])
// CHECK-NEXT: ret double [[TMP3]]
//
double fmsub (double d) {
return __fmsub (d, d, d);
}
// CHECK-LABEL: @fmsubs(
// CHECK: [[F_ADDR:%.*]] = alloca float, align 4
// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]])
// CHECK-NEXT: ret float [[TMP3]]
//
float fmsubs (float f) {
return __fmsubs (f, f, f);
}
// CHECK-LABEL: @fnmadd(
// CHECK: [[D_ADDR:%.*]] = alloca double, align 8
// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fnmadd(double [[TMP0]], double [[TMP1]], double [[TMP2]])
// CHECK-NEXT: ret double [[TMP3]]
//
double fnmadd (double d) {
return __fnmadd (d, d, d);
}
// CHECK-LABEL: @fnmadds(
// CHECK: [[F_ADDR:%.*]] = alloca float, align 4
// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fnmadds(float [[TMP0]], float [[TMP1]], float [[TMP2]])
// CHECK-NEXT: ret float [[TMP3]]
//
float fnmadds (float f) {
return __fnmadds (f, f, f);
}
// CHECK-LABEL: @fnmsub(
// CHECK: [[D_ADDR:%.*]] = alloca double, align 8
// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP2:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fnmsub(double [[TMP0]], double [[TMP1]], double [[TMP2]])
// CHECK-NEXT: ret double [[TMP3]]
//
double fnmsub (double d) {
return __fnmsub (d, d, d);
}
// CHECK-LABEL: @fnmsubs(
// CHECK: [[F_ADDR:%.*]] = alloca float, align 4
// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP2:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fnmsubs(float [[TMP0]], float [[TMP1]], float [[TMP2]])
// CHECK-NEXT: ret float [[TMP3]]
//
float fnmsubs (float f) {
return __fnmsubs (f, f, f);
}
// CHECK-LABEL: @fre(
// CHECK: [[D_ADDR:%.*]] = alloca double, align 8
// CHECK-NEXT: store double [[D:%.*]], double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP0:%.*]] = load double, double* [[D_ADDR]], align 8
// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ppc.fre(double [[TMP0]])
// CHECK-NEXT: ret double [[TMP1]]
//
double fre (double d) {
return __fre (d);
}
// CHECK-LABEL: @fres(
// CHECK: [[F_ADDR:%.*]] = alloca float, align 4
// CHECK-NEXT: store float [[F:%.*]], float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP0:%.*]] = load float, float* [[F_ADDR]], align 4
// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ppc.fres(float [[TMP0]])
// CHECK-NEXT: ret float [[TMP1]]
//
float fres (float f) {
return __fres (f);
}

View File

@ -60,3 +60,23 @@ unsigned long long test_builtin_ppc_maddld_unsigned() {
// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs
return __builtin_ppc_maddld(ull, ull, ull);
}
unsigned long long extract_sig (double d) {
// CHECK-LABEL: @extract_sig(
// CHECK: [[TMP1:%.*]] = call i64 @llvm.ppc.extract.sig(double %0)
// CHECK-NEXT: ret i64 [[TMP1]]
//
// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs
return __extract_sig (d);
}
double insert_exp (double d, unsigned long long ull) {
// CHECK-LABEL: @insert_exp(
// CHECK: [[TMP2:%.*]] = call double @llvm.ppc.insert.exp(double %0, i64 %1)
// CHECK-NEXT: ret double [[TMP2]]
//
// CHECK-32-ERROR: error: this builtin is only available on 64-bit targets
// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs
return __insert_exp (d, ull);
}

View File

@ -19,3 +19,11 @@ int test_builtin_ppc_cmprb() {
// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs
return __builtin_ppc_cmprb(0, ui, ui) + __builtin_ppc_cmprb(1, ui, ui);
}
unsigned int extract_exp (double d) {
// CHECK-LABEL: @extract_exp
// CHECK: [[TMP1:%.*]] = call i32 @llvm.ppc.extract.exp(double %0)
// CHECK-NEXT: ret i32 [[TMP1]]
// CHECK-NONPWR9-ERR: error: this builtin is only valid on POWER9 or later CPUs
return __extract_exp (d);
}

View File

@ -1618,6 +1618,69 @@ let TargetPrefix = "ppc" in {
def int_ppc_store8r
: GCCBuiltin<"__builtin_ppc_store8r">,
Intrinsic<[], [llvm_i64_ty, llvm_ptr_ty], [IntrWriteMem]>;
def int_ppc_insert_exp
: GCCBuiltin<"__builtin_ppc_insert_exp">,
Intrinsic <[llvm_double_ty], [llvm_double_ty, llvm_i64_ty],
[IntrNoMem]>;
def int_ppc_extract_exp
: GCCBuiltin<"__builtin_ppc_extract_exp">,
Intrinsic <[llvm_i32_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_extract_sig
: GCCBuiltin<"__builtin_ppc_extract_sig">,
Intrinsic <[llvm_i64_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_mtfsb0
: GCCBuiltin<"__builtin_ppc_mtfsb0">,
Intrinsic <[], [llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
def int_ppc_mtfsb1
: GCCBuiltin<"__builtin_ppc_mtfsb1">,
Intrinsic <[], [llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
def int_ppc_mtfsf
: GCCBuiltin<"__builtin_ppc_mtfsf">,
Intrinsic <[], [llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects, ImmArg<ArgIndex<0>>]>;
def int_ppc_mtfsfi
: GCCBuiltin<"__builtin_ppc_mtfsfi">,
Intrinsic <[], [llvm_i32_ty, llvm_i32_ty],
[IntrNoMem, IntrHasSideEffects,
ImmArg<ArgIndex<0>>,ImmArg<ArgIndex<1>>]>;
def int_ppc_fmsub
: GCCBuiltin<"__builtin_ppc_fmsub">,
Intrinsic <[llvm_double_ty],
[llvm_double_ty, llvm_double_ty, llvm_double_ty],
[IntrNoMem]>;
def int_ppc_fmsubs
: GCCBuiltin<"__builtin_ppc_fmsubs">,
Intrinsic <[llvm_float_ty],
[llvm_float_ty, llvm_float_ty, llvm_float_ty],
[IntrNoMem]>;
def int_ppc_fnmadd
: GCCBuiltin<"__builtin_ppc_fnmadd">,
Intrinsic <[llvm_double_ty],
[llvm_double_ty, llvm_double_ty, llvm_double_ty],
[IntrNoMem]>;
def int_ppc_fnmadds
: GCCBuiltin<"__builtin_ppc_fnmadds">,
Intrinsic <[llvm_float_ty],
[llvm_float_ty, llvm_float_ty, llvm_float_ty],
[IntrNoMem]>;
def int_ppc_fnmsub
: GCCBuiltin<"__builtin_ppc_fnmsub">,
Intrinsic <[llvm_double_ty],
[llvm_double_ty, llvm_double_ty, llvm_double_ty],
[IntrNoMem]>;
def int_ppc_fnmsubs
: GCCBuiltin<"__builtin_ppc_fnmsubs">,
Intrinsic <[llvm_float_ty],
[llvm_float_ty, llvm_float_ty, llvm_float_ty],
[IntrNoMem]>;
def int_ppc_fre
: GCCBuiltin<"__builtin_ppc_fre">,
Intrinsic <[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>;
def int_ppc_fres
: GCCBuiltin<"__builtin_ppc_fres">,
Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>;
}
//===----------------------------------------------------------------------===//

View File

@ -3089,12 +3089,16 @@ let Uses = [RM], mayRaiseFPException = 1 in {
// When FM is 30/31, we are setting the 62/63 bit of FPSCR, the implicit-def
// RM should be set.
let hasSideEffects = 1 in {
def MTFSB0 : XForm_43<63, 70, (outs), (ins u5imm:$FM),
"mtfsb0 $FM", IIC_IntMTFSB0, []>,
"mtfsb0 $FM", IIC_IntMTFSB0,
[(int_ppc_mtfsb0 timm:$FM)]>,
PPC970_DGroup_Single, PPC970_Unit_FPU;
def MTFSB1 : XForm_43<63, 38, (outs), (ins u5imm:$FM),
"mtfsb1 $FM", IIC_IntMTFSB0, []>,
"mtfsb1 $FM", IIC_IntMTFSB0,
[(int_ppc_mtfsb1 timm:$FM)]>,
PPC970_DGroup_Single, PPC970_Unit_FPU;
}
let Defs = [RM] in {
let isCodeGenOnly = 1 in
@ -3647,6 +3651,16 @@ def : Pat<(fcopysign f32:$frB, f64:$frA),
(FCPSGNS (COPY_TO_REGCLASS $frA, F4RC), $frB)>;
}
// XL Compat intrinsics.
def : Pat<(int_ppc_fmsub f64:$A, f64:$B, f64:$C), (FMSUB $A, $B, $C)>;
def : Pat<(int_ppc_fmsubs f32:$A, f32:$B, f32:$C), (FMSUBS $A, $B, $C)>;
def : Pat<(int_ppc_fnmsub f64:$A, f64:$B, f64:$C), (FNMSUB $A, $B, $C)>;
def : Pat<(int_ppc_fnmsubs f32:$A, f32:$B, f32:$C), (FNMSUBS $A, $B, $C)>;
def : Pat<(int_ppc_fnmadd f64:$A, f64:$B, f64:$C), (FNMADD $A, $B, $C)>;
def : Pat<(int_ppc_fnmadds f32:$A, f32:$B, f32:$C), (FNMADDS $A, $B, $C)>;
def : Pat<(int_ppc_fre f64:$A), (FRE $A)>;
def : Pat<(int_ppc_fres f32:$A), (FRES $A)>;
include "PPCInstrAltivec.td"
include "PPCInstrSPE.td"
include "PPCInstr64Bit.td"

View File

@ -1539,10 +1539,10 @@ let Predicates = [HasVSX, HasP9Vector] in {
// Insert Exponent DP/QP
// XT NOTE: XT.dword[1] = 0xUUUU_UUUU_UUUU_UUUU
def XSIEXPDP : XX1Form <60, 918, (outs vsrc:$XT), (ins g8rc:$rA, g8rc:$rB),
"xsiexpdp $XT, $rA, $rB", IIC_VecFP, []>;
// FIXME: Setting the hasSideEffects flag here to match current behaviour.
let hasSideEffects = 1 in {
def XSIEXPDP : XX1Form <60, 918, (outs vsrc:$XT), (ins g8rc:$rA, g8rc:$rB),
"xsiexpdp $XT, $rA, $rB", IIC_VecFP, []>;
// vB NOTE: only vB.dword[0] is used, that's why we don't use
// X_VT5_VA5_VB5 form
def XSIEXPQP : XForm_18<63, 868, (outs vrrc:$vT), (ins vrrc:$vA, vsfrc:$vB),
@ -1550,11 +1550,11 @@ let Predicates = [HasVSX, HasP9Vector] in {
}
// Extract Exponent/Significand DP/QP
def XSXEXPDP : XX2_RT5_XO5_XB6<60, 0, 347, "xsxexpdp", []>;
def XSXSIGDP : XX2_RT5_XO5_XB6<60, 1, 347, "xsxsigdp", []>;
// FIXME: Setting the hasSideEffects flag here to match current behaviour.
let hasSideEffects = 1 in {
def XSXEXPDP : XX2_RT5_XO5_XB6<60, 0, 347, "xsxexpdp", []>;
def XSXSIGDP : XX2_RT5_XO5_XB6<60, 1, 347, "xsxsigdp", []>;
def XSXEXPQP : X_VT5_XO5_VB5 <63, 2, 804, "xsxexpqp", []>;
def XSXSIGQP : X_VT5_XO5_VB5 <63, 18, 804, "xsxsigqp", []>;
}
@ -2851,6 +2851,12 @@ def : Pat<(v2i64 (PPCvcmp_rec v2i64:$vA, v2i64:$vB, 711)),
def : Pat<(v2i64 (PPCvcmp_rec v2i64:$vA, v2i64:$vB, 199)),
(VCMPGTUB_rec DblwdCmp.MRGEQ, (v2i64 (XXLXORz)))>;
} // AddedComplexity = 0
// XL Compat builtins.
def : Pat<(int_ppc_fmsub f64:$A, f64:$B, f64:$C), (XSMSUBMDP $A, $B, $C)>;
def : Pat<(int_ppc_fnmsub f64:$A, f64:$B, f64:$C), (XSNMSUBMDP $A, $B, $C)>;
def : Pat<(int_ppc_fnmadd f64:$A, f64:$B, f64:$C), (XSNMADDMDP $A, $B, $C)>;
def : Pat<(int_ppc_fre f64:$A), (XSREDP $A)>;
} // HasVSX
// Any big endian VSX subtarget.
@ -3246,6 +3252,18 @@ def : Pat<(v8i16 (bitconvert (v16i8 immAllOnesV))),
(v8i16 (COPY_TO_REGCLASS(XXLEQVOnes), VSRC))>;
def : Pat<(v16i8 (bitconvert (v16i8 immAllOnesV))),
(v16i8 (COPY_TO_REGCLASS(XXLEQVOnes), VSRC))>;
// XL Compat builtins.
def : Pat<(int_ppc_fmsubs f32:$A, f32:$B, f32:$C), (XSMSUBMSP $A, $B, $C)>;
def : Pat<(int_ppc_fnmsubs f32:$A, f32:$B, f32:$C), (XSNMSUBMSP $A, $B, $C)>;
def : Pat<(int_ppc_fnmadds f32:$A, f32:$B, f32:$C), (XSNMADDMSP $A, $B, $C)>;
def : Pat<(int_ppc_fres f32:$A), (XSRESP $A)>;
def : Pat<(i32 (int_ppc_extract_exp f64:$A)),
(EXTRACT_SUBREG (XSXEXPDP (COPY_TO_REGCLASS $A, VSFRC)), sub_32)>;
def : Pat<(int_ppc_extract_sig f64:$A),
(XSXSIGDP (COPY_TO_REGCLASS $A, VSFRC))>;
def : Pat<(f64 (int_ppc_insert_exp f64:$A, i64:$B)),
(COPY_TO_REGCLASS (XSIEXPDP (COPY_TO_REGCLASS $A, G8RC), $B), F8RC)>;
} // HasVSX, HasP8Vector
// Any big endian Power8 VSX subtarget.

View File

@ -0,0 +1,231 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu < %s |\
; RUN: FileCheck %s --check-prefix=CHECK-PWR8
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mattr=-vsx < %s | FileCheck %s --check-prefix=CHECK-NOVSX
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-PWR7
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix -mcpu=pwr7 \
; RUN: < %s | FileCheck %s --check-prefix=CHECK-PWR7
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix -mcpu=pwr8 < %s |\
; RUN: FileCheck %s --check-prefix=CHECK-PWR8
define dso_local void @mtfsb0() {
; CHECK-PWR8-LABEL: mtfsb0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: mtfsb0 10
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: mtfsb0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: mtfsb0 10
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: mtfsb0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: mtfsb0 10
; CHECK-PWR7-NEXT: blr
entry:
tail call void @llvm.ppc.mtfsb0(i32 10)
ret void
}
declare void @llvm.ppc.mtfsb0(i32 immarg) #1
define dso_local void @mtfsb1() {
; CHECK-PWR8-LABEL: mtfsb1:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: mtfsb1 0
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: mtfsb1:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: mtfsb1 0
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: mtfsb1:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: mtfsb1 0
; CHECK-PWR7-NEXT: blr
entry:
tail call void @llvm.ppc.mtfsb1(i32 0)
ret void
}
declare void @llvm.ppc.mtfsb1(i32 immarg) #1
define dso_local double @fmsub_t0(double %d, double %d2, double %d3) {
; CHECK-PWR8-LABEL: fmsub_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsmsubmdp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fmsub_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fmsub 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fmsub_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: xsmsubmdp 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call double @llvm.ppc.fmsub(double %d, double %d2, double %d3)
ret double %0
}
declare double @llvm.ppc.fmsub(double, double, double)
define dso_local float @fmsubs_t0(float %f, float %f2, float %f3) {
; CHECK-PWR8-LABEL: fmsubs_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsmsubmsp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fmsubs_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fmsubs 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fmsubs_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: fmsubs 1, 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call float @llvm.ppc.fmsubs(float %f, float %f2, float %f3)
ret float %0
}
declare float @llvm.ppc.fmsubs(float, float, float)
define dso_local double @fnmadd_t0(double %d, double %d2, double %d3) {
; CHECK-PWR8-LABEL: fnmadd_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsnmaddmdp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fnmadd_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fnmadd 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fnmadd_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: xsnmaddmdp 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call double @llvm.ppc.fnmadd(double %d, double %d2, double %d3)
ret double %0
}
declare double @llvm.ppc.fnmadd(double, double, double)
define dso_local float @fnmadds_t0(float %f, float %f2, float %f3) {
; CHECK-PWR8-LABEL: fnmadds_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsnmaddmsp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fnmadds_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fnmadds 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fnmadds_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: fnmadds 1, 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call float @llvm.ppc.fnmadds(float %f, float %f2, float %f3)
ret float %0
}
declare float @llvm.ppc.fnmadds(float, float, float)
define dso_local double @fnmsub_t0(double %d, double %d2, double %d3) {
; CHECK-PWR8-LABEL: fnmsub_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsnmsubmdp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fnmsub_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fnmsub 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fnmsub_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: xsnmsubmdp 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call double @llvm.ppc.fnmsub(double %d, double %d2, double %d3)
ret double %0
}
declare double @llvm.ppc.fnmsub(double, double, double)
define dso_local float @fnmsubs_t0(float %f, float %f2, float %f3) {
; CHECK-PWR8-LABEL: fnmsubs_t0:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsnmsubmsp 1, 2, 3
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fnmsubs_t0:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fnmsubs 1, 1, 2, 3
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fnmsubs_t0:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: fnmsubs 1, 1, 2, 3
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call float @llvm.ppc.fnmsubs(float %f, float %f2, float %f3)
ret float %0
}
declare float @llvm.ppc.fnmsubs(float, float, float)
define dso_local double @fre(double %d) {
; CHECK-PWR8-LABEL: fre:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsredp 1, 1
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fre:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fre 1, 1
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fre:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: xsredp 1, 1
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call double @llvm.ppc.fre(double %d)
ret double %0
}
declare double @llvm.ppc.fre(double)
define dso_local float @fres(float %f) {
; CHECK-PWR8-LABEL: fres:
; CHECK-PWR8: # %bb.0: # %entry
; CHECK-PWR8-NEXT: xsresp 1, 1
; CHECK-PWR8-NEXT: blr
;
; CHECK-NOVSX-LABEL: fres:
; CHECK-NOVSX: # %bb.0: # %entry
; CHECK-NOVSX-NEXT: fres 1, 1
; CHECK-NOVSX-NEXT: blr
;
; CHECK-PWR7-LABEL: fres:
; CHECK-PWR7: # %bb.0: # %entry
; CHECK-PWR7-NEXT: fres 1, 1
; CHECK-PWR7-NEXT: blr
entry:
%0 = tail call float @llvm.ppc.fres(float %f)
ret float %0
}
declare float @llvm.ppc.fres(float)

View File

@ -0,0 +1,31 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
define dso_local i64 @extract_sig(double %d) {
; CHECK-LABEL: extract_sig:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: xsxsigdp 3, 1
; CHECK-NEXT: blr
entry:
%0 = tail call i64 @llvm.ppc.extract.sig(double %d)
ret i64 %0
}
declare i64 @llvm.ppc.extract.sig(double)
define dso_local double @insert_exp(double %d, i64 %ull) {
; CHECK-LABEL: insert_exp:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: mffprd 3, 1
; CHECK-NEXT: xsiexpdp 1, 3, 4
; CHECK-NEXT: # kill: def $f1 killed $f1 killed $vsl1
; CHECK-NEXT: blr
entry:
%0 = tail call double @llvm.ppc.insert.exp(double %d, i64 %ull)
ret double %0
}
declare double @llvm.ppc.insert.exp(double, i64)

View File

@ -0,0 +1,27 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-linux-gnu \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-linux-gnu \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-aix \
; RUN: -mcpu=pwr9 < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \
; RUN: -mcpu=pwr9 < %s | FileCheck %s --check-prefix=CHECK-32BIT
define dso_local zeroext i32 @extract_exp(double %d) {
; CHECK-LABEL: extract_exp:
; CHECK: # %bb.0: # %entry
; CHECK-NEXT: xsxexpdp 3, 1
; CHECK-NEXT: clrldi 3, 3, 32
; CHECK-NEXT: blr
;
; CHECK-32BIT-LABEL: extract_exp:
; CHECK-32BIT: # %bb.0: # %entry
; CHECK-32BIT-NEXT: xsxexpdp 3, 1
; CHECK-32BIT-NEXT: # kill: def $r3 killed $r3 killed $x3
; CHECK-32BIT-NEXT: blr
entry:
%0 = tail call i32 @llvm.ppc.extract.exp(double %d)
ret i32 %0
}
declare i32 @llvm.ppc.extract.exp(double)