mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
Fold fptrunc(add (fpextend x), (fpextend y)) -> add(x,y), as GCC does.
llvm-svn: 46406
This commit is contained in:
parent
00183edf55
commit
aa553aa0c1
@ -203,7 +203,7 @@ namespace {
|
||||
Instruction *visitTrunc(TruncInst &CI);
|
||||
Instruction *visitZExt(ZExtInst &CI);
|
||||
Instruction *visitSExt(SExtInst &CI);
|
||||
Instruction *visitFPTrunc(CastInst &CI);
|
||||
Instruction *visitFPTrunc(FPTruncInst &CI);
|
||||
Instruction *visitFPExt(CastInst &CI);
|
||||
Instruction *visitFPToUI(CastInst &CI);
|
||||
Instruction *visitFPToSI(CastInst &CI);
|
||||
@ -7141,8 +7141,80 @@ Instruction *InstCombiner::visitSExt(SExtInst &CI) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFPTrunc(CastInst &CI) {
|
||||
return commonCastTransforms(CI);
|
||||
/// FitsInFPType - Return a Constant* for the specified FP constant if it fits
|
||||
/// in the specified FP type without changing its value.
|
||||
static Constant *FitsInFPType(ConstantFP *CFP, const Type *FPTy,
|
||||
const fltSemantics &Sem) {
|
||||
APFloat F = CFP->getValueAPF();
|
||||
if (F.convert(Sem, APFloat::rmNearestTiesToEven) == APFloat::opOK)
|
||||
return ConstantFP::get(FPTy, F);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// LookThroughFPExtensions - If this is an fp extension instruction, look
|
||||
/// through it until we get the source value.
|
||||
static Value *LookThroughFPExtensions(Value *V) {
|
||||
if (Instruction *I = dyn_cast<Instruction>(V))
|
||||
if (I->getOpcode() == Instruction::FPExt)
|
||||
return LookThroughFPExtensions(I->getOperand(0));
|
||||
|
||||
// If this value is a constant, return the constant in the smallest FP type
|
||||
// that can accurately represent it. This allows us to turn
|
||||
// (float)((double)X+2.0) into x+2.0f.
|
||||
if (ConstantFP *CFP = dyn_cast<ConstantFP>(V)) {
|
||||
if (CFP->getType() == Type::PPC_FP128Ty)
|
||||
return V; // No constant folding of this.
|
||||
// See if the value can be truncated to float and then reextended.
|
||||
if (Value *V = FitsInFPType(CFP, Type::FloatTy, APFloat::IEEEsingle))
|
||||
return V;
|
||||
if (CFP->getType() == Type::DoubleTy)
|
||||
return V; // Won't shrink.
|
||||
if (Value *V = FitsInFPType(CFP, Type::DoubleTy, APFloat::IEEEdouble))
|
||||
return V;
|
||||
// Don't try to shrink to various long double types.
|
||||
}
|
||||
|
||||
return V;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFPTrunc(FPTruncInst &CI) {
|
||||
if (Instruction *I = commonCastTransforms(CI))
|
||||
return I;
|
||||
|
||||
// If we have fptrunc(add (fpextend x), (fpextend y)), where x and y are
|
||||
// smaller than the destination type, we can eliminate the truncate by doing
|
||||
// the add as the smaller type. This applies to add/sub/mul/div as well as
|
||||
// many builtins (sqrt, etc).
|
||||
BinaryOperator *OpI = dyn_cast<BinaryOperator>(CI.getOperand(0));
|
||||
if (OpI && OpI->hasOneUse()) {
|
||||
switch (OpI->getOpcode()) {
|
||||
default: break;
|
||||
case Instruction::Add:
|
||||
case Instruction::Sub:
|
||||
case Instruction::Mul:
|
||||
case Instruction::FDiv:
|
||||
case Instruction::FRem:
|
||||
const Type *SrcTy = OpI->getType();
|
||||
Value *LHSTrunc = LookThroughFPExtensions(OpI->getOperand(0));
|
||||
Value *RHSTrunc = LookThroughFPExtensions(OpI->getOperand(1));
|
||||
if (LHSTrunc->getType() != SrcTy &&
|
||||
RHSTrunc->getType() != SrcTy) {
|
||||
unsigned DstSize = CI.getType()->getPrimitiveSizeInBits();
|
||||
// If the source types were both smaller than the destination type of
|
||||
// the cast, do this xform.
|
||||
if (LHSTrunc->getType()->getPrimitiveSizeInBits() <= DstSize &&
|
||||
RHSTrunc->getType()->getPrimitiveSizeInBits() <= DstSize) {
|
||||
LHSTrunc = InsertCastBefore(Instruction::FPExt, LHSTrunc,
|
||||
CI.getType(), CI);
|
||||
RHSTrunc = InsertCastBefore(Instruction::FPExt, RHSTrunc,
|
||||
CI.getType(), CI);
|
||||
return BinaryOperator::create(OpI->getOpcode(), LHSTrunc, RHSTrunc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitFPExt(CastInst &CI) {
|
||||
|
36
test/Transforms/InstCombine/fpextend.ll
Normal file
36
test/Transforms/InstCombine/fpextend.ll
Normal file
@ -0,0 +1,36 @@
|
||||
; RUN: llvm-as < %s | opt -instcombine | llvm-dis | not grep fpext
|
||||
@X = external global float
|
||||
@Y = external global float
|
||||
|
||||
define void @test() nounwind {
|
||||
entry:
|
||||
%tmp = load float* @X, align 4 ; <float> [#uses=1]
|
||||
%tmp1 = fpext float %tmp to double ; <double> [#uses=1]
|
||||
%tmp3 = add double %tmp1, 0.000000e+00 ; <double> [#uses=1]
|
||||
%tmp34 = fptrunc double %tmp3 to float ; <float> [#uses=1]
|
||||
store float %tmp34, float* @X, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test3() nounwind {
|
||||
entry:
|
||||
%tmp = load float* @X, align 4 ; <float> [#uses=1]
|
||||
%tmp1 = fpext float %tmp to double ; <double> [#uses=1]
|
||||
%tmp2 = load float* @Y, align 4 ; <float> [#uses=1]
|
||||
%tmp23 = fpext float %tmp2 to double ; <double> [#uses=1]
|
||||
%tmp5 = fdiv double %tmp1, %tmp23 ; <double> [#uses=1]
|
||||
%tmp56 = fptrunc double %tmp5 to float ; <float> [#uses=1]
|
||||
store float %tmp56, float* @X, align 4
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test4() nounwind {
|
||||
entry:
|
||||
%tmp = load float* @X, align 4 ; <float> [#uses=1]
|
||||
%tmp1 = fpext float %tmp to double ; <double> [#uses=1]
|
||||
%tmp2 = sub double -0.000000e+00, %tmp1 ; <double> [#uses=1]
|
||||
%tmp34 = fptrunc double %tmp2 to float ; <float> [#uses=1]
|
||||
store float %tmp34, float* @X, align 4
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user