ConstantFolding.cpp revision b5282dcf4745be59046f440980a1c0f0a50c9c09
1//===-- ConstantFolding.cpp - Analyze constant folding possibilities ------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file was developed by the LLVM research group and is distributed under 6// the University of Illinois Open Source License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This family of functions determines the possibility of performing constant 11// folding. 12// 13//===----------------------------------------------------------------------===// 14 15#include "llvm/Analysis/ConstantFolding.h" 16#include "llvm/Constants.h" 17#include "llvm/DerivedTypes.h" 18#include "llvm/Instructions.h" 19#include "llvm/Intrinsics.h" 20#include "llvm/Support/GetElementPtrTypeIterator.h" 21#include "llvm/Support/MathExtras.h" 22#include <cerrno> 23#include <cmath> 24using namespace llvm; 25 26//===----------------------------------------------------------------------===// 27// Constant Folding ... 28// 29 30 31/// canConstantFoldCallTo - Return true if its even possible to fold a call to 32/// the specified function. 33bool 34llvm::canConstantFoldCallTo(Function *F) { 35 const std::string &Name = F->getName(); 36 37 switch (F->getIntrinsicID()) { 38 case Intrinsic::sqrt_f32: 39 case Intrinsic::sqrt_f64: 40 case Intrinsic::bswap_i16: 41 case Intrinsic::bswap_i32: 42 case Intrinsic::bswap_i64: 43 case Intrinsic::powi_f32: 44 case Intrinsic::powi_f64: 45 // FIXME: these should be constant folded as well 46 //case Intrinsic::ctpop_i8: 47 //case Intrinsic::ctpop_i16: 48 //case Intrinsic::ctpop_i32: 49 //case Intrinsic::ctpop_i64: 50 //case Intrinsic::ctlz_i8: 51 //case Intrinsic::ctlz_i16: 52 //case Intrinsic::ctlz_i32: 53 //case Intrinsic::ctlz_i64: 54 //case Intrinsic::cttz_i8: 55 //case Intrinsic::cttz_i16: 56 //case Intrinsic::cttz_i32: 57 //case Intrinsic::cttz_i64: 58 return true; 59 default: break; 60 } 61 62 switch (Name[0]) 63 { 64 case 'a': 65 return Name == "acos" || Name == "asin" || Name == "atan" || 66 Name == "atan2"; 67 case 'c': 68 return Name == "ceil" || Name == "cos" || Name == "cosf" || 69 Name == "cosh"; 70 case 'e': 71 return Name == "exp"; 72 case 'f': 73 return Name == "fabs" || Name == "fmod" || Name == "floor"; 74 case 'l': 75 return Name == "log" || Name == "log10"; 76 case 'p': 77 return Name == "pow"; 78 case 's': 79 return Name == "sin" || Name == "sinh" || 80 Name == "sqrt" || Name == "sqrtf"; 81 case 't': 82 return Name == "tan" || Name == "tanh"; 83 default: 84 return false; 85 } 86} 87 88Constant * 89llvm::ConstantFoldFP(double (*NativeFP)(double), double V, const Type *Ty) { 90 errno = 0; 91 V = NativeFP(V); 92 if (errno == 0) 93 return ConstantFP::get(Ty, V); 94 return 0; 95} 96 97/// ConstantFoldCall - Attempt to constant fold a call to the specified function 98/// with the specified arguments, returning null if unsuccessful. 99Constant * 100llvm::ConstantFoldCall(Function *F, const std::vector<Constant*> &Operands) { 101 const std::string &Name = F->getName(); 102 const Type *Ty = F->getReturnType(); 103 104 if (Operands.size() == 1) { 105 if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) { 106 double V = Op->getValue(); 107 switch (Name[0]) 108 { 109 case 'a': 110 if (Name == "acos") 111 return ConstantFoldFP(acos, V, Ty); 112 else if (Name == "asin") 113 return ConstantFoldFP(asin, V, Ty); 114 else if (Name == "atan") 115 return ConstantFP::get(Ty, atan(V)); 116 break; 117 case 'c': 118 if (Name == "ceil") 119 return ConstantFoldFP(ceil, V, Ty); 120 else if (Name == "cos") 121 return ConstantFP::get(Ty, cos(V)); 122 else if (Name == "cosh") 123 return ConstantFP::get(Ty, cosh(V)); 124 break; 125 case 'e': 126 if (Name == "exp") 127 return ConstantFP::get(Ty, exp(V)); 128 break; 129 case 'f': 130 if (Name == "fabs") 131 return ConstantFP::get(Ty, fabs(V)); 132 else if (Name == "floor") 133 return ConstantFoldFP(floor, V, Ty); 134 break; 135 case 'l': 136 if (Name == "log" && V > 0) 137 return ConstantFP::get(Ty, log(V)); 138 else if (Name == "log10" && V > 0) 139 return ConstantFoldFP(log10, V, Ty); 140 else if (Name == "llvm.sqrt.f32" || Name == "llvm.sqrt.f64") { 141 if (V >= -0.0) 142 return ConstantFP::get(Ty, sqrt(V)); 143 else // Undefined 144 return ConstantFP::get(Ty, 0.0); 145 } 146 break; 147 case 's': 148 if (Name == "sin") 149 return ConstantFP::get(Ty, sin(V)); 150 else if (Name == "sinh") 151 return ConstantFP::get(Ty, sinh(V)); 152 else if (Name == "sqrt" && V >= 0) 153 return ConstantFP::get(Ty, sqrt(V)); 154 else if (Name == "sqrtf" && V >= 0) 155 return ConstantFP::get(Ty, sqrt((float)V)); 156 break; 157 case 't': 158 if (Name == "tan") 159 return ConstantFP::get(Ty, tan(V)); 160 else if (Name == "tanh") 161 return ConstantFP::get(Ty, tanh(V)); 162 break; 163 default: 164 break; 165 } 166 } else if (ConstantInt *Op = dyn_cast<ConstantInt>(Operands[0])) { 167 uint64_t V = Op->getZExtValue(); 168 if (Name == "llvm.bswap.i16") 169 return ConstantInt::get(Ty, ByteSwap_16(V)); 170 else if (Name == "llvm.bswap.i32") 171 return ConstantInt::get(Ty, ByteSwap_32(V)); 172 else if (Name == "llvm.bswap.i64") 173 return ConstantInt::get(Ty, ByteSwap_64(V)); 174 } 175 } else if (Operands.size() == 2) { 176 if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) { 177 double Op1V = Op1->getValue(); 178 if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) { 179 double Op2V = Op2->getValue(); 180 181 if (Name == "pow") { 182 errno = 0; 183 double V = pow(Op1V, Op2V); 184 if (errno == 0) 185 return ConstantFP::get(Ty, V); 186 } else if (Name == "fmod") { 187 errno = 0; 188 double V = fmod(Op1V, Op2V); 189 if (errno == 0) 190 return ConstantFP::get(Ty, V); 191 } else if (Name == "atan2") { 192 return ConstantFP::get(Ty, atan2(Op1V,Op2V)); 193 } 194 } else if (ConstantInt *Op2C = dyn_cast<ConstantInt>(Operands[1])) { 195 if (Name == "llvm.powi.f32") { 196 return ConstantFP::get(Ty, std::pow((float)Op1V, 197 (int)Op2C->getZExtValue())); 198 } else if (Name == "llvm.powi.f64") { 199 return ConstantFP::get(Ty, std::pow((double)Op1V, 200 (int)Op2C->getZExtValue())); 201 } 202 } 203 } 204 } 205 return 0; 206} 207 208