mirror of
https://github.com/intel/llvm.git
synced 2026-01-17 14:48:27 +08:00
[PowerPC] Floating Point Builtins for XL Compat.
This patch is in a series of patches to provide builtins for compatibility with the XL compiler. This patch adds builtins related to floating point operations Reviewed By: #powerpc, nemanjai, amyk, NeHuang Differential Revision: https://reviews.llvm.org/D103986
This commit is contained in:
@@ -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", "")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
314
clang/test/CodeGen/builtins-ppc-xlcompat-fp.c
Normal file
314
clang/test/CodeGen/builtins-ppc-xlcompat-fp.c
Normal file
@@ -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);
|
||||
}
|
||||
@@ -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]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
//
|
||||
|
||||
@@ -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.
|
||||
|
||||
101
llvm/test/CodeGen/builtins-ppc-xlcompat-fp.ll
Normal file
101
llvm/test/CodeGen/builtins-ppc-xlcompat-fp.ll
Normal file
@@ -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)
|
||||
Reference in New Issue
Block a user