many cleanups to the pow optimizer. Allow it to handle powf,

add support for  pow(x, 2.0) -> x*x.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@49411 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-04-09 00:07:45 +00:00
parent def286408f
commit 77d00b0cea
2 changed files with 62 additions and 38 deletions

View File

@ -1133,51 +1133,67 @@ LLVMMemSetOptimization MemSet64Optimizer("llvm.memset.i64");
struct VISIBILITY_HIDDEN PowOptimization : public LibCallOptimization { struct VISIBILITY_HIDDEN PowOptimization : public LibCallOptimization {
public: public:
/// @brief Default Constructor /// @brief Default Constructor
PowOptimization() : LibCallOptimization("pow", PowOptimization(const char *Name) : LibCallOptimization(Name,
"Number of 'pow' calls simplified") {} "Number of 'pow' calls simplified") {}
/// @brief Make sure that the "pow" function has the right prototype /// @brief Make sure that the "pow" function has the right prototype
virtual bool ValidateCalledFunction(const Function* f, SimplifyLibCalls& SLC){ virtual bool ValidateCalledFunction(const Function *F, SimplifyLibCalls &SLC){
// Just make sure this has 2 arguments // Just make sure this has 2 arguments of the same FP type, which match the
return (f->arg_size() == 2); // result type.
const FunctionType *FT = F->getFunctionType();
return FT->getNumParams() == 2 &&
FT->getParamType(0) == FT->getParamType(1) &&
FT->getParamType(0) == FT->getReturnType() &&
FT->getParamType(0)->isFloatingPoint();
} }
/// @brief Perform the pow optimization. /// @brief Perform the pow optimization.
virtual bool OptimizeCall(CallInst *ci, SimplifyLibCalls &SLC) { virtual bool OptimizeCall(CallInst *CI, SimplifyLibCalls &SLC) {
const Type *Ty = cast<Function>(ci->getOperand(0))->getReturnType(); const Type *Ty = CI->getType();
if (Ty != Type::FloatTy && Ty != Type::DoubleTy) if (Ty != Type::FloatTy && Ty != Type::DoubleTy)
return false; // FIXME long double not yet supported return false; // FIXME long double not yet supported
Value* base = ci->getOperand(1);
Value* expn = ci->getOperand(2); Value *Op1 = CI->getOperand(1);
if (ConstantFP *Op1 = dyn_cast<ConstantFP>(base)) { Value *Op2 = CI->getOperand(2);
if (Op1->isExactlyValue(1.0)) // pow(1.0,x) -> 1.0 if (ConstantFP *Op1C = dyn_cast<ConstantFP>(Op1)) {
return ReplaceCallWith(ci, ConstantFP::get(Ty, if (Op1C->isExactlyValue(1.0)) // pow(1.0, x) -> 1.0
Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0))); return ReplaceCallWith(CI, Op1C);
} else if (ConstantFP* Op2 = dyn_cast<ConstantFP>(expn)) { }
if (Op2->getValueAPF().isZero()) {
ConstantFP *Op2C = dyn_cast<ConstantFP>(Op2);
if (Op2C == 0) return false;
if (Op2C->getValueAPF().isZero()) {
// pow(x, 0.0) -> 1.0 // pow(x, 0.0) -> 1.0
return ReplaceCallWith(ci, ConstantFP::get(Ty, return ReplaceCallWith(CI, ConstantFP::get(Ty,
Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0))); Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0)));
} else if (Op2->isExactlyValue(0.5)) { } else if (Op2C->isExactlyValue(0.5)) {
// pow(x, 0.5) -> sqrt(x) // pow(x, 0.5) -> sqrt(x)
CallInst* sqrt_inst = CallInst::Create(SLC.get_sqrt(), base, Value *Sqrt = CallInst::Create(SLC.get_sqrt(), Op1, "sqrt", CI);
ci->getName()+".pow",ci); return ReplaceCallWith(CI, Sqrt);
return ReplaceCallWith(ci, sqrt_inst); } else if (Op2C->isExactlyValue(1.0)) {
} else if (Op2->isExactlyValue(1.0)) {
// pow(x, 1.0) -> x // pow(x, 1.0) -> x
return ReplaceCallWith(ci, base); return ReplaceCallWith(CI, Op1);
} else if (Op2->isExactlyValue(-1.0)) { } else if (Op2C->isExactlyValue(2.0)) {
// pow(x, 2.0) -> x*x
Value *Sq = BinaryOperator::createMul(Op1, Op1, "pow2", CI);
return ReplaceCallWith(CI, Sq);
} else if (Op2C->isExactlyValue(-1.0)) {
// pow(x, -1.0) -> 1.0/x // pow(x, -1.0) -> 1.0/x
Value *div_inst = Value *div_inst =
BinaryOperator::createFDiv(ConstantFP::get(Ty, BinaryOperator::createFDiv(ConstantFP::get(Ty,
Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0)), Ty==Type::FloatTy ? APFloat(1.0f) : APFloat(1.0)),
base, ci->getName()+".pow", ci); Op1, CI->getName()+".pow", CI);
return ReplaceCallWith(ci, div_inst); return ReplaceCallWith(CI, div_inst);
}
} }
return false; // opt failed return false; // opt failed
} }
} PowOptimizer; };
PowOptimization PowFOptimizer("powf");
PowOptimization PowOptimizer("pow");
PowOptimization PowLOptimizer("powl");
/// This LibCallOptimization will simplify calls to the "printf" library /// This LibCallOptimization will simplify calls to the "printf" library
/// function. It looks for cases where the result of printf is not used and the /// function. It looks for cases where the result of printf is not used and the

View File

@ -1,11 +1,10 @@
; Testcase for calls to the standard C "pow" function ; Testcase for calls to the standard C "pow" function
; ;
; Equivalent to: http://gcc.gnu.org/ml/gcc-patches/2003-02/msg01786.html ; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | not grep {call .pow}
; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | \
; RUN: not grep {call double .pow}
; END.
declare double @pow(double, double) declare double @pow(double, double)
declare float @powf(float, float)
define double @test1(double %X) { define double @test1(double %X) {
%Y = call double @pow( double %X, double 0.000000e+00 ) ; <double> [#uses=1] %Y = call double @pow( double %X, double 0.000000e+00 ) ; <double> [#uses=1]
@ -22,3 +21,12 @@ define double @test3(double %X) {
ret double %Y ret double %Y
} }
define double @test4(double %X) {
%Y = call double @pow( double %X, double 2.0)
ret double %Y
}
define float @test4f(float %X) {
%Y = call float @powf( float %X, float 2.0)
ret float %Y
}