LLVM API Documentation

Analysis/ConstantFolding.cpp

Go to the documentation of this file.
00001 //===-- ConstantFolding.cpp - Analyze constant folding possibilities ------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by the LLVM research group and is distributed under
00006 // the University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This family of functions determines the possibility of performing constant
00011 // folding.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "llvm/Analysis/ConstantFolding.h"
00016 #include "llvm/Constants.h"
00017 #include "llvm/DerivedTypes.h"
00018 #include "llvm/Instructions.h"
00019 #include "llvm/Intrinsics.h"
00020 #include "llvm/Support/GetElementPtrTypeIterator.h"
00021 #include "llvm/Support/MathExtras.h"
00022 #include <cerrno>
00023 #include <cmath>
00024 using namespace llvm;
00025 
00026 //===----------------------------------------------------------------------===//
00027 //  Constant Folding ...
00028 //
00029 
00030 
00031 /// canConstantFoldCallTo - Return true if its even possible to fold a call to
00032 /// the specified function.
00033 bool
00034 llvm::canConstantFoldCallTo(Function *F) {
00035   const std::string &Name = F->getName();
00036 
00037   switch (F->getIntrinsicID()) {
00038   case Intrinsic::isunordered_f32:
00039   case Intrinsic::isunordered_f64:
00040   case Intrinsic::sqrt_f32:
00041   case Intrinsic::sqrt_f64:
00042   case Intrinsic::bswap_i16:
00043   case Intrinsic::bswap_i32:
00044   case Intrinsic::bswap_i64:
00045   // FIXME: these should be constant folded as well
00046   //case Intrinsic::ctpop_i8:
00047   //case Intrinsic::ctpop_i16:
00048   //case Intrinsic::ctpop_i32:
00049   //case Intrinsic::ctpop_i64:
00050   //case Intrinsic::ctlz_i8:
00051   //case Intrinsic::ctlz_i16:
00052   //case Intrinsic::ctlz_i32:
00053   //case Intrinsic::ctlz_i64:
00054   //case Intrinsic::cttz_i8:
00055   //case Intrinsic::cttz_i16:
00056   //case Intrinsic::cttz_i32:
00057   //case Intrinsic::cttz_i64:
00058     return true;
00059   default: break;
00060   }
00061 
00062   switch (Name[0])
00063   {
00064     case 'a':
00065       return Name == "acos" || Name == "asin" || Name == "atan" ||
00066              Name == "atan2";
00067     case 'c':
00068       return Name == "ceil" || Name == "cos" || Name == "cosf" ||
00069              Name == "cosh";
00070     case 'e':
00071       return Name == "exp";
00072     case 'f':
00073       return Name == "fabs" || Name == "fmod" || Name == "floor";
00074     case 'l':
00075       return Name == "log" || Name == "log10";
00076     case 'p':
00077       return Name == "pow";
00078     case 's':
00079       return Name == "sin" || Name == "sinh" || 
00080              Name == "sqrt" || Name == "sqrtf";
00081     case 't':
00082       return Name == "tan" || Name == "tanh";
00083     default:
00084       return false;
00085   }
00086 }
00087 
00088 Constant *
00089 llvm::ConstantFoldFP(double (*NativeFP)(double), double V, const Type *Ty) {
00090   errno = 0;
00091   V = NativeFP(V);
00092   if (errno == 0)
00093     return ConstantFP::get(Ty, V);
00094   return 0;
00095 }
00096 
00097 /// ConstantFoldCall - Attempt to constant fold a call to the specified function
00098 /// with the specified arguments, returning null if unsuccessful.
00099 Constant *
00100 llvm::ConstantFoldCall(Function *F, const std::vector<Constant*> &Operands) {
00101   const std::string &Name = F->getName();
00102   const Type *Ty = F->getReturnType();
00103 
00104   if (Operands.size() == 1) {
00105     if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) {
00106       double V = Op->getValue();
00107       switch (Name[0])
00108       {
00109         case 'a':
00110           if (Name == "acos")
00111             return ConstantFoldFP(acos, V, Ty);
00112           else if (Name == "asin")
00113             return ConstantFoldFP(asin, V, Ty);
00114           else if (Name == "atan")
00115             return ConstantFP::get(Ty, atan(V));
00116           break;
00117         case 'c':
00118           if (Name == "ceil")
00119             return ConstantFoldFP(ceil, V, Ty);
00120           else if (Name == "cos")
00121             return ConstantFP::get(Ty, cos(V));
00122           else if (Name == "cosh")
00123             return ConstantFP::get(Ty, cosh(V));
00124           break;
00125         case 'e':
00126           if (Name == "exp")
00127             return ConstantFP::get(Ty, exp(V));
00128           break;
00129         case 'f':
00130           if (Name == "fabs")
00131             return ConstantFP::get(Ty, fabs(V));
00132           else if (Name == "floor")
00133             return ConstantFoldFP(floor, V, Ty);
00134           break;
00135         case 'l':
00136           if (Name == "log" && V > 0)
00137             return ConstantFP::get(Ty, log(V));
00138           else if (Name == "log10" && V > 0)
00139             return ConstantFoldFP(log10, V, Ty);
00140           else if (Name == "llvm.sqrt.f32" || Name == "llvm.sqrt.f64") {
00141             if (V >= -0.0)
00142               return ConstantFP::get(Ty, sqrt(V));
00143             else // Undefined
00144               return ConstantFP::get(Ty, 0.0);
00145           }
00146           break;
00147         case 's':
00148           if (Name == "sin")
00149             return ConstantFP::get(Ty, sin(V));
00150           else if (Name == "sinh")
00151             return ConstantFP::get(Ty, sinh(V));
00152           else if (Name == "sqrt" && V >= 0)
00153             return ConstantFP::get(Ty, sqrt(V));
00154           else if (Name == "sqrtf" && V >= 0)
00155             return ConstantFP::get(Ty, sqrt((float)V));
00156           break;
00157         case 't':
00158           if (Name == "tan")
00159             return ConstantFP::get(Ty, tan(V));
00160           else if (Name == "tanh")
00161             return ConstantFP::get(Ty, tanh(V));
00162           break;
00163         default:
00164           break;
00165       }
00166     } else if (ConstantUInt *Op = dyn_cast<ConstantUInt>(Operands[0])) {
00167       uint64_t V = Op->getValue();
00168       if (Name == "llvm.bswap.i16")
00169         return ConstantUInt::get(Ty, ByteSwap_16(V));
00170       else if (Name == "llvm.bswap.i32")
00171         return ConstantUInt::get(Ty, ByteSwap_32(V));
00172       else if (Name == "llvm.bswap.i64")
00173         return ConstantUInt::get(Ty, ByteSwap_64(V));
00174     }
00175   } else if (Operands.size() == 2) {
00176     if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
00177       double Op1V = Op1->getValue();
00178       if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
00179         double Op2V = Op2->getValue();
00180 
00181         if (Name == "llvm.isunordered.f32" || Name == "llvm.isunordered.f64")
00182           return ConstantBool::get(IsNAN(Op1V) || IsNAN(Op2V));
00183         else
00184         if (Name == "pow") {
00185           errno = 0;
00186           double V = pow(Op1V, Op2V);
00187           if (errno == 0)
00188             return ConstantFP::get(Ty, V);
00189         } else if (Name == "fmod") {
00190           errno = 0;
00191           double V = fmod(Op1V, Op2V);
00192           if (errno == 0)
00193             return ConstantFP::get(Ty, V);
00194         } else if (Name == "atan2")
00195           return ConstantFP::get(Ty, atan2(Op1V,Op2V));
00196       }
00197     }
00198   }
00199   return 0;
00200 }
00201