diff --git a/clang/include/clang/Basic/BuiltinsPPC.def b/clang/include/clang/Basic/BuiltinsPPC.def index 7d46cb96a302e1..1c68eaf2ec78e0 100644 --- a/clang/include/clang/Basic/BuiltinsPPC.def +++ b/clang/include/clang/Basic/BuiltinsPPC.def @@ -47,6 +47,21 @@ BUILTIN(__builtin_ppc_dcbt, "vv*", "") BUILTIN(__builtin_ppc_dcbtst, "vv*", "") BUILTIN(__builtin_ppc_dcbz, "vv*", "") BUILTIN(__builtin_ppc_icbt, "vv*", "") +BUILTIN(__builtin_ppc_fric, "dd", "") +BUILTIN(__builtin_ppc_frim, "dd", "") +BUILTIN(__builtin_ppc_frims, "ff", "") +BUILTIN(__builtin_ppc_frin, "dd", "") +BUILTIN(__builtin_ppc_frins, "ff", "") +BUILTIN(__builtin_ppc_frip, "dd", "") +BUILTIN(__builtin_ppc_frips, "ff", "") +BUILTIN(__builtin_ppc_friz, "dd", "") +BUILTIN(__builtin_ppc_frizs, "ff", "") +BUILTIN(__builtin_ppc_fsel, "dddd", "") +BUILTIN(__builtin_ppc_fsels, "ffff", "") +BUILTIN(__builtin_ppc_frsqrte, "dd", "") +BUILTIN(__builtin_ppc_frsqrtes, "ff", "") +BUILTIN(__builtin_ppc_fsqrt, "dd", "") +BUILTIN(__builtin_ppc_fsqrts, "ff", "") BUILTIN(__builtin_ppc_compare_and_swap, "iiD*i*i", "") BUILTIN(__builtin_ppc_compare_and_swaplp, "iLiD*Li*Li", "") BUILTIN(__builtin_ppc_fetch_and_add, "UiUiD*Ui", "") diff --git a/clang/lib/Basic/Targets/PPC.cpp b/clang/lib/Basic/Targets/PPC.cpp index a8dd6a3fb2ad61..86096dc0743b60 100644 --- a/clang/lib/Basic/Targets/PPC.cpp +++ b/clang/lib/Basic/Targets/PPC.cpp @@ -220,6 +220,21 @@ static void defineXLCompatMacros(MacroBuilder &Builder) { Builder.defineMacro("__mtmsr", "__builtin_ppc_mtmsr"); Builder.defineMacro("__mfspr", "__builtin_ppc_mfspr"); Builder.defineMacro("__mtspr", "__builtin_ppc_mtspr"); + Builder.defineMacro("__fric", "__builtin_ppc_fric"); + Builder.defineMacro("__frim", "__builtin_ppc_frim"); + Builder.defineMacro("__frims", "__builtin_ppc_frims"); + Builder.defineMacro("__frin", "__builtin_ppc_frin"); + Builder.defineMacro("__frins", "__builtin_ppc_frins"); + Builder.defineMacro("__frip", "__builtin_ppc_frip"); + Builder.defineMacro("__frips", "__builtin_ppc_frips"); + Builder.defineMacro("__friz", "__builtin_ppc_friz"); + Builder.defineMacro("__frizs", "__builtin_ppc_frizs"); + Builder.defineMacro("__fsel", "__builtin_ppc_fsel"); + Builder.defineMacro("__fsels", "__builtin_ppc_fsels"); + Builder.defineMacro("__frsqrte", "__builtin_ppc_frsqrte"); + Builder.defineMacro("__frsqrtes", "__builtin_ppc_frsqrtes"); + Builder.defineMacro("__fsqrt", "__builtin_ppc_fsqrt"); + Builder.defineMacro("__fsqrts", "__builtin_ppc_fsqrts"); } /// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 46316d0b295e15..cd86433cbf7515 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -15726,6 +15726,41 @@ Value *CodeGenFunction::EmitPPCBuiltinExpr(unsigned BuiltinID, Builder.getFastMathFlags() &= (FMF); return FDiv; } + case PPC::BI__builtin_ppc_fric: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::rint, + Intrinsic::experimental_constrained_rint)) + .getScalarVal(); + case PPC::BI__builtin_ppc_frim: + case PPC::BI__builtin_ppc_frims: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::floor, + Intrinsic::experimental_constrained_floor)) + .getScalarVal(); + case PPC::BI__builtin_ppc_frin: + case PPC::BI__builtin_ppc_frins: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::round, + Intrinsic::experimental_constrained_round)) + .getScalarVal(); + case PPC::BI__builtin_ppc_frip: + case PPC::BI__builtin_ppc_frips: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::ceil, + Intrinsic::experimental_constrained_ceil)) + .getScalarVal(); + case PPC::BI__builtin_ppc_friz: + case PPC::BI__builtin_ppc_frizs: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::trunc, + Intrinsic::experimental_constrained_trunc)) + .getScalarVal(); + case PPC::BI__builtin_ppc_fsqrt: + case PPC::BI__builtin_ppc_fsqrts: + return RValue::get(emitUnaryMaybeConstrainedFPBuiltin( + *this, E, Intrinsic::sqrt, + Intrinsic::experimental_constrained_sqrt)) + .getScalarVal(); } } diff --git a/clang/test/CodeGen/builtins-ppc-xlcompat-fp.c b/clang/test/CodeGen/builtins-ppc-xlcompat-fp.c new file mode 100644 index 00000000000000..a6c3c53c4b221f --- /dev/null +++ b/clang/test/CodeGen/builtins-ppc-xlcompat-fp.c @@ -0,0 +1,314 @@ +// REQUIRES: powerpc-registered-target +// RUN: %clang_cc1 -triple powerpc64le-unknown-unknown \ +// RUN: -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc64-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s +// RUN: %clang_cc1 -triple powerpc-unknown-aix \ +// RUN: -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s + +extern double a; +extern double b; +extern double c; +extern float d; +extern float e; +extern float f; + +// CHECK-LABEL: @test_fric( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.rint.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_fric() { + return __fric(a); +} + +// CHECK-LABEL: @test_frim( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.floor.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_frim() { + return __frim(a); +} + +// CHECK-LABEL: @test_frims( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.floor.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_frims() { + return __frims(d); +} + +// CHECK-LABEL: @test_frin( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.round.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_frin() { + return __frin(a); +} + +// CHECK-LABEL: @test_frins( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.round.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_frins() { + return __frins(d); +} + +// CHECK-LABEL: @test_frip( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.ceil.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_frip() { + return __frip(a); +} + +// CHECK-LABEL: @test_frips( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.ceil.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_frips() { + return __frips(d); +} + +// CHECK-LABEL: @test_friz( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.trunc.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_friz() { + return __friz(a); +} + +// CHECK-LABEL: @test_frizs( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.trunc.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_frizs() { + return __frizs(d); +} + +// CHECK-LABEL: @test_fsel( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @b, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* @c, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fsel(double [[TMP0]], double [[TMP1]], double [[TMP2]]) +// CHECK-NEXT: ret double [[TMP3]] +// +double test_fsel() { + return __fsel(a, b, c); +} + +// CHECK-LABEL: @test_fsels( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @e, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* @f, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fsels(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: ret float [[TMP3]] +// +float test_fsels() { + return __fsels(d, e, f); +} + +// CHECK-LABEL: @test_frsqrte( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ppc.frsqrte(double [[TMP0]]) +// CHECK-NEXT: ret double [[TMP1]] +// +double test_frsqrte() { + return __frsqrte(a); +} + +// CHECK-LABEL: @test_frsqrtes( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ppc.frsqrtes(float [[TMP0]]) +// CHECK-NEXT: ret float [[TMP1]] +// +float test_frsqrtes() { + return __frsqrtes(d); +} + +// CHECK-LABEL: @test_fsqrt( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.sqrt.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_fsqrt() { + return __fsqrt(a); +} + +// CHECK-LABEL: @test_fsqrts( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.sqrt.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_fsqrts() { + return __fsqrts(d); +} + +// CHECK-LABEL: @test_builtin_ppc_fric( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.rint.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_fric() { + return __builtin_ppc_fric(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frim( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.floor.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_frim() { + return __builtin_ppc_frim(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frims( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.floor.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_builtin_ppc_frims() { + return __builtin_ppc_frims(d); +} + +// CHECK-LABEL: @test_builtin_ppc_frin( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.round.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_frin() { + return __builtin_ppc_frin(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frins( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.round.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_builtin_ppc_frins() { + return __builtin_ppc_frins(d); +} + +// CHECK-LABEL: @test_builtin_ppc_frip( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.ceil.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_frip() { + return __builtin_ppc_frip(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frips( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.ceil.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_builtin_ppc_frips() { + return __builtin_ppc_frips(d); +} + +// CHECK-LABEL: @test_builtin_ppc_friz( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.trunc.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_friz() { + return __builtin_ppc_friz(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frizs( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.trunc.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_builtin_ppc_frizs() { + return __builtin_ppc_frizs(d); +} + +// CHECK-LABEL: @test_builtin_ppc_fsel( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @b, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = load double, double* @c, align 8 +// CHECK-NEXT: [[TMP3:%.*]] = call double @llvm.ppc.fsel(double [[TMP0]], double [[TMP1]], double [[TMP2]]) +// CHECK-NEXT: ret double [[TMP3]] +// +double test_builtin_ppc_fsel() { + return __builtin_ppc_fsel(a, b, c); +} + +// CHECK-LABEL: @test_builtin_ppc_fsels( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @e, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = load float, float* @f, align 4 +// CHECK-NEXT: [[TMP3:%.*]] = call float @llvm.ppc.fsels(float [[TMP0]], float [[TMP1]], float [[TMP2]]) +// CHECK-NEXT: ret float [[TMP3]] +// +float test_builtin_ppc_fsels() { + return __builtin_ppc_fsels(d, e, f); +} + +// CHECK-LABEL: @test_builtin_ppc_frsqrte( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.ppc.frsqrte(double [[TMP0]]) +// CHECK-NEXT: ret double [[TMP1]] +// +double test_builtin_ppc_frsqrte() { + return __builtin_ppc_frsqrte(a); +} + +// CHECK-LABEL: @test_builtin_ppc_frsqrtes( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.ppc.frsqrtes(float [[TMP0]]) +// CHECK-NEXT: ret float [[TMP1]] +// +float test_builtin_ppc_frsqrtes() { + return __builtin_ppc_frsqrtes(d); +} + +// CHECK-LABEL: @test_builtin_ppc_fsqrt( +// CHECK: [[TMP0:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP1:%.*]] = load double, double* @a, align 8 +// CHECK-NEXT: [[TMP2:%.*]] = call double @llvm.sqrt.f64(double [[TMP1]]) +// CHECK-NEXT: ret double [[TMP2]] +// +double test_builtin_ppc_fsqrt() { + return __builtin_ppc_fsqrt(a); +} + +// CHECK-LABEL: @test_builtin_ppc_fsqrts( +// CHECK: [[TMP0:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP1:%.*]] = load float, float* @d, align 4 +// CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.sqrt.f32(float [[TMP1]]) +// CHECK-NEXT: ret float [[TMP2]] +// +float test_builtin_ppc_fsqrts() { + return __builtin_ppc_fsqrts(d); +} diff --git a/llvm/include/llvm/IR/IntrinsicsPowerPC.td b/llvm/include/llvm/IR/IntrinsicsPowerPC.td index 69f2346e02cb37..a3a42b0489cccb 100644 --- a/llvm/include/llvm/IR/IntrinsicsPowerPC.td +++ b/llvm/include/llvm/IR/IntrinsicsPowerPC.td @@ -1703,6 +1703,17 @@ let TargetPrefix = "ppc" in { def int_ppc_fres : GCCBuiltin<"__builtin_ppc_fres">, Intrinsic <[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; + + def int_ppc_fsel : GCCBuiltin<"__builtin_ppc_fsel">, + Intrinsic<[llvm_double_ty], [llvm_double_ty, llvm_double_ty, + llvm_double_ty], [IntrNoMem]>; + def int_ppc_fsels : GCCBuiltin<"__builtin_ppc_fsels">, + Intrinsic<[llvm_float_ty], [llvm_float_ty, llvm_float_ty, + llvm_float_ty], [IntrNoMem]>; + def int_ppc_frsqrte : GCCBuiltin<"__builtin_ppc_frsqrte">, + Intrinsic<[llvm_double_ty], [llvm_double_ty], [IntrNoMem]>; + def int_ppc_frsqrtes : GCCBuiltin<"__builtin_ppc_frsqrtes">, + Intrinsic<[llvm_float_ty], [llvm_float_ty], [IntrNoMem]>; } //===----------------------------------------------------------------------===// diff --git a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp index 66b97860f5a91e..606aae66196c19 100644 --- a/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp +++ b/llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp @@ -4983,6 +4983,18 @@ void PPCDAGToDAGISel::Select(SDNode *N) { break; case ISD::INTRINSIC_WO_CHAIN: { + // We emit the PPC::FSELS instruction here because of type conflicts with + // the comparison operand. The FSELS instruction is defined to use an 8-byte + // comparison like the FSELD version. The fsels intrinsic takes a 4-byte + // value for the comparison. When selecting through a .td file, a type + // error is raised. Must check this first so we never break on the + // !Subtarget->isISA3_1() check. + if (N->getConstantOperandVal(0) == Intrinsic::ppc_fsels) { + SDValue Ops[] = {N->getOperand(1), N->getOperand(2), N->getOperand(3)}; + CurDAG->SelectNodeTo(N, PPC::FSELS, MVT::f32, Ops); + return; + } + if (!Subtarget->isISA3_1()) break; unsigned Opcode = 0; diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td index 79e5583baba0af..4cea450f44fe73 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td +++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td @@ -4409,6 +4409,10 @@ def : Pat<(i1 (not (trunc i32:$in))), def : Pat<(i1 (not (trunc i64:$in))), (ANDI_rec_1_EQ_BIT8 $in)>; +def : Pat<(int_ppc_fsel f8rc:$FRA, f8rc:$FRC, f8rc:$FRB), (FSELD $FRA, $FRC, $FRB)>; +def : Pat<(int_ppc_frsqrte f8rc:$frB), (FRSQRTE $frB)>; +def : Pat<(int_ppc_frsqrtes f4rc:$frB), (FRSQRTES $frB)>; + //===----------------------------------------------------------------------===// // PowerPC Instructions used for assembler/disassembler only // diff --git a/llvm/lib/Target/PowerPC/PPCInstrVSX.td b/llvm/lib/Target/PowerPC/PPCInstrVSX.td index f816ce9909fd5c..c0f2aed43a4d38 100644 --- a/llvm/lib/Target/PowerPC/PPCInstrVSX.td +++ b/llvm/lib/Target/PowerPC/PPCInstrVSX.td @@ -2857,6 +2857,7 @@ 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)>; +def : Pat<(int_ppc_frsqrte vsfrc:$XB), (XSRSQRTEDP $XB)>; } // HasVSX // Any big endian VSX subtarget. @@ -3267,6 +3268,7 @@ def : Pat<(f64 (int_ppc_insert_exp f64:$A, i64:$B)), def : Pat<(int_ppc_stfiw ForceXForm:$dst, f64:$XT), (STXSIWX f64:$XT, ForceXForm:$dst)>; +def : Pat<(int_ppc_frsqrtes vssrc:$XB), (XSRSQRTESP $XB)>; } // HasVSX, HasP8Vector // Any big endian Power8 VSX subtarget. diff --git a/llvm/test/CodeGen/builtins-ppc-xlcompat-fp.ll b/llvm/test/CodeGen/builtins-ppc-xlcompat-fp.ll new file mode 100644 index 00000000000000..d828493205f839 --- /dev/null +++ b/llvm/test/CodeGen/builtins-ppc-xlcompat-fp.ll @@ -0,0 +1,101 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -verify-machineinstrs -mtriple=powerpc64-unknown-unknown \ +; RUN: -mcpu=pwr7 < %s | FileCheck %s --check-prefix=CHECK-PWR7 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-PWR8 +; RUN: llc -verify-machineinstrs -mtriple=powerpc-unknown-aix \ +; RUN: -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-PWR8 +; RUN: llc -verify-machineinstrs -mtriple=powerpc64le-unknown-unknown \ +; RUN: -mattr=-vsx -mcpu=pwr8 < %s | FileCheck %s --check-prefix=CHECK-NOVSX + +define dso_local double @test_fsel(double %a, double %b, double %c) local_unnamed_addr { +; CHECK-PWR7-LABEL: test_fsel: +; CHECK-PWR7: # %bb.0: # %entry +; CHECK-PWR7-NEXT: fsel 1, 1, 2, 3 +; CHECK-PWR7-NEXT: blr +; +; CHECK-PWR8-LABEL: test_fsel: +; CHECK-PWR8: # %bb.0: # %entry +; CHECK-PWR8-NEXT: fsel 1, 1, 2, 3 +; CHECK-PWR8-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_fsel: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: fsel 1, 1, 2, 3 +; CHECK-NOVSX-NEXT: blr + +entry: + %0 = tail call double @llvm.ppc.fsel(double %a, double %b, double %c) + ret double %0 +} + +declare double @llvm.ppc.fsel(double, double, double) + +define dso_local float @test_fsels(float %a, float %b, float %c) local_unnamed_addr { +; CHECK-PWR7-LABEL: test_fsels: +; CHECK-PWR7: # %bb.0: # %entry +; CHECK-PWR7-NEXT: fsel 1, 1, 2, 3 +; CHECK-PWR7-NEXT: blr +; +; CHECK-PWR8-LABEL: test_fsels: +; CHECK-PWR8: # %bb.0: # %entry +; CHECK-PWR8-NEXT: fsel 1, 1, 2, 3 +; CHECK-PWR8-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_fsels: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: fsel 1, 1, 2, 3 +; CHECK-NOVSX-NEXT: blr + +entry: + %0 = tail call float @llvm.ppc.fsels(float %a, float %b, float %c) + ret float %0 +} + +declare float @llvm.ppc.fsels(float, float, float) + +define dso_local double @test_frsqrte(double %a) local_unnamed_addr { +; CHECK-PWR7-LABEL: test_frsqrte: +; CHECK-PWR7: # %bb.0: # %entry +; CHECK-PWR7-NEXT: xsrsqrtedp 1, 1 +; CHECK-PWR7-NEXT: blr +; +; CHECK-PWR8-LABEL: test_frsqrte: +; CHECK-PWR8: # %bb.0: # %entry +; CHECK-PWR8-NEXT: xsrsqrtedp 1, 1 +; CHECK-PWR8-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_frsqrte: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: frsqrte 1, 1 +; CHECK-NOVSX-NEXT: blr + +entry: + %0 = tail call double @llvm.ppc.frsqrte(double %a) + ret double %0 +} + +declare double @llvm.ppc.frsqrte(double) + +define dso_local float @test_frsqrtes(float %a) local_unnamed_addr { +; CHECK-PWR7-LABEL: test_frsqrtes: +; CHECK-PWR7: # %bb.0: # %entry +; CHECK-PWR7-NEXT: frsqrtes 1, 1 +; CHECK-PWR7-NEXT: blr +; +; CHECK-PWR8-LABEL: test_frsqrtes: +; CHECK-PWR8: # %bb.0: # %entry +; CHECK-PWR8-NEXT: xsrsqrtesp 1, 1 +; CHECK-PWR8-NEXT: blr +; +; CHECK-NOVSX-LABEL: test_frsqrtes: +; CHECK-NOVSX: # %bb.0: # %entry +; CHECK-NOVSX-NEXT: frsqrtes 1, 1 +; CHECK-NOVSX-NEXT: blr + +entry: + %0 = tail call float @llvm.ppc.frsqrtes(float %a) + ret float %0 +} + +declare float @llvm.ppc.frsqrtes(float)