LLVM API Documentation

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" || Name == "sqrt";
00080     case 't':
00081       return Name == "tan" || Name == "tanh";
00082     default:
00083       return false;
00084   }
00085 }
00086 
00087 Constant *
00088 llvm::ConstantFoldFP(double (*NativeFP)(double), double V, const Type *Ty) {
00089   errno = 0;
00090   V = NativeFP(V);
00091   if (errno == 0)
00092     return ConstantFP::get(Ty, V);
00093   return 0;
00094 }
00095 
00096 /// ConstantFoldCall - Attempt to constant fold a call to the specified function
00097 /// with the specified arguments, returning null if unsuccessful.
00098 Constant *
00099 llvm::ConstantFoldCall(Function *F, const std::vector<Constant*> &Operands) {
00100   const std::string &Name = F->getName();
00101   const Type *Ty = F->getReturnType();
00102 
00103   if (Operands.size() == 1) {
00104     if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) {
00105       double V = Op->getValue();
00106       switch (Name[0])
00107       {
00108         case 'a':
00109           if (Name == "acos")
00110             return ConstantFoldFP(acos, V, Ty);
00111           else if (Name == "asin")
00112             return ConstantFoldFP(asin, V, Ty);
00113           else if (Name == "atan")
00114             return ConstantFP::get(Ty, atan(V));
00115           break;
00116         case 'c':
00117           if (Name == "ceil")
00118             return ConstantFoldFP(ceil, V, Ty);
00119           else if (Name == "cos")
00120             return ConstantFP::get(Ty, cos(V));
00121           else if (Name == "cosh")
00122             return ConstantFP::get(Ty, cosh(V));
00123           break;
00124         case 'e':
00125           if (Name == "exp")
00126             return ConstantFP::get(Ty, exp(V));
00127           break;
00128         case 'f':
00129           if (Name == "fabs")
00130             return ConstantFP::get(Ty, fabs(V));
00131           else if (Name == "floor")
00132             return ConstantFoldFP(floor, V, Ty);
00133           break;
00134         case 'l':
00135           if (Name == "log" && V > 0)
00136             return ConstantFP::get(Ty, log(V));
00137           else if (Name == "log10" && V > 0)
00138             return ConstantFoldFP(log10, V, Ty);
00139           else if (Name == "llvm.sqrt.f32" || Name == "llvm.sqrt.f64") {
00140             if (V >= -0.0)
00141               return ConstantFP::get(Ty, sqrt(V));
00142             else // Undefined
00143               return ConstantFP::get(Ty, 0.0);
00144           }
00145           break;
00146         case 's':
00147           if (Name == "sin")
00148             return ConstantFP::get(Ty, sin(V));
00149           else if (Name == "sinh")
00150             return ConstantFP::get(Ty, sinh(V));
00151           else if (Name == "sqrt" && V >= 0)
00152             return ConstantFP::get(Ty, sqrt(V));
00153           break;
00154         case 't':
00155           if (Name == "tan")
00156             return ConstantFP::get(Ty, tan(V));
00157           else if (Name == "tanh")
00158             return ConstantFP::get(Ty, tanh(V));
00159           break;
00160         default:
00161           break;
00162       }
00163     } else if (ConstantUInt *Op = dyn_cast<ConstantUInt>(Operands[0])) {
00164       uint64_t V = Op->getValue();
00165       if (Name == "llvm.bswap.i16")
00166         return ConstantUInt::get(Ty, ByteSwap_16(V));
00167       else if (Name == "llvm.bswap.i32")
00168         return ConstantUInt::get(Ty, ByteSwap_32(V));
00169       else if (Name == "llvm.bswap.i64")
00170         return ConstantUInt::get(Ty, ByteSwap_64(V));
00171     }
00172   } else if (Operands.size() == 2) {
00173     if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
00174       double Op1V = Op1->getValue();
00175       if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
00176         double Op2V = Op2->getValue();
00177 
00178         if (Name == "llvm.isunordered.f32" || Name == "llvm.isunordered.f64")
00179           return ConstantBool::get(IsNAN(Op1V) || IsNAN(Op2V));
00180         else
00181         if (Name == "pow") {
00182           errno = 0;
00183           double V = pow(Op1V, Op2V);
00184           if (errno == 0)
00185             return ConstantFP::get(Ty, V);
00186         } else if (Name == "fmod") {
00187           errno = 0;
00188           double V = fmod(Op1V, Op2V);
00189           if (errno == 0)
00190             return ConstantFP::get(Ty, V);
00191         } else if (Name == "atan2")
00192           return ConstantFP::get(Ty, atan2(Op1V,Op2V));
00193       }
00194     }
00195   }
00196   return 0;
00197 }
00198