comparison gen/passes/GarbageCollect2Stack.cpp @ 1424:ad999630aa35

Teach -dgc2stack to preserve the call graph. This should allow for more efficient execution by the pass manager.
author Frits van Bommel <fvbommel wxs.nl>
date Thu, 28 May 2009 02:14:01 +0200
parents 67ac63740c7f
children c363d131c1ef
comparison
equal deleted inserted replaced
1423:42bd767ec5a4 1424:ad999630aa35
28 #include "llvm/Intrinsics.h" 28 #include "llvm/Intrinsics.h"
29 #include "llvm/Support/CallSite.h" 29 #include "llvm/Support/CallSite.h"
30 #include "llvm/Support/CommandLine.h" 30 #include "llvm/Support/CommandLine.h"
31 #include "llvm/Support/IRBuilder.h" 31 #include "llvm/Support/IRBuilder.h"
32 #include "llvm/Analysis/CaptureTracking.h" 32 #include "llvm/Analysis/CaptureTracking.h"
33 #include "llvm/Analysis/CallGraph.h"
33 #include "llvm/Analysis/ValueTracking.h" 34 #include "llvm/Analysis/ValueTracking.h"
34 #include "llvm/Analysis/LoopInfo.h" 35 #include "llvm/Analysis/LoopInfo.h"
35 #include "llvm/Target/TargetData.h" 36 #include "llvm/Target/TargetData.h"
36 #include "llvm/ADT/StringMap.h" 37 #include "llvm/ADT/StringMap.h"
37 #include "llvm/ADT/Statistic.h" 38 #include "llvm/ADT/Statistic.h"
41 42
42 STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas"); 43 STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas");
43 STATISTIC(NumToDynSize, "Number of calls promoted to dynamically-sized allocas"); 44 STATISTIC(NumToDynSize, "Number of calls promoted to dynamically-sized allocas");
44 STATISTIC(NumDeleted, "Number of GC calls deleted because the return value was unused"); 45 STATISTIC(NumDeleted, "Number of GC calls deleted because the return value was unused");
45 46
46 //===----------------------------------------------------------------------===//
47 // Helper functions
48 //===----------------------------------------------------------------------===//
49
50 void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len) {
51 Dst = B.CreateBitCast(Dst, PointerType::getUnqual(Type::Int8Ty));
52
53 Module *M = B.GetInsertBlock()->getParent()->getParent();
54 const Type* Tys[1];
55 Tys[0] = Len->getType();
56 Value *MemSet = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 1);
57 Value *Align = ConstantInt::get(Type::Int32Ty, 1);
58
59 B.CreateCall4(MemSet, Dst, Val, Len, Align);
60 }
61
62 static void EmitMemZero(IRBuilder<>& B, Value* Dst, Value* Len) {
63 EmitMemSet(B, Dst, ConstantInt::get(Type::Int8Ty, 0), Len);
64 }
65
66
67 //===----------------------------------------------------------------------===//
68 // Helpers for specific types of GC calls.
69 //===----------------------------------------------------------------------===//
70 47
71 namespace { 48 namespace {
72 struct Analysis { 49 struct Analysis {
73 TargetData& TD; 50 TargetData& TD;
74 const Module& M; 51 const Module& M;
52 CallGraph* CG;
53 CallGraphNode* CGNode;
75 54
76 const Type* getTypeFor(Value* typeinfo) const; 55 const Type* getTypeFor(Value* typeinfo) const;
77 }; 56 };
78 57 }
58
59 //===----------------------------------------------------------------------===//
60 // Helper functions
61 //===----------------------------------------------------------------------===//
62
63 void EmitMemSet(IRBuilder<>& B, Value* Dst, Value* Val, Value* Len,
64 const Analysis& A) {
65 Dst = B.CreateBitCast(Dst, PointerType::getUnqual(Type::Int8Ty));
66
67 Module *M = B.GetInsertBlock()->getParent()->getParent();
68 const Type* Tys[1];
69 Tys[0] = Len->getType();
70 Function *MemSet = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys, 1);
71 Value *Align = ConstantInt::get(Type::Int32Ty, 1);
72
73 CallSite CS = B.CreateCall4(MemSet, Dst, Val, Len, Align);
74 if (A.CGNode)
75 A.CGNode->addCalledFunction(CS, A.CG->getOrInsertFunction(MemSet));
76 }
77
78 static void EmitMemZero(IRBuilder<>& B, Value* Dst, Value* Len,
79 const Analysis& A) {
80 EmitMemSet(B, Dst, ConstantInt::get(Type::Int8Ty, 0), Len, A);
81 }
82
83
84 //===----------------------------------------------------------------------===//
85 // Helpers for specific types of GC calls.
86 //===----------------------------------------------------------------------===//
87
88 namespace {
79 class FunctionInfo { 89 class FunctionInfo {
80 protected: 90 protected:
81 const Type* Ty; 91 const Type* Ty;
82 92
83 public: 93 public:
172 uint64_t size = A.TD.getTypeStoreSize(Ty); 182 uint64_t size = A.TD.getTypeStoreSize(Ty);
173 Value* TypeSize = ConstantInt::get(arrSize->getType(), size); 183 Value* TypeSize = ConstantInt::get(arrSize->getType(), size);
174 // Use the original B to put initialization at the 184 // Use the original B to put initialization at the
175 // allocation site. 185 // allocation site.
176 Value* Size = B.CreateMul(TypeSize, arrSize); 186 Value* Size = B.CreateMul(TypeSize, arrSize);
177 EmitMemZero(B, alloca, Size); 187 EmitMemZero(B, alloca, Size, A);
178 } 188 }
179 189
180 return alloca; 190 return alloca;
181 } 191 }
182 }; 192 };
257 bool runOnFunction(Function &F); 267 bool runOnFunction(Function &F);
258 268
259 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 269 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
260 AU.addRequired<TargetData>(); 270 AU.addRequired<TargetData>();
261 AU.addRequired<LoopInfo>(); 271 AU.addRequired<LoopInfo>();
272 AU.addPreserved<CallGraph>();
262 } 273 }
263 }; 274 };
264 char GarbageCollect2Stack::ID = 0; 275 char GarbageCollect2Stack::ID = 0;
265 } // end anonymous namespace. 276 } // end anonymous namespace.
266 277
282 KnownFunctions["_d_newarrayvT"] = &NewArrayVT; 293 KnownFunctions["_d_newarrayvT"] = &NewArrayVT;
283 KnownFunctions["_d_newarrayT"] = &NewArrayT; 294 KnownFunctions["_d_newarrayT"] = &NewArrayT;
284 KnownFunctions["_d_allocclass"] = &AllocClass; 295 KnownFunctions["_d_allocclass"] = &AllocClass;
285 } 296 }
286 297
287 static void RemoveCall(Instruction* Inst) { 298 static void RemoveCall(CallSite CS, const Analysis& A) {
288 if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) { 299 if (CS.isInvoke()) {
300 InvokeInst* Invoke = cast<InvokeInst>(CS.getInstruction());
289 // If this was an invoke instruction, we need to do some extra 301 // If this was an invoke instruction, we need to do some extra
290 // work to preserve the control flow. 302 // work to preserve the control flow.
291 303
292 // First notify the exception landing pad block that we won't be 304 // First notify the exception landing pad block that we won't be
293 // going there anymore. 305 // going there anymore.
294 Invoke->getUnwindDest()->removePredecessor(Invoke->getParent()); 306 Invoke->getUnwindDest()->removePredecessor(Invoke->getParent());
295 // Create a branch to the "normal" destination. 307 // Create a branch to the "normal" destination.
296 BranchInst::Create(Invoke->getNormalDest(), Invoke->getParent()); 308 BranchInst::Create(Invoke->getNormalDest(), Invoke->getParent());
297 } 309 }
298 // Remove the runtime call. 310 // Remove the runtime call.
299 Inst->eraseFromParent(); 311 if (A.CGNode)
312 A.CGNode->removeCallEdgeFor(CS);
313 CS.getInstruction()->eraseFromParent();
300 } 314 }
301 315
302 /// runOnFunction - Top level algorithm. 316 /// runOnFunction - Top level algorithm.
303 /// 317 ///
304 bool GarbageCollect2Stack::runOnFunction(Function &F) { 318 bool GarbageCollect2Stack::runOnFunction(Function &F) {
305 DEBUG(DOUT << "Running -dgc2stack on function " << F.getName() << '\n'); 319 DEBUG(DOUT << "Running -dgc2stack on function " << F.getName() << '\n');
306 320
307 TargetData &TD = getAnalysis<TargetData>(); 321 TargetData &TD = getAnalysis<TargetData>();
308 const LoopInfo &LI = getAnalysis<LoopInfo>(); 322 const LoopInfo &LI = getAnalysis<LoopInfo>();
309 323 CallGraph* CG = getAnalysisIfAvailable<CallGraph>();
310 Analysis A = { TD, *M }; 324 CallGraphNode* CGNode = CG ? (*CG)[&F] : NULL;
325
326 Analysis A = { TD, *M, CG, CGNode };
311 327
312 BasicBlock& Entry = F.getEntryBlock(); 328 BasicBlock& Entry = F.getEntryBlock();
313 329
314 IRBuilder<> AllocaBuilder(&Entry, Entry.begin()); 330 IRBuilder<> AllocaBuilder(&Entry, Entry.begin());
315 331
349 FunctionInfo* info = OMI->getValue(); 365 FunctionInfo* info = OMI->getValue();
350 366
351 if (Inst->use_empty() && info->SafeToDelete) { 367 if (Inst->use_empty() && info->SafeToDelete) {
352 Changed = true; 368 Changed = true;
353 NumDeleted++; 369 NumDeleted++;
354 RemoveCall(Inst); 370 RemoveCall(CS, A);
355 continue; 371 continue;
356 } 372 }
357 373
358 DEBUG(DOUT << "GarbageCollect2Stack inspecting: " << *Inst); 374 DEBUG(DOUT << "GarbageCollect2Stack inspecting: " << *Inst);
359 375
372 // uses of the runtime call with the alloca. 388 // uses of the runtime call with the alloca.
373 if (newVal->getType() != Inst->getType()) 389 if (newVal->getType() != Inst->getType())
374 newVal = Builder.CreateBitCast(newVal, Inst->getType()); 390 newVal = Builder.CreateBitCast(newVal, Inst->getType());
375 Inst->replaceAllUsesWith(newVal); 391 Inst->replaceAllUsesWith(newVal);
376 392
377 RemoveCall(Inst); 393 RemoveCall(CS, A);
378 } 394 }
379 } 395 }
380 396
381 return Changed; 397 return Changed;
382 } 398 }