}
}
- // Fold (fptrunc (sqrt (fpext x))) -> (sqrtf x)
- // Note that we restrict this transformation based on
- // TLI->has(LibFunc::sqrtf), even for the sqrt intrinsic, because
- // TLI->has(LibFunc::sqrtf) is sufficient to guarantee that the
- // single-precision intrinsic can be expanded in the backend.
- CallInst *Call = dyn_cast<CallInst>(CI.getOperand(0));
- if (Call && Call->getCalledFunction() && TLI->has(LibFunc::sqrtf) &&
- (Call->getCalledFunction()->getName() == TLI->getName(LibFunc::sqrt) ||
- Call->getCalledFunction()->getIntrinsicID() == Intrinsic::sqrt) &&
- Call->getNumArgOperands() == 1 &&
- Call->hasOneUse()) {
- CastInst *Arg = dyn_cast<CastInst>(Call->getArgOperand(0));
- if (Arg && Arg->getOpcode() == Instruction::FPExt &&
- CI.getType()->isFloatTy() &&
- Call->getType()->isDoubleTy() &&
- Arg->getType()->isDoubleTy() &&
- Arg->getOperand(0)->getType()->isFloatTy()) {
- Function *Callee = Call->getCalledFunction();
- Module *M = CI.getParent()->getParent()->getParent();
- Constant *SqrtfFunc = (Callee->getIntrinsicID() == Intrinsic::sqrt) ?
- Intrinsic::getDeclaration(M, Intrinsic::sqrt, Builder->getFloatTy()) :
- M->getOrInsertFunction("sqrtf", Callee->getAttributes(),
- Builder->getFloatTy(), Builder->getFloatTy(),
- NULL);
- CallInst *ret = CallInst::Create(SqrtfFunc, Arg->getOperand(0),
- "sqrtfcall");
- ret->setAttributes(Callee->getAttributes());
-
-
- // Remove the old Call. With -fmath-errno, it won't get marked readnone.
- ReplaceInstUsesWith(*Call, UndefValue::get(Call->getType()));
- EraseInstFromFunction(*Call);
- return ret;
- }
- }
-
return nullptr;
}
// floor((double)floatval) -> (double)floorf(floatval)
Value *V = Cast->getOperand(0);
- V = EmitUnaryFloatFnCall(V, Callee->getName(), B, Callee->getAttributes());
+ if (Callee->isIntrinsic()) {
+ Module *M = CI->getParent()->getParent()->getParent();
+ Intrinsic::ID IID = (Intrinsic::ID) Callee->getIntrinsicID();
+ Function *F = Intrinsic::getDeclaration(M, IID, B.getFloatTy());
+ V = B.CreateCall(F, V);
+ } else {
+ // The call is a library call rather than an intrinsic.
+ V = EmitUnaryFloatFnCall(V, Callee->getName(), B, Callee->getAttributes());
+ }
+
return B.CreateFPExt(V, B.getDoubleTy());
}
Value *V = nullptr;
Value *V1 = Cast1->getOperand(0);
Value *V2 = Cast2->getOperand(0);
+ // TODO: Handle intrinsics in the same way as in optimizeUnaryDoubleFP().
V = EmitBinaryFloatFnCall(V1, V2, Callee->getName(), B,
Callee->getAttributes());
return B.CreateFPExt(V, B.getDoubleTy());
Function *Callee = CI->getCalledFunction();
Value *Ret = nullptr;
- if (UnsafeFPShrink && Callee->getName() == "sqrt" &&
- TLI->has(LibFunc::sqrtf)) {
+ if (TLI->has(LibFunc::sqrtf) && (Callee->getName() == "sqrt" ||
+ Callee->getIntrinsicID() == Intrinsic::sqrt))
Ret = optimizeUnaryDoubleFP(CI, B, true);
- }
// FIXME: For finer-grain optimization, we need intrinsics to have the same
// fast-math flag decorations that are applied to FP instructions. For now,
UnsafeFPShrink = true;
}
- // Next check for intrinsics.
+ // First, check for intrinsics.
if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI)) {
if (!isCallingConvC)
return nullptr;
; CHECK: call float @sqrtf(float %f)
}
+define double @sqrt_test2(float %f) {
+ %conv = fpext float %f to double
+ %call = call double @sqrt(double %conv)
+ ret double %call
+; CHECK-LABEL: sqrt_test2
+; CHECK: call double @sqrt(double %conv)
+}
+
define float @sqrt_int_test(float %f) {
%conv = fpext float %f to double
%call = call double @llvm.sqrt.f64(double %conv)
; CHECK: call float @llvm.sqrt.f32(float %f)
}
-define double @sqrt_test2(float %f) {
+define double @sqrt_int_test2(float %f) {
%conv = fpext float %f to double
- %call = call double @sqrt(double %conv)
+ %call = call double @llvm.sqrt.f64(double %conv)
ret double %call
-; CHECK-LABEL: sqrt_test2
-; CHECK: call double @sqrt(double %conv)
+; CHECK-LABEL: sqrt_int_test2
+; CHECK: call double @llvm.sqrt.f64(double %conv)
}
+
define float @tan_test(float %f) {
%conv = fpext float %f to double
%call = call double @tan(double %conv)
declare double @tanh(double) #1
declare double @tan(double) #1
-declare double @sqrt(double) #1
+
+; sqrt is a special case: the shrinking optimization
+; is valid even without unsafe-fp-math.
+declare double @sqrt(double)
+declare double @llvm.sqrt.f64(double)
+
declare double @sin(double) #1
declare double @log2(double) #1
declare double @log1p(double) #1
declare double @asin(double) #1
declare double @asinh(double) #1
-declare double @llvm.sqrt.f64(double) #1
attributes #1 = { "unsafe-fp-math"="true" }