Teach InstCombine to hoist FABS and FNEG through FPTRUNC instructions. The application of these operations commutes with the truncation, so we should prefer to do them in the smallest size we can, to save register space, use smaller constant pool entries, etc.

llvm-svn: 172117
This commit is contained in:
Owen Anderson 2013-01-10 22:06:52 +00:00
parent 929cf5615f
commit dbf0ca523d
2 changed files with 46 additions and 1 deletions

View File

@ -1204,8 +1204,34 @@ Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
}
break;
}
// (fptrunc (fneg x)) -> (fneg (fptrunc x))
if (BinaryOperator::isFNeg(OpI)) {
Value *InnerTrunc = Builder->CreateFPTrunc(OpI->getOperand(1),
CI.getType());
return BinaryOperator::CreateFNeg(InnerTrunc);
}
}
IntrinsicInst *II = dyn_cast<IntrinsicInst>(CI.getOperand(0));
if (II) {
switch (II->getIntrinsicID()) {
default: break;
case Intrinsic::fabs: {
// (fptrunc (fabs x)) -> (fabs (fptrunc x))
Value *InnerTrunc = Builder->CreateFPTrunc(II->getArgOperand(0),
CI.getType());
Type *IntrinsicType[] = { CI.getType() };
Function *Overload =
Intrinsic::getDeclaration(CI.getParent()->getParent()->getParent(),
II->getIntrinsicID(), IntrinsicType);
Value *Args[] = { InnerTrunc };
return CallInst::Create(Overload, Args, II->getName());
}
}
}
// Fold (fptrunc (sqrt (fpext x))) -> (sqrtf x)
CallInst *Call = dyn_cast<CallInst>(CI.getOperand(0));
if (Call && Call->getCalledFunction() && TLI->has(LibFunc::sqrtf) &&

View File

@ -13,3 +13,22 @@ define i8 @test2() {
; CHECK: ret i8 -1
}
; CHECK: test3
define half @test3(float %a) {
; CHECK: fptrunc
; CHECK: llvm.fabs.f16
%b = call float @llvm.fabs.f32(float %a)
%c = fptrunc float %b to half
ret half %c
}
; CHECK: test4
define half @test4(float %a) {
; CHECK: fptrunc
; CHECK: fsub
%b = fsub float -0.0, %a
%c = fptrunc float %b to half
ret half %c
}
declare float @llvm.fabs.f32(float) nounwind readonly