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 }