LLVM API Documentation

GCStrategy.cpp

Go to the documentation of this file.
00001 //===-- GCStrategy.cpp - Garbage collection infrastructure -----------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements target- and collector-independent garbage collection
00011 // infrastructure.
00012 //
00013 // MachineCodeAnalysis identifies the GC safe points in the machine code. Roots
00014 // are identified in SelectionDAGISel.
00015 //
00016 //===----------------------------------------------------------------------===//
00017 
00018 #include "llvm/CodeGen/GCStrategy.h"
00019 #include "llvm/CodeGen/Passes.h"
00020 #include "llvm/IntrinsicInst.h"
00021 #include "llvm/Module.h"
00022 #include "llvm/CodeGen/MachineFrameInfo.h"
00023 #include "llvm/CodeGen/MachineFunctionPass.h"
00024 #include "llvm/CodeGen/MachineInstrBuilder.h"
00025 #include "llvm/CodeGen/MachineModuleInfo.h"
00026 #include "llvm/Target/TargetFrameInfo.h"
00027 #include "llvm/Target/TargetInstrInfo.h"
00028 #include "llvm/Target/TargetMachine.h"
00029 #include "llvm/Target/TargetRegisterInfo.h"
00030 #include "llvm/Support/Compiler.h"
00031 
00032 using namespace llvm;
00033 
00034 namespace {
00035   
00036   /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or
00037   /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as 
00038   /// directed by the GCStrategy. It also performs automatic root initialization
00039   /// and custom intrinsic lowering.
00040   class VISIBILITY_HIDDEN LowerIntrinsics : public FunctionPass {
00041     static bool NeedsDefaultLoweringPass(const GCStrategy &C);
00042     static bool NeedsCustomLoweringPass(const GCStrategy &C);
00043     static bool CouldBecomeSafePoint(Instruction *I);
00044     bool PerformDefaultLowering(Function &F, GCStrategy &Coll);
00045     static bool InsertRootInitializers(Function &F,
00046                                        AllocaInst **Roots, unsigned Count);
00047     
00048   public:
00049     static char ID;
00050     
00051     LowerIntrinsics();
00052     const char *getPassName() const;
00053     void getAnalysisUsage(AnalysisUsage &AU) const;
00054     
00055     bool doInitialization(Module &M);
00056     bool runOnFunction(Function &F);
00057   };
00058   
00059   
00060   /// MachineCodeAnalysis - This is a target-independent pass over the machine 
00061   /// function representation to identify safe points for the garbage collector
00062   /// in the machine code. It inserts labels at safe points and populates a
00063   /// GCMetadata record for each function.
00064   class VISIBILITY_HIDDEN MachineCodeAnalysis : public MachineFunctionPass {
00065     const TargetMachine *TM;
00066     GCFunctionInfo *FI;
00067     MachineModuleInfo *MMI;
00068     const TargetInstrInfo *TII;
00069     
00070     void FindSafePoints(MachineFunction &MF);
00071     void VisitCallPoint(MachineBasicBlock::iterator MI);
00072     unsigned InsertLabel(MachineBasicBlock &MBB, 
00073                          MachineBasicBlock::iterator MI) const;
00074     
00075     void FindStackOffsets(MachineFunction &MF);
00076     
00077   public:
00078     static char ID;
00079     
00080     MachineCodeAnalysis();
00081     const char *getPassName() const;
00082     void getAnalysisUsage(AnalysisUsage &AU) const;
00083     
00084     bool runOnMachineFunction(MachineFunction &MF);
00085   };
00086   
00087 }
00088 
00089 // -----------------------------------------------------------------------------
00090 
00091 GCStrategy::GCStrategy() :
00092   NeededSafePoints(0),
00093   CustomReadBarriers(false),
00094   CustomWriteBarriers(false),
00095   CustomRoots(false),
00096   InitRoots(true),
00097   UsesMetadata(false)
00098 {}
00099 
00100 GCStrategy::~GCStrategy() {
00101   for (iterator I = begin(), E = end(); I != E; ++I)
00102     delete *I;
00103   
00104   Functions.clear();
00105 }
00106  
00107 bool GCStrategy::initializeCustomLowering(Module &M) { return false; }
00108  
00109 bool GCStrategy::performCustomLowering(Function &F) {
00110   cerr << "gc " << getName() << " must override performCustomLowering.\n";
00111   abort();
00112   return 0;
00113 }
00114 
00115 GCFunctionInfo *GCStrategy::insertFunctionInfo(const Function &F) {
00116   GCFunctionInfo *FI = new GCFunctionInfo(F, *this);
00117   Functions.push_back(FI);
00118   return FI;
00119 }
00120 
00121 // -----------------------------------------------------------------------------
00122 
00123 FunctionPass *llvm::createGCLoweringPass() {
00124   return new LowerIntrinsics();
00125 }
00126  
00127 char LowerIntrinsics::ID = 0;
00128 
00129 LowerIntrinsics::LowerIntrinsics()
00130   : FunctionPass(&ID) {}
00131 
00132 const char *LowerIntrinsics::getPassName() const {
00133   return "Lower Garbage Collection Instructions";
00134 }
00135     
00136 void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
00137   FunctionPass::getAnalysisUsage(AU);
00138   AU.addRequired<GCModuleInfo>();
00139 }
00140 
00141 /// doInitialization - If this module uses the GC intrinsics, find them now.
00142 bool LowerIntrinsics::doInitialization(Module &M) {
00143   // FIXME: This is rather antisocial in the context of a JIT since it performs
00144   //        work against the entire module. But this cannot be done at
00145   //        runFunction time (initializeCustomLowering likely needs to change
00146   //        the module).
00147   GCModuleInfo *MI = getAnalysisToUpdate<GCModuleInfo>();
00148   assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
00149   for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
00150     if (!I->isDeclaration() && I->hasGC())
00151       MI->getFunctionInfo(*I); // Instantiate the GC strategy.
00152   
00153   bool MadeChange = false;
00154   for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I)
00155     if (NeedsCustomLoweringPass(**I))
00156       if ((*I)->initializeCustomLowering(M))
00157         MadeChange = true;
00158   
00159   return MadeChange;
00160 }
00161 
00162 bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, 
00163                                                           unsigned Count) {
00164   // Scroll past alloca instructions.
00165   BasicBlock::iterator IP = F.getEntryBlock().begin();
00166   while (isa<AllocaInst>(IP)) ++IP;
00167   
00168   // Search for initializers in the initial BB.
00169   SmallPtrSet<AllocaInst*,16> InitedRoots;
00170   for (; !CouldBecomeSafePoint(IP); ++IP)
00171     if (StoreInst *SI = dyn_cast<StoreInst>(IP))
00172       if (AllocaInst *AI =
00173           dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts()))
00174         InitedRoots.insert(AI);
00175   
00176   // Add root initializers.
00177   bool MadeChange = false;
00178   
00179   for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I)
00180     if (!InitedRoots.count(*I)) {
00181       new StoreInst(ConstantPointerNull::get(cast<PointerType>(
00182                       cast<PointerType>((*I)->getType())->getElementType())),
00183                     *I, IP);
00184       MadeChange = true;
00185     }
00186   
00187   return MadeChange;
00188 }
00189 
00190 bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &C) {
00191   // Default lowering is necessary only if read or write barriers have a default
00192   // action. The default for roots is no action.
00193   return !C.customWriteBarrier()
00194       || !C.customReadBarrier()
00195       || C.initializeRoots();
00196 }
00197 
00198 bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) {
00199   // Custom lowering is only necessary if enabled for some action.
00200   return C.customWriteBarrier()
00201       || C.customReadBarrier()
00202       || C.customRoots();
00203 }
00204 
00205 /// CouldBecomeSafePoint - Predicate to conservatively determine whether the
00206 /// instruction could introduce a safe point.
00207 bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) {
00208   // The natural definition of instructions which could introduce safe points
00209   // are:
00210   // 
00211   //   - call, invoke (AfterCall, BeforeCall)
00212   //   - phis (Loops)
00213   //   - invoke, ret, unwind (Exit)
00214   // 
00215   // However, instructions as seemingly inoccuous as arithmetic can become
00216   // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
00217   // it is necessary to take a conservative approach.
00218   
00219   if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) ||
00220       isa<StoreInst>(I) || isa<LoadInst>(I))
00221     return false;
00222   
00223   // llvm.gcroot is safe because it doesn't do anything at runtime.
00224   if (CallInst *CI = dyn_cast<CallInst>(I))
00225     if (Function *F = CI->getCalledFunction())
00226       if (unsigned IID = F->getIntrinsicID())
00227         if (IID == Intrinsic::gcroot)
00228           return false;
00229   
00230   return true;
00231 }
00232 
00233 /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
00234 /// Leave gcroot intrinsics; the code generator needs to see those.
00235 bool LowerIntrinsics::runOnFunction(Function &F) {
00236   // Quick exit for functions that do not use GC.
00237   if (!F.hasGC())
00238     return false;
00239   
00240   GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F);
00241   GCStrategy &S = FI.getStrategy();
00242   
00243   bool MadeChange = false;
00244   
00245   if (NeedsDefaultLoweringPass(S))
00246     MadeChange |= PerformDefaultLowering(F, S);
00247   
00248   if (NeedsCustomLoweringPass(S))
00249     MadeChange |= S.performCustomLowering(F);
00250   
00251   return MadeChange;
00252 }
00253 
00254 bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) {
00255   bool LowerWr = !S.customWriteBarrier();
00256   bool LowerRd = !S.customReadBarrier();
00257   bool InitRoots = S.initializeRoots();
00258   
00259   SmallVector<AllocaInst*,32> Roots;
00260   
00261   bool MadeChange = false;
00262   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
00263     for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
00264       if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) {
00265         Function *F = CI->getCalledFunction();
00266         switch (F->getIntrinsicID()) {
00267         case Intrinsic::gcwrite:
00268           if (LowerWr) {
00269             // Replace a write barrier with a simple store.
00270             Value *St = new StoreInst(CI->getOperand(1), CI->getOperand(3), CI);
00271             CI->replaceAllUsesWith(St);
00272             CI->eraseFromParent();
00273           }
00274           break;
00275         case Intrinsic::gcread:
00276           if (LowerRd) {
00277             // Replace a read barrier with a simple load.
00278             Value *Ld = new LoadInst(CI->getOperand(2), "", CI);
00279             Ld->takeName(CI);
00280             CI->replaceAllUsesWith(Ld);
00281             CI->eraseFromParent();
00282           }
00283           break;
00284         case Intrinsic::gcroot:
00285           if (InitRoots) {
00286             // Initialize the GC root, but do not delete the intrinsic. The
00287             // backend needs the intrinsic to flag the stack slot.
00288             Roots.push_back(cast<AllocaInst>(
00289                               CI->getOperand(1)->stripPointerCasts()));
00290           }
00291           break;
00292         default:
00293           continue;
00294         }
00295         
00296         MadeChange = true;
00297       }
00298     }
00299   }
00300   
00301   if (Roots.size())
00302     MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size());
00303   
00304   return MadeChange;
00305 }
00306 
00307 // -----------------------------------------------------------------------------
00308 
00309 FunctionPass *llvm::createGCMachineCodeAnalysisPass() {
00310   return new MachineCodeAnalysis();
00311 }
00312 
00313 char MachineCodeAnalysis::ID = 0;
00314 
00315 MachineCodeAnalysis::MachineCodeAnalysis()
00316   : MachineFunctionPass(intptr_t(&ID)) {}
00317 
00318 const char *MachineCodeAnalysis::getPassName() const {
00319   return "Analyze Machine Code For Garbage Collection";
00320 }
00321 
00322 void MachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
00323   MachineFunctionPass::getAnalysisUsage(AU);
00324   AU.setPreservesAll();
00325   AU.addRequired<MachineModuleInfo>();
00326   AU.addRequired<GCModuleInfo>();
00327 }
00328 
00329 unsigned MachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, 
00330                                      MachineBasicBlock::iterator MI) const {
00331   unsigned Label = MMI->NextLabelID();
00332   BuildMI(MBB, MI, TII->get(TargetInstrInfo::GC_LABEL)).addImm(Label);
00333   return Label;
00334 }
00335 
00336 void MachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
00337   // Find the return address (next instruction), too, so as to bracket the call
00338   // instruction.
00339   MachineBasicBlock::iterator RAI = CI; 
00340   ++RAI;                                
00341   
00342   if (FI->getStrategy().needsSafePoint(GC::PreCall))
00343     FI->addSafePoint(GC::PreCall, InsertLabel(*CI->getParent(), CI));
00344   
00345   if (FI->getStrategy().needsSafePoint(GC::PostCall))
00346     FI->addSafePoint(GC::PostCall, InsertLabel(*CI->getParent(), RAI));
00347 }
00348 
00349 void MachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
00350   for (MachineFunction::iterator BBI = MF.begin(),
00351                                  BBE = MF.end(); BBI != BBE; ++BBI)
00352     for (MachineBasicBlock::iterator MI = BBI->begin(),
00353                                      ME = BBI->end(); MI != ME; ++MI)
00354       if (MI->getDesc().isCall())
00355         VisitCallPoint(MI);
00356 }
00357 
00358 void MachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
00359   const TargetRegisterInfo *TRI = TM->getRegisterInfo();
00360   assert(TRI && "TargetRegisterInfo not available!");
00361   
00362   for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(),
00363                                       RE = FI->roots_end(); RI != RE; ++RI)
00364     RI->StackOffset = TRI->getFrameIndexOffset(MF, RI->Num);
00365 }
00366 
00367 bool MachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
00368   // Quick exit for functions that do not use GC.
00369   if (!MF.getFunction()->hasGC())
00370     return false;
00371   
00372   FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction());
00373   if (!FI->getStrategy().needsSafePoints())
00374     return false;
00375   
00376   TM = &MF.getTarget();
00377   MMI = &getAnalysis<MachineModuleInfo>();
00378   TII = TM->getInstrInfo();
00379   
00380   // Find the size of the stack frame.
00381   FI->setFrameSize(MF.getFrameInfo()->getStackSize());
00382   
00383   // Find all safe points.
00384   FindSafePoints(MF);
00385   
00386   // Find the stack offsets for all roots.
00387   FindStackOffsets(MF);
00388   
00389   return false;
00390 }



This web site is hosted by the Computer Science Department at the University of Illinois at Urbana-Champaign.