diff options
-rw-r--r-- | llvm/include/llvm/Analysis/TargetLibraryInfo.def | 9 | ||||
-rw-r--r-- | llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h | 1 | ||||
-rw-r--r-- | llvm/lib/Analysis/TargetLibraryInfo.cpp | 22 | ||||
-rw-r--r-- | llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | 33 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/cabs-array.ll | 65 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/cabs-discrete.ll | 59 | ||||
-rw-r--r-- | llvm/unittests/Analysis/TargetLibraryInfoTest.cpp | 3 |
7 files changed, 192 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/TargetLibraryInfo.def b/llvm/include/llvm/Analysis/TargetLibraryInfo.def index 9cbe917c146..a461ed813b9 100644 --- a/llvm/include/llvm/Analysis/TargetLibraryInfo.def +++ b/llvm/include/llvm/Analysis/TargetLibraryInfo.def @@ -457,6 +457,15 @@ TLI_DEFINE_STRING_INTERNAL("bcopy") /// void bzero(void *s, size_t n); TLI_DEFINE_ENUM_INTERNAL(bzero) TLI_DEFINE_STRING_INTERNAL("bzero") +/// double cabs(double complex z) +TLI_DEFINE_ENUM_INTERNAL(cabs) +TLI_DEFINE_STRING_INTERNAL("cabs") +/// float cabs(float complex z) +TLI_DEFINE_ENUM_INTERNAL(cabsf) +TLI_DEFINE_STRING_INTERNAL("cabsf") +/// long double cabs(long double complex z) +TLI_DEFINE_ENUM_INTERNAL(cabsl) +TLI_DEFINE_STRING_INTERNAL("cabsl") /// void *calloc(size_t count, size_t size); TLI_DEFINE_ENUM_INTERNAL(calloc) TLI_DEFINE_STRING_INTERNAL("calloc") diff --git a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h index c8a37343321..73a62f59203 100644 --- a/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/llvm/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -129,6 +129,7 @@ private: Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B); // Math Library Optimizations + Value *optimizeCAbs(CallInst *CI, IRBuilder<> &B); Value *optimizeCos(CallInst *CI, IRBuilder<> &B); Value *optimizePow(CallInst *CI, IRBuilder<> &B); Value *replacePowWithSqrt(CallInst *Pow, IRBuilder<> &B); diff --git a/llvm/lib/Analysis/TargetLibraryInfo.cpp b/llvm/lib/Analysis/TargetLibraryInfo.cpp index f8facf28277..609b9961deb 100644 --- a/llvm/lib/Analysis/TargetLibraryInfo.cpp +++ b/llvm/lib/Analysis/TargetLibraryInfo.cpp @@ -182,6 +182,9 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_atanh); TLI.setUnavailable(LibFunc_atanhf); TLI.setUnavailable(LibFunc_atanhl); + TLI.setUnavailable(LibFunc_cabs); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cabsl); TLI.setUnavailable(LibFunc_cbrt); TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_cbrtl); @@ -1267,6 +1270,25 @@ bool TargetLibraryInfoImpl::isValidProtoForLibFunc(const FunctionType &FTy, return (NumParams == 1 && FTy.getParamType(0)->isPointerTy() && FTy.getReturnType()->isIntegerTy()); + case LibFunc_cabs: + case LibFunc_cabsf: + case LibFunc_cabsl: { + Type* RetTy = FTy.getReturnType(); + if (!RetTy->isFloatingPointTy()) + return false; + + // NOTE: These prototypes are target specific and currently support + // "complex" passed as an array or discrete real & imaginary parameters. + // Add other calling conventions to enable libcall optimizations. + if (NumParams == 1) + return (FTy.getParamType(0)->isArrayTy() && + FTy.getParamType(0)->getArrayNumElements() == 2 && + FTy.getParamType(0)->getArrayElementType() == RetTy); + else if (NumParams == 2) + return (FTy.getParamType(0) == RetTy && FTy.getParamType(1) == RetTy); + else + return false; + } case LibFunc::NumLibFuncs: break; } diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp index 60f6c600b5a..03a1d55ddc3 100644 --- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -1033,6 +1033,35 @@ static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilder<> &B) { return B.CreateFPExt(V, B.getDoubleTy()); } +// cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z))) +Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilder<> &B) { + if (!CI->isFast()) + return nullptr; + + // Propagate fast-math flags from the existing call to new instructions. + IRBuilder<>::FastMathFlagGuard Guard(B); + B.setFastMathFlags(CI->getFastMathFlags()); + + Value *Real, *Imag; + if (CI->getNumArgOperands() == 1) { + Value *Op = CI->getArgOperand(0); + assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!"); + Real = B.CreateExtractValue(Op, 0, "real"); + Imag = B.CreateExtractValue(Op, 1, "imag"); + } else { + assert(CI->getNumArgOperands() == 2 && "Unexpected signature for cabs!"); + Real = CI->getArgOperand(0); + Imag = CI->getArgOperand(1); + } + + Value *RealReal = B.CreateFMul(Real, Real); + Value *ImagImag = B.CreateFMul(Imag, Imag); + + Function *FSqrt = Intrinsic::getDeclaration(CI->getModule(), Intrinsic::sqrt, + CI->getType()); + return B.CreateCall(FSqrt, B.CreateFAdd(RealReal, ImagImag), "cabs"); +} + Value *LibCallSimplifier::optimizeCos(CallInst *CI, IRBuilder<> &B) { Function *Callee = CI->getCalledFunction(); Value *Ret = nullptr; @@ -2162,6 +2191,10 @@ Value *LibCallSimplifier::optimizeFloatingPointLibCall(CallInst *CI, case LibFunc_fmax: case LibFunc_fmaxl: return optimizeFMinFMax(CI, Builder); + case LibFunc_cabs: + case LibFunc_cabsf: + case LibFunc_cabsl: + return optimizeCAbs(CI, Builder); default: return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/cabs-array.ll b/llvm/test/Transforms/InstCombine/cabs-array.ll new file mode 100644 index 00000000000..1c15dc1c545 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/cabs-array.ll @@ -0,0 +1,65 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @std_cabs([2 x double] %z) { +; CHECK-LABEL: define double @std_cabs( +; CHECK: tail call double @cabs( + %call = tail call double @cabs([2 x double] %z) + ret double %call +} + +define float @std_cabsf([2 x float] %z) { +; CHECK-LABEL: define float @std_cabsf( +; CHECK: tail call float @cabsf( + %call = tail call float @cabsf([2 x float] %z) + ret float %call +} + +define fp128 @std_cabsl([2 x fp128] %z) { +; CHECK-LABEL: define fp128 @std_cabsl( +; CHECK: tail call fp128 @cabsl( + %call = tail call fp128 @cabsl([2 x fp128] %z) + ret fp128 %call +} + +define double @fast_cabs([2 x double] %z) { +; CHECK-LABEL: define double @fast_cabs( +; CHECK: %real = extractvalue [2 x double] %z, 0 +; CHECK: %imag = extractvalue [2 x double] %z, 1 +; CHECK: %1 = fmul fast double %real, %real +; CHECK: %2 = fmul fast double %imag, %imag +; CHECK: %3 = fadd fast double %1, %2 +; CHECK: %cabs = call fast double @llvm.sqrt.f64(double %3) +; CHECK: ret double %cabs + %call = tail call fast double @cabs([2 x double] %z) + ret double %call +} + +define float @fast_cabsf([2 x float] %z) { +; CHECK-LABEL: define float @fast_cabsf( +; CHECK: %real = extractvalue [2 x float] %z, 0 +; CHECK: %imag = extractvalue [2 x float] %z, 1 +; CHECK: %1 = fmul fast float %real, %real +; CHECK: %2 = fmul fast float %imag, %imag +; CHECK: %3 = fadd fast float %1, %2 +; CHECK: %cabs = call fast float @llvm.sqrt.f32(float %3) +; CHECK: ret float %cabs + %call = tail call fast float @cabsf([2 x float] %z) + ret float %call +} + +define fp128 @fast_cabsl([2 x fp128] %z) { +; CHECK-LABEL: define fp128 @fast_cabsl( +; CHECK: %real = extractvalue [2 x fp128] %z, 0 +; CHECK: %imag = extractvalue [2 x fp128] %z, 1 +; CHECK: %1 = fmul fast fp128 %real, %real +; CHECK: %2 = fmul fast fp128 %imag, %imag +; CHECK: %3 = fadd fast fp128 %1, %2 +; CHECK: %cabs = call fast fp128 @llvm.sqrt.f128(fp128 %3) +; CHECK: ret fp128 %cabs + %call = tail call fast fp128 @cabsl([2 x fp128] %z) + ret fp128 %call +} + +declare double @cabs([2 x double]) +declare float @cabsf([2 x float]) +declare fp128 @cabsl([2 x fp128]) diff --git a/llvm/test/Transforms/InstCombine/cabs-discrete.ll b/llvm/test/Transforms/InstCombine/cabs-discrete.ll new file mode 100644 index 00000000000..405c073c194 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/cabs-discrete.ll @@ -0,0 +1,59 @@ +; RUN: opt < %s -instcombine -S | FileCheck %s + +define double @std_cabs(double %real, double %imag) { +; CHECK-LABEL: define double @std_cabs( +; CHECK: tail call double @cabs( + %call = tail call double @cabs(double %real, double %imag) + ret double %call +} + +define float @std_cabsf(float %real, float %imag) { +; CHECK-LABEL: define float @std_cabsf( +; CHECK: tail call float @cabsf( + %call = tail call float @cabsf(float %real, float %imag) + ret float %call +} + +define fp128 @std_cabsl(fp128 %real, fp128 %imag) { +; CHECK-LABEL: define fp128 @std_cabsl( +; CHECK: tail call fp128 @cabsl( + %call = tail call fp128 @cabsl(fp128 %real, fp128 %imag) + ret fp128 %call +} + +define double @fast_cabs(double %real, double %imag) { +; CHECK-LABEL: define double @fast_cabs( +; CHECK: %1 = fmul fast double %real, %real +; CHECK: %2 = fmul fast double %imag, %imag +; CHECK: %3 = fadd fast double %1, %2 +; CHECK: %cabs = call fast double @llvm.sqrt.f64(double %3) +; CHECK: ret double %cabs + %call = tail call fast double @cabs(double %real, double %imag) + ret double %call +} + +define float @fast_cabsf(float %real, float %imag) { +; CHECK-LABEL: define float @fast_cabsf( +; CHECK: %1 = fmul fast float %real, %real +; CHECK: %2 = fmul fast float %imag, %imag +; CHECK: %3 = fadd fast float %1, %2 +; CHECK: %cabs = call fast float @llvm.sqrt.f32(float %3) +; CHECK: ret float %cabs + %call = tail call fast float @cabsf(float %real, float %imag) + ret float %call +} + +define fp128 @fast_cabsl(fp128 %real, fp128 %imag) { +; CHECK-LABEL: define fp128 @fast_cabsl( +; CHECK: %1 = fmul fast fp128 %real, %real +; CHECK: %2 = fmul fast fp128 %imag, %imag +; CHECK: %3 = fadd fast fp128 %1, %2 +; CHECK: %cabs = call fast fp128 @llvm.sqrt.f128(fp128 %3) +; CHECK: ret fp128 %cabs + %call = tail call fast fp128 @cabsl(fp128 %real, fp128 %imag) + ret fp128 %call +} + +declare double @cabs(double %real, double %imag) +declare float @cabsf(float %real, float %imag) +declare fp128 @cabsl(fp128 %real, fp128 %imag) diff --git a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp index 9d852cf0301..ef558a434c7 100644 --- a/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp +++ b/llvm/unittests/Analysis/TargetLibraryInfoTest.cpp @@ -131,6 +131,9 @@ TEST_F(TargetLibraryInfoTest, ValidProto) { "declare double @copysign(double, double)\n" "declare float @copysignf(float, float)\n" "declare x86_fp80 @copysignl(x86_fp80, x86_fp80)\n" + "declare double @cabs([2 x double])\n" + "declare float @cabsf([2 x float])\n" + "declare x86_fp80 @cabsl([2 x x86_fp80])\n" "declare double @cos(double)\n" "declare float @cosf(float)\n" "declare double @cosh(double)\n" |