Mercurial > projects > ldc
comparison gen/passes/GarbageCollect2Stack.cpp @ 1548:a326f145a57b
ConstantInt::get{True,False} moved to LLVMContext
Non-breaking build fix for LLVM r76533. Also fixes a context related
bug in GarbageCollect2Stack.
author | Benjamin Kramer <benny.kra@gmail.com> |
---|---|
date | Tue, 21 Jul 2009 13:11:39 +0200 |
parents | 7fcb72d518f6 |
children | ed0feda76820 |
comparison
equal
deleted
inserted
replaced
1547:259b031f3d22 | 1548:a326f145a57b |
---|---|
83 //===----------------------------------------------------------------------===// | 83 //===----------------------------------------------------------------------===// |
84 | 84 |
85 namespace { | 85 namespace { |
86 class FunctionInfo { | 86 class FunctionInfo { |
87 protected: | 87 protected: |
88 LLVMContext* Context; | |
89 const Type* Ty; | 88 const Type* Ty; |
90 | 89 |
91 public: | 90 public: |
92 unsigned TypeInfoArgNr; | 91 unsigned TypeInfoArgNr; |
93 bool SafeToDelete; | 92 bool SafeToDelete; |
94 | 93 |
95 // Analyze the current call, filling in some fields. Returns true if | 94 // Analyze the current call, filling in some fields. Returns true if |
96 // this is an allocation we can stack-allocate. | 95 // this is an allocation we can stack-allocate. |
97 virtual bool analyze(CallSite CS, const Analysis& A) { | 96 virtual bool analyze(LLVMContext& context, CallSite CS, const Analysis& A) { |
98 Value* TypeInfo = CS.getArgument(TypeInfoArgNr); | 97 Value* TypeInfo = CS.getArgument(TypeInfoArgNr); |
99 Ty = A.getTypeFor(TypeInfo); | 98 Ty = A.getTypeFor(TypeInfo); |
100 return (Ty != NULL); | 99 return (Ty != NULL); |
101 } | 100 } |
102 | 101 |
103 // Returns the alloca to replace this call. | 102 // Returns the alloca to replace this call. |
104 // It will always be inserted before the call. | 103 // It will always be inserted before the call. |
105 virtual AllocaInst* promote(CallSite CS, IRBuilder<>& B, const Analysis& A) { | 104 virtual AllocaInst* promote(LLVMContext& context, CallSite CS, IRBuilder<>& B, const Analysis& A) { |
106 NumGcToStack++; | 105 NumGcToStack++; |
107 | 106 |
108 Instruction* Begin = CS.getCaller()->getEntryBlock().begin(); | 107 Instruction* Begin = CS.getCaller()->getEntryBlock().begin(); |
109 return new AllocaInst(Ty, ".nongc_mem", Begin); // FIXME: align? | 108 return new AllocaInst(Ty, ".nongc_mem", Begin); // FIXME: align? |
110 } | 109 } |
111 | 110 |
112 FunctionInfo(LLVMContext* context, unsigned typeInfoArgNr, bool safeToDelete) | 111 FunctionInfo(unsigned typeInfoArgNr, bool safeToDelete) |
113 : Context(context), TypeInfoArgNr(typeInfoArgNr), SafeToDelete(safeToDelete) {} | 112 : TypeInfoArgNr(typeInfoArgNr), SafeToDelete(safeToDelete) {} |
114 }; | 113 }; |
115 | 114 |
116 class ArrayFI : public FunctionInfo { | 115 class ArrayFI : public FunctionInfo { |
117 Value* arrSize; | 116 Value* arrSize; |
118 int ArrSizeArgNr; | 117 int ArrSizeArgNr; |
119 bool Initialized; | 118 bool Initialized; |
120 | 119 |
121 public: | 120 public: |
122 ArrayFI(LLVMContext* context, unsigned tiArgNr, bool safeToDelete, | 121 ArrayFI(unsigned tiArgNr, bool safeToDelete, |
123 bool initialized, unsigned arrSizeArgNr) | 122 bool initialized, unsigned arrSizeArgNr) |
124 : FunctionInfo(context, tiArgNr, safeToDelete), | 123 : FunctionInfo(tiArgNr, safeToDelete), |
125 ArrSizeArgNr(arrSizeArgNr), | 124 ArrSizeArgNr(arrSizeArgNr), |
126 Initialized(initialized) | 125 Initialized(initialized) |
127 {} | 126 {} |
128 | 127 |
129 virtual bool analyze(CallSite CS, const Analysis& A) { | 128 virtual bool analyze(LLVMContext& context, CallSite CS, const Analysis& A) { |
130 if (!FunctionInfo::analyze(CS, A)) | 129 if (!FunctionInfo::analyze(context, CS, A)) |
131 return false; | 130 return false; |
132 | 131 |
133 arrSize = CS.getArgument(ArrSizeArgNr); | 132 arrSize = CS.getArgument(ArrSizeArgNr); |
134 const IntegerType* SizeType = | 133 const IntegerType* SizeType = |
135 dyn_cast<IntegerType>(arrSize->getType()); | 134 dyn_cast<IntegerType>(arrSize->getType()); |
153 cast<PointerType>(ArrTy->getElementType(1)); | 152 cast<PointerType>(ArrTy->getElementType(1)); |
154 Ty = PtrTy->getElementType(); | 153 Ty = PtrTy->getElementType(); |
155 return true; | 154 return true; |
156 } | 155 } |
157 | 156 |
158 virtual AllocaInst* promote(CallSite CS, IRBuilder<>& B, const Analysis& A) { | 157 virtual AllocaInst* promote(LLVMContext& context, CallSite CS, IRBuilder<>& B, const Analysis& A) { |
159 IRBuilder<> Builder = B; | 158 IRBuilder<> Builder = B; |
160 // If the allocation is of constant size it's best to put it in the | 159 // If the allocation is of constant size it's best to put it in the |
161 // entry block, so do so if we're not already there. | 160 // entry block, so do so if we're not already there. |
162 // For dynamically-sized allocations it's best to avoid the overhead | 161 // For dynamically-sized allocations it's best to avoid the overhead |
163 // of allocating them if possible, so leave those where they are. | 162 // of allocating them if possible, so leave those where they are. |
176 AllocaInst* alloca = Builder.CreateAlloca(Ty, count, ".nongc_mem"); // FIXME: align? | 175 AllocaInst* alloca = Builder.CreateAlloca(Ty, count, ".nongc_mem"); // FIXME: align? |
177 | 176 |
178 if (Initialized) { | 177 if (Initialized) { |
179 // For now, only zero-init is supported. | 178 // For now, only zero-init is supported. |
180 uint64_t size = A.TD.getTypeStoreSize(Ty); | 179 uint64_t size = A.TD.getTypeStoreSize(Ty); |
181 Value* TypeSize = Context->getConstantInt(arrSize->getType(), size); | 180 Value* TypeSize = context.getConstantInt(arrSize->getType(), size); |
182 // Use the original B to put initialization at the | 181 // Use the original B to put initialization at the |
183 // allocation site. | 182 // allocation site. |
184 Value* Size = B.CreateMul(TypeSize, arrSize); | 183 Value* Size = B.CreateMul(TypeSize, arrSize); |
185 EmitMemZero(*Context, B, alloca, Size, A); | 184 EmitMemZero(context, B, alloca, Size, A); |
186 } | 185 } |
187 | 186 |
188 return alloca; | 187 return alloca; |
189 } | 188 } |
190 }; | 189 }; |
191 | 190 |
192 // FunctionInfo for _d_allocclass | 191 // FunctionInfo for _d_allocclass |
193 class AllocClassFI : public FunctionInfo { | 192 class AllocClassFI : public FunctionInfo { |
194 public: | 193 public: |
195 virtual bool analyze(CallSite CS, const Analysis& A) { | 194 virtual bool analyze(LLVMContext& context, CallSite CS, const Analysis& A) { |
196 // This call contains no TypeInfo parameter, so don't call the | 195 // This call contains no TypeInfo parameter, so don't call the |
197 // base class implementation here... | 196 // base class implementation here... |
198 if (CS.arg_size() != 1) | 197 if (CS.arg_size() != 1) |
199 return false; | 198 return false; |
200 Value* arg = CS.getArgument(0)->stripPointerCasts(); | 199 Value* arg = CS.getArgument(0)->stripPointerCasts(); |
221 // those can be ignored) | 220 // those can be ignored) |
222 Constant* hasCustomDelete = dyn_cast<Constant>(MD_GetElement(node, CD_CustomDelete)); | 221 Constant* hasCustomDelete = dyn_cast<Constant>(MD_GetElement(node, CD_CustomDelete)); |
223 if (hasDestructor == NULL || hasCustomDelete == NULL) | 222 if (hasDestructor == NULL || hasCustomDelete == NULL) |
224 return false; | 223 return false; |
225 | 224 |
226 if (Context->getConstantExprOr(hasDestructor, hasCustomDelete) | 225 if (context.getConstantExprOr(hasDestructor, hasCustomDelete) |
227 != ConstantInt::getFalse()) | 226 != context.getConstantIntFalse()) |
228 return false; | 227 return false; |
229 | 228 |
230 Ty = MD_GetElement(node, CD_BodyType)->getType(); | 229 Ty = MD_GetElement(node, CD_BodyType)->getType(); |
231 return true; | 230 return true; |
232 } | 231 } |
233 | 232 |
234 // The default promote() should be fine. | 233 // The default promote() should be fine. |
235 | 234 |
236 AllocClassFI(LLVMContext* context) : FunctionInfo(context, ~0u, true) {} | 235 AllocClassFI() : FunctionInfo(~0u, true) {} |
237 }; | 236 }; |
238 } | 237 } |
239 | 238 |
240 | 239 |
241 //===----------------------------------------------------------------------===// | 240 //===----------------------------------------------------------------------===// |
257 public: | 256 public: |
258 static char ID; // Pass identification | 257 static char ID; // Pass identification |
259 GarbageCollect2Stack(); | 258 GarbageCollect2Stack(); |
260 | 259 |
261 bool doInitialization(Module &M) { | 260 bool doInitialization(Module &M) { |
261 Context = &M.getContext(); | |
262 this->M = &M; | 262 this->M = &M; |
263 return false; | 263 return false; |
264 } | 264 } |
265 | 265 |
266 bool runOnFunction(Function &F); | 266 bool runOnFunction(Function &F); |
284 return new GarbageCollect2Stack(); | 284 return new GarbageCollect2Stack(); |
285 } | 285 } |
286 | 286 |
287 GarbageCollect2Stack::GarbageCollect2Stack() | 287 GarbageCollect2Stack::GarbageCollect2Stack() |
288 : FunctionPass(&ID), | 288 : FunctionPass(&ID), |
289 AllocMemoryT(Context, 0, true), | 289 AllocMemoryT(0, true), |
290 NewArrayVT(Context, 0, true, false, 1), | 290 NewArrayVT(0, true, false, 1), |
291 NewArrayT(Context, 0, true, true, 1), | 291 NewArrayT(0, true, true, 1) |
292 AllocClass(Context) | |
293 { | 292 { |
294 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; | 293 KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT; |
295 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; | 294 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; |
296 KnownFunctions["_d_newarrayT"] = &NewArrayT; | 295 KnownFunctions["_d_newarrayT"] = &NewArrayT; |
297 KnownFunctions["_d_allocclass"] = &AllocClass; | 296 KnownFunctions["_d_allocclass"] = &AllocClass; |
298 } | 297 } |
299 | 298 |
300 static void RemoveCall(CallSite CS, const Analysis& A) { | 299 static void RemoveCall(LLVMContext& context, CallSite CS, const Analysis& A) { |
301 if (CS.isInvoke()) { | 300 if (CS.isInvoke()) { |
302 InvokeInst* Invoke = cast<InvokeInst>(CS.getInstruction()); | 301 InvokeInst* Invoke = cast<InvokeInst>(CS.getInstruction()); |
303 // If this was an invoke instruction, we need to do some extra | 302 // If this was an invoke instruction, we need to do some extra |
304 // work to preserve the control flow. | 303 // work to preserve the control flow. |
305 | 304 |
306 // Create a "conditional" branch that -simplifycfg can clean up, so we | 305 // Create a "conditional" branch that -simplifycfg can clean up, so we |
307 // can keep using the DominatorTree without updating it. | 306 // can keep using the DominatorTree without updating it. |
308 BranchInst::Create(Invoke->getNormalDest(), Invoke->getUnwindDest(), | 307 BranchInst::Create(Invoke->getNormalDest(), Invoke->getUnwindDest(), |
309 ConstantInt::getTrue(), Invoke->getParent()); | 308 context.getConstantIntTrue(), Invoke->getParent()); |
310 } | 309 } |
311 // Remove the runtime call. | 310 // Remove the runtime call. |
312 if (A.CGNode) | 311 if (A.CGNode) |
313 A.CGNode->removeCallEdgeFor(CS); | 312 A.CGNode->removeCallEdgeFor(CS); |
314 CS.getInstruction()->eraseFromParent(); | 313 CS.getInstruction()->eraseFromParent(); |
359 FunctionInfo* info = OMI->getValue(); | 358 FunctionInfo* info = OMI->getValue(); |
360 | 359 |
361 if (Inst->use_empty() && info->SafeToDelete) { | 360 if (Inst->use_empty() && info->SafeToDelete) { |
362 Changed = true; | 361 Changed = true; |
363 NumDeleted++; | 362 NumDeleted++; |
364 RemoveCall(CS, A); | 363 RemoveCall(*Context, CS, A); |
365 continue; | 364 continue; |
366 } | 365 } |
367 | 366 |
368 DEBUG(DOUT << "GarbageCollect2Stack inspecting: " << *Inst); | 367 DEBUG(DOUT << "GarbageCollect2Stack inspecting: " << *Inst); |
369 | 368 |
370 if (!info->analyze(CS, A) || !isSafeToStackAllocate(Inst, DT)) | 369 if (!info->analyze(*Context, CS, A) || !isSafeToStackAllocate(Inst, DT)) |
371 continue; | 370 continue; |
372 | 371 |
373 // Let's alloca this! | 372 // Let's alloca this! |
374 Changed = true; | 373 Changed = true; |
375 | 374 |
376 IRBuilder<> Builder(BB, Inst); | 375 IRBuilder<> Builder(BB, Inst); |
377 Value* newVal = info->promote(CS, Builder, A); | 376 Value* newVal = info->promote(*Context, CS, Builder, A); |
378 | 377 |
379 DEBUG(DOUT << "Promoted to: " << *newVal); | 378 DEBUG(DOUT << "Promoted to: " << *newVal); |
380 | 379 |
381 // Make sure the type is the same as it was before, and replace all | 380 // Make sure the type is the same as it was before, and replace all |
382 // uses of the runtime call with the alloca. | 381 // uses of the runtime call with the alloca. |
383 if (newVal->getType() != Inst->getType()) | 382 if (newVal->getType() != Inst->getType()) |
384 newVal = Builder.CreateBitCast(newVal, Inst->getType()); | 383 newVal = Builder.CreateBitCast(newVal, Inst->getType()); |
385 Inst->replaceAllUsesWith(newVal); | 384 Inst->replaceAllUsesWith(newVal); |
386 | 385 |
387 RemoveCall(CS, A); | 386 RemoveCall(*Context, CS, A); |
388 } | 387 } |
389 } | 388 } |
390 | 389 |
391 return Changed; | 390 return Changed; |
392 } | 391 } |