Simplify.
[oota-llvm.git] / lib / VMCore / LLVMContextImpl.cpp
1 //===--------------- LLVMContextImpl.cpp - Implementation ------*- C++ -*--===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements LLVMContextImpl, the opaque implementation 
11 //  of LLVMContext.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "LLVMContextImpl.h"
16 #include "llvm/Constants.h"
17 #include "llvm/DerivedTypes.h"
18 #include "llvm/LLVMContext.h"
19 #include "llvm/MDNode.h"
20 using namespace llvm;
21
22 static char getValType(ConstantAggregateZero *CPZ) { return 0; }
23
24 static std::vector<Constant*> getValType(ConstantArray *CA) {
25   std::vector<Constant*> Elements;
26   Elements.reserve(CA->getNumOperands());
27   for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
28     Elements.push_back(cast<Constant>(CA->getOperand(i)));
29   return Elements;
30 }
31
32 static std::vector<Constant*> getValType(ConstantStruct *CS) {
33   std::vector<Constant*> Elements;
34   Elements.reserve(CS->getNumOperands());
35   for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
36     Elements.push_back(cast<Constant>(CS->getOperand(i)));
37   return Elements;
38 }
39
40 static std::vector<Constant*> getValType(ConstantVector *CP) {
41   std::vector<Constant*> Elements;
42   Elements.reserve(CP->getNumOperands());
43   for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i)
44     Elements.push_back(CP->getOperand(i));
45   return Elements;
46 }
47
48
49 LLVMContextImpl::LLVMContextImpl(LLVMContext &C) :
50     Context(C), TheTrueVal(0), TheFalseVal(0) { }
51
52
53 ConstantFP *LLVMContextImpl::getConstantFP(const APFloat &V) {
54   DenseMapAPFloatKeyInfo::KeyTy Key(V);
55   
56   ConstantsLock.reader_acquire();
57   ConstantFP *&Slot = FPConstants[Key];
58   ConstantsLock.reader_release();
59     
60   if (!Slot) {
61     sys::SmartScopedWriter<true> Writer(ConstantsLock);
62     ConstantFP *&NewSlot = FPConstants[Key];
63     if (!NewSlot) {
64       const Type *Ty;
65       if (&V.getSemantics() == &APFloat::IEEEsingle)
66         Ty = Type::FloatTy;
67       else if (&V.getSemantics() == &APFloat::IEEEdouble)
68         Ty = Type::DoubleTy;
69       else if (&V.getSemantics() == &APFloat::x87DoubleExtended)
70         Ty = Type::X86_FP80Ty;
71       else if (&V.getSemantics() == &APFloat::IEEEquad)
72         Ty = Type::FP128Ty;
73       else {
74         assert(&V.getSemantics() == &APFloat::PPCDoubleDouble && 
75                "Unknown FP format");
76         Ty = Type::PPC_FP128Ty;
77       }
78       NewSlot = new ConstantFP(Ty, V);
79     }
80     
81     return NewSlot;
82   }
83   
84   return Slot;
85 }
86
87 MDString *LLVMContextImpl::getMDString(const char *StrBegin,
88                                        unsigned StrLength) {
89   sys::SmartScopedWriter<true> Writer(ConstantsLock);
90   StringMapEntry<MDString *> &Entry = 
91     MDStringCache.GetOrCreateValue(StringRef(StrBegin, StrLength));
92   MDString *&S = Entry.getValue();
93   if (!S) S = new MDString(Entry.getKeyData(),
94                            Entry.getKeyLength());
95
96   return S;
97 }
98
99 MDNode *LLVMContextImpl::getMDNode(Value*const* Vals, unsigned NumVals) {
100   FoldingSetNodeID ID;
101   for (unsigned i = 0; i != NumVals; ++i)
102     ID.AddPointer(Vals[i]);
103
104   ConstantsLock.reader_acquire();
105   void *InsertPoint;
106   MDNode *N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
107   ConstantsLock.reader_release();
108   
109   if (!N) {
110     sys::SmartScopedWriter<true> Writer(ConstantsLock);
111     N = MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
112     if (!N) {
113       // InsertPoint will have been set by the FindNodeOrInsertPos call.
114       N = new MDNode(Vals, NumVals);
115       MDNodeSet.InsertNode(N, InsertPoint);
116     }
117   }
118
119   return N;
120 }
121
122 ConstantAggregateZero*
123 LLVMContextImpl::getConstantAggregateZero(const Type *Ty) {
124   assert((isa<StructType>(Ty) || isa<ArrayType>(Ty) || isa<VectorType>(Ty)) &&
125          "Cannot create an aggregate zero of non-aggregate type!");
126
127   // Implicitly locked.
128   return AggZeroConstants.getOrCreate(Ty, 0);
129 }
130
131 Constant *LLVMContextImpl::getConstantArray(const ArrayType *Ty,
132                              const std::vector<Constant*> &V) {
133   // If this is an all-zero array, return a ConstantAggregateZero object
134   if (!V.empty()) {
135     Constant *C = V[0];
136     if (!C->isNullValue()) {
137       // Implicitly locked.
138       return ArrayConstants.getOrCreate(Ty, V);
139     }
140     for (unsigned i = 1, e = V.size(); i != e; ++i)
141       if (V[i] != C) {
142         // Implicitly locked.
143         return ArrayConstants.getOrCreate(Ty, V);
144       }
145   }
146   
147   return Context.getConstantAggregateZero(Ty);
148 }
149
150 Constant *LLVMContextImpl::getConstantStruct(const StructType *Ty,
151                               const std::vector<Constant*> &V) {
152   // Create a ConstantAggregateZero value if all elements are zeros...
153   for (unsigned i = 0, e = V.size(); i != e; ++i)
154     if (!V[i]->isNullValue())
155       // Implicitly locked.
156       return StructConstants.getOrCreate(Ty, V);
157
158   return Context.getConstantAggregateZero(Ty);
159 }
160
161 Constant *LLVMContextImpl::getConstantVector(const VectorType *Ty,
162                               const std::vector<Constant*> &V) {
163   assert(!V.empty() && "Vectors can't be empty");
164   // If this is an all-undef or alll-zero vector, return a
165   // ConstantAggregateZero or UndefValue.
166   Constant *C = V[0];
167   bool isZero = C->isNullValue();
168   bool isUndef = isa<UndefValue>(C);
169
170   if (isZero || isUndef) {
171     for (unsigned i = 1, e = V.size(); i != e; ++i)
172       if (V[i] != C) {
173         isZero = isUndef = false;
174         break;
175       }
176   }
177   
178   if (isZero)
179     return Context.getConstantAggregateZero(Ty);
180   if (isUndef)
181     return Context.getUndef(Ty);
182     
183   // Implicitly locked.
184   return VectorConstants.getOrCreate(Ty, V);
185 }
186
187 // *** erase methods ***
188
189 void LLVMContextImpl::erase(MDString *M) {
190   sys::SmartScopedWriter<true> Writer(ConstantsLock);
191   MDStringCache.erase(MDStringCache.find(M->getString()));
192 }
193
194 void LLVMContextImpl::erase(MDNode *M) {
195   sys::SmartScopedWriter<true> Writer(ConstantsLock);
196   MDNodeSet.RemoveNode(M);
197 }
198
199 void LLVMContextImpl::erase(ConstantAggregateZero *Z) {
200   AggZeroConstants.remove(Z);
201 }
202
203 void LLVMContextImpl::erase(ConstantArray *C) {
204   ArrayConstants.remove(C);
205 }
206
207 void LLVMContextImpl::erase(ConstantStruct *S) {
208   StructConstants.remove(S);
209 }
210
211 void LLVMContextImpl::erase(ConstantVector *V) {
212   VectorConstants.remove(V);
213 }
214
215 // *** RAUW helpers ***
216
217 Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantArray *CA,
218                                                Value *From, Value *To, Use *U) {
219   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
220   Constant *ToC = cast<Constant>(To);
221
222   std::pair<ArrayConstantsTy::MapKey, Constant*> Lookup;
223   Lookup.first.first = CA->getType();
224   Lookup.second = CA;
225
226   std::vector<Constant*> &Values = Lookup.first.second;
227   Values.reserve(CA->getNumOperands());  // Build replacement array.
228
229   // Fill values with the modified operands of the constant array.  Also, 
230   // compute whether this turns into an all-zeros array.
231   bool isAllZeros = false;
232   unsigned NumUpdated = 0;
233   if (!ToC->isNullValue()) {
234     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
235          O != E; ++O) {
236       Constant *Val = cast<Constant>(O->get());
237       if (Val == From) {
238         Val = ToC;
239         ++NumUpdated;
240       }
241       Values.push_back(Val);
242     }
243   } else {
244     isAllZeros = true;
245     for (Use *O = CA->OperandList, *E = CA->OperandList + CA->getNumOperands();
246          O != E; ++O) {
247       Constant *Val = cast<Constant>(O->get());
248       if (Val == From) {
249         Val = ToC;
250         ++NumUpdated;
251       }
252       Values.push_back(Val);
253       if (isAllZeros) isAllZeros = Val->isNullValue();
254     }
255   }
256   
257   Constant *Replacement = 0;
258   if (isAllZeros) {
259     Replacement = Context.getConstantAggregateZero(CA->getType());
260   } else {
261     // Check to see if we have this array type already.
262     sys::SmartScopedWriter<true> Writer(ConstantsLock);
263     bool Exists;
264     ArrayConstantsTy::MapTy::iterator I =
265       ArrayConstants.InsertOrGetItem(Lookup, Exists);
266     
267     if (Exists) {
268       Replacement = I->second;
269     } else {
270       // Okay, the new shape doesn't exist in the system yet.  Instead of
271       // creating a new constant array, inserting it, replaceallusesof'ing the
272       // old with the new, then deleting the old... just update the current one
273       // in place!
274       ArrayConstants.MoveConstantToNewSlot(CA, I);
275       
276       // Update to the new value.  Optimize for the case when we have a single
277       // operand that we're changing, but handle bulk updates efficiently.
278       if (NumUpdated == 1) {
279         unsigned OperandToUpdate = U - CA->OperandList;
280         assert(CA->getOperand(OperandToUpdate) == From &&
281                "ReplaceAllUsesWith broken!");
282         CA->setOperand(OperandToUpdate, ToC);
283       } else {
284         for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
285           if (CA->getOperand(i) == From)
286             CA->setOperand(i, ToC);
287       }
288       return 0;
289     }
290   }
291   
292   return Replacement;
293 }
294
295 Constant *LLVMContextImpl::replaceUsesOfWithOnConstant(ConstantStruct *CS,
296                                                Value *From, Value *To, Use *U) {
297   assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
298   Constant *ToC = cast<Constant>(To);
299
300   unsigned OperandToUpdate = U - CS->OperandList;
301   assert(CS->getOperand(OperandToUpdate) == From &&
302          "ReplaceAllUsesWith broken!");
303
304   std::pair<StructConstantsTy::MapKey, Constant*> Lookup;
305   Lookup.first.first = CS->getType();
306   Lookup.second = CS;
307   std::vector<Constant*> &Values = Lookup.first.second;
308   Values.reserve(CS->getNumOperands());  // Build replacement struct.
309   
310   
311   // Fill values with the modified operands of the constant struct.  Also, 
312   // compute whether this turns into an all-zeros struct.
313   bool isAllZeros = false;
314   if (!ToC->isNullValue()) {
315     for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
316          O != E; ++O)
317       Values.push_back(cast<Constant>(O->get()));
318   } else {
319     isAllZeros = true;
320     for (Use *O = CS->OperandList, *E = CS->OperandList + CS->getNumOperands(); 
321          O != E; ++O) {
322       Constant *Val = cast<Constant>(O->get());
323       Values.push_back(Val);
324       if (isAllZeros) isAllZeros = Val->isNullValue();
325     }
326   }
327   Values[OperandToUpdate] = ToC;
328   
329   Constant *Replacement = 0;
330   if (isAllZeros) {
331     Replacement = Context.getConstantAggregateZero(CS->getType());
332   } else {
333     // Check to see if we have this array type already.
334     sys::SmartScopedWriter<true> Writer(ConstantsLock);
335     bool Exists;
336     StructConstantsTy::MapTy::iterator I =
337       StructConstants.InsertOrGetItem(Lookup, Exists);
338     
339     if (Exists) {
340       Replacement = I->second;
341     } else {
342       // Okay, the new shape doesn't exist in the system yet.  Instead of
343       // creating a new constant struct, inserting it, replaceallusesof'ing the
344       // old with the new, then deleting the old... just update the current one
345       // in place!
346       StructConstants.MoveConstantToNewSlot(CS, I);
347       
348       // Update to the new value.
349       CS->setOperand(OperandToUpdate, ToC);
350       return 0;
351     }
352   }
353   
354   assert(Replacement != CS && "I didn't contain From!");
355   
356   return Replacement;
357 }