ConstantFolding.cpp revision 72d88ae5447a3929c97e88f4c806213847b5d988
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 88static Constant *ConstantFoldFP(double (*NativeFP)(double), double V, 89 const Type *Ty) { 90 errno = 0; 91 V = NativeFP(V); 92 if (errno == 0) 93 return ConstantFP::get(Ty, V); 94 errno = 0; 95 return 0; 96} 97 98/// ConstantFoldCall - Attempt to constant fold a call to the specified function 99/// with the specified arguments, returning null if unsuccessful. 100Constant * 101llvm::ConstantFoldCall(Function *F, Constant** Operands, unsigned NumOperands) { 102 const std::string &Name = F->getName(); 103 const Type *Ty = F->getReturnType(); 104 105 if (NumOperands == 1) { 106 if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) { 107 double V = Op->getValue(); 108 switch (Name[0]) 109 { 110 case 'a': 111 if (Name == "acos") 112 return ConstantFoldFP(acos, V, Ty); 113 else if (Name == "asin") 114 return ConstantFoldFP(asin, V, Ty); 115 else if (Name == "atan") 116 return ConstantFP::get(Ty, atan(V)); 117 break; 118 case 'c': 119 if (Name == "ceil") 120 return ConstantFoldFP(ceil, V, Ty); 121 else if (Name == "cos") 122 return ConstantFP::get(Ty, cos(V)); 123 else if (Name == "cosh") 124 return ConstantFP::get(Ty, cosh(V)); 125 break; 126 case 'e': 127 if (Name == "exp") 128 return ConstantFP::get(Ty, exp(V)); 129 break; 130 case 'f': 131 if (Name == "fabs") 132 return ConstantFP::get(Ty, fabs(V)); 133 else if (Name == "floor") 134 return ConstantFoldFP(floor, V, Ty); 135 break; 136 case 'l': 137 if (Name == "log" && V > 0) 138 return ConstantFP::get(Ty, log(V)); 139 else if (Name == "log10" && V > 0) 140 return ConstantFoldFP(log10, V, Ty); 141 else if (Name == "llvm.sqrt.f32" || Name == "llvm.sqrt.f64") { 142 if (V >= -0.0) 143 return ConstantFP::get(Ty, sqrt(V)); 144 else // Undefined 145 return ConstantFP::get(Ty, 0.0); 146 } 147 break; 148 case 's': 149 if (Name == "sin") 150 return ConstantFP::get(Ty, sin(V)); 151 else if (Name == "sinh") 152 return ConstantFP::get(Ty, sinh(V)); 153 else if (Name == "sqrt" && V >= 0) 154 return ConstantFP::get(Ty, sqrt(V)); 155 else if (Name == "sqrtf" && V >= 0) 156 return ConstantFP::get(Ty, sqrt((float)V)); 157 break; 158 case 't': 159 if (Name == "tan") 160 return ConstantFP::get(Ty, tan(V)); 161 else if (Name == "tanh") 162 return ConstantFP::get(Ty, tanh(V)); 163 break; 164 default: 165 break; 166 } 167 } else if (ConstantInt *Op = dyn_cast<ConstantInt>(Operands[0])) { 168 uint64_t V = Op->getZExtValue(); 169 if (Name == "llvm.bswap.i16") 170 return ConstantInt::get(Ty, ByteSwap_16(V)); 171 else if (Name == "llvm.bswap.i32") 172 return ConstantInt::get(Ty, ByteSwap_32(V)); 173 else if (Name == "llvm.bswap.i64") 174 return ConstantInt::get(Ty, ByteSwap_64(V)); 175 } 176 } else if (NumOperands == 2) { 177 if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) { 178 double Op1V = Op1->getValue(); 179 if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) { 180 double Op2V = Op2->getValue(); 181 182 if (Name == "pow") { 183 errno = 0; 184 double V = pow(Op1V, Op2V); 185 if (errno == 0) 186 return ConstantFP::get(Ty, V); 187 } else if (Name == "fmod") { 188 errno = 0; 189 double V = fmod(Op1V, Op2V); 190 if (errno == 0) 191 return ConstantFP::get(Ty, V); 192 } else if (Name == "atan2") { 193 return ConstantFP::get(Ty, atan2(Op1V,Op2V)); 194 } 195 } else if (ConstantInt *Op2C = dyn_cast<ConstantInt>(Operands[1])) { 196 if (Name == "llvm.powi.f32") { 197 return ConstantFP::get(Ty, std::pow((float)Op1V, 198 (int)Op2C->getZExtValue())); 199 } else if (Name == "llvm.powi.f64") { 200 return ConstantFP::get(Ty, std::pow((double)Op1V, 201 (int)Op2C->getZExtValue())); 202 } 203 } 204 } 205 } 206 return 0; 207} 208 209