LLVM API Documentation
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