blob: 915a7cb734f5d8e84ae665c15952c0e3bed0e973 [file] [log] [blame]
John Criswellbd9d3702005-10-27 16:00:10 +00001//===-- 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::isunordered:
39 case Intrinsic::sqrt:
Nate Begeman6fb3bd62006-01-14 01:25:24 +000040 case Intrinsic::bswap_i16:
41 case Intrinsic::bswap_i32:
42 case Intrinsic::bswap_i64:
43 // FIXME: these should be constant folded as well
44 //case Intrinsic::ctpop:
45 //case Intrinsic::ctlz:
46 //case Intrinsic::cttz:
John Criswellbd9d3702005-10-27 16:00:10 +000047 return true;
48 default: break;
49 }
50
51 switch (Name[0])
52 {
53 case 'a':
54 return Name == "acos" || Name == "asin" || Name == "atan" ||
55 Name == "atan2";
56 case 'c':
57 return Name == "ceil" || Name == "cos" || Name == "cosf" ||
58 Name == "cosh";
59 case 'e':
60 return Name == "exp";
61 case 'f':
62 return Name == "fabs" || Name == "fmod" || Name == "floor";
63 case 'l':
64 return Name == "log" || Name == "log10";
65 case 'p':
66 return Name == "pow";
67 case 's':
68 return Name == "sin" || Name == "sinh" || Name == "sqrt";
69 case 't':
70 return Name == "tan" || Name == "tanh";
71 default:
72 return false;
73 }
74}
75
76Constant *
77llvm::ConstantFoldFP(double (*NativeFP)(double), double V, const Type *Ty) {
78 errno = 0;
79 V = NativeFP(V);
80 if (errno == 0)
81 return ConstantFP::get(Ty, V);
82 return 0;
83}
84
85/// ConstantFoldCall - Attempt to constant fold a call to the specified function
86/// with the specified arguments, returning null if unsuccessful.
87Constant *
88llvm::ConstantFoldCall(Function *F, const std::vector<Constant*> &Operands) {
89 const std::string &Name = F->getName();
90 const Type *Ty = F->getReturnType();
91
92 if (Operands.size() == 1) {
93 if (ConstantFP *Op = dyn_cast<ConstantFP>(Operands[0])) {
94 double V = Op->getValue();
95 switch (Name[0])
96 {
97 case 'a':
98 if (Name == "acos")
99 return ConstantFoldFP(acos, V, Ty);
100 else if (Name == "asin")
101 return ConstantFoldFP(asin, V, Ty);
102 else if (Name == "atan")
103 return ConstantFP::get(Ty, atan(V));
104 break;
105 case 'c':
106 if (Name == "ceil")
107 return ConstantFoldFP(ceil, V, Ty);
108 else if (Name == "cos")
109 return ConstantFP::get(Ty, cos(V));
110 else if (Name == "cosh")
111 return ConstantFP::get(Ty, cosh(V));
112 break;
113 case 'e':
114 if (Name == "exp")
115 return ConstantFP::get(Ty, exp(V));
116 break;
117 case 'f':
118 if (Name == "fabs")
119 return ConstantFP::get(Ty, fabs(V));
120 else if (Name == "floor")
121 return ConstantFoldFP(floor, V, Ty);
122 break;
123 case 'l':
124 if (Name == "log" && V > 0)
125 return ConstantFP::get(Ty, log(V));
126 else if (Name == "log10" && V > 0)
127 return ConstantFoldFP(log10, V, Ty);
128 else if (Name == "llvm.sqrt") {
129 if (V >= -0.0)
130 return ConstantFP::get(Ty, sqrt(V));
131 else // Undefined
132 return ConstantFP::get(Ty, 0.0);
133 }
134 break;
135 case 's':
136 if (Name == "sin")
137 return ConstantFP::get(Ty, sin(V));
138 else if (Name == "sinh")
139 return ConstantFP::get(Ty, sinh(V));
140 else if (Name == "sqrt" && V >= 0)
141 return ConstantFP::get(Ty, sqrt(V));
142 break;
143 case 't':
144 if (Name == "tan")
145 return ConstantFP::get(Ty, tan(V));
146 else if (Name == "tanh")
147 return ConstantFP::get(Ty, tanh(V));
148 break;
149 default:
150 break;
151 }
Nate Begeman6fb3bd62006-01-14 01:25:24 +0000152 } else if (ConstantUInt *Op = dyn_cast<ConstantUInt>(Operands[0])) {
153 uint64_t V = Op->getValue();
154 if (Name == "llvm.bswap.i16")
155 return ConstantUInt::get(Ty, ByteSwap_16(V));
156 else if (Name == "llvm.bswap.i32")
157 return ConstantUInt::get(Ty, ByteSwap_32(V));
158 else if (Name == "llvm.bswap.i64")
159 return ConstantUInt::get(Ty, ByteSwap_64(V));
John Criswellbd9d3702005-10-27 16:00:10 +0000160 }
161 } else if (Operands.size() == 2) {
162 if (ConstantFP *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
163 double Op1V = Op1->getValue();
164 if (ConstantFP *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
165 double Op2V = Op2->getValue();
166
167 if (Name == "llvm.isunordered")
168 return ConstantBool::get(IsNAN(Op1V) || IsNAN(Op2V));
169 else
170 if (Name == "pow") {
171 errno = 0;
172 double V = pow(Op1V, Op2V);
173 if (errno == 0)
174 return ConstantFP::get(Ty, V);
175 } else if (Name == "fmod") {
176 errno = 0;
177 double V = fmod(Op1V, Op2V);
178 if (errno == 0)
179 return ConstantFP::get(Ty, V);
180 } else if (Name == "atan2")
181 return ConstantFP::get(Ty, atan2(Op1V,Op2V));
182 }
183 }
184 }
185 return 0;
186}
187