X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FGCRootLowering.cpp;h=484d31737b2e4150ac198f8c3576ee84f505e91e;hb=f79435efbed8ec33e851c2154447c3f6c64e3296;hp=4b788d3ffce1b2effbbfb31f54bbf264acef15fd;hpb=71649b0d0dbb7b519142fb1a3317c48b43dd0933;p=oota-llvm.git diff --git a/lib/CodeGen/GCRootLowering.cpp b/lib/CodeGen/GCRootLowering.cpp index 4b788d3ffce..484d31737b2 100644 --- a/lib/CodeGen/GCRootLowering.cpp +++ b/lib/CodeGen/GCRootLowering.cpp @@ -11,6 +11,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/CodeGen/GCMetadata.h" #include "llvm/CodeGen/GCStrategy.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" @@ -33,76 +34,64 @@ using namespace llvm; namespace { - /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or - /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as - /// directed by the GCStrategy. It also performs automatic root initialization - /// and custom intrinsic lowering. - class LowerIntrinsics : public FunctionPass { - static bool NeedsDefaultLoweringPass(const GCStrategy &C); - static bool NeedsCustomLoweringPass(const GCStrategy &C); - static bool CouldBecomeSafePoint(Instruction *I); - bool PerformDefaultLowering(Function &F, GCStrategy &Coll); - static bool InsertRootInitializers(Function &F, - AllocaInst **Roots, unsigned Count); - - public: - static char ID; - - LowerIntrinsics(); - const char *getPassName() const override; - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool doInitialization(Module &M) override; - bool runOnFunction(Function &F) override; - }; - - - /// GCMachineCodeAnalysis - This is a target-independent pass over the machine - /// function representation to identify safe points for the garbage collector - /// in the machine code. It inserts labels at safe points and populates a - /// GCMetadata record for each function. - class GCMachineCodeAnalysis : public MachineFunctionPass { - const TargetMachine *TM; - GCFunctionInfo *FI; - MachineModuleInfo *MMI; - const TargetInstrInfo *TII; - - void FindSafePoints(MachineFunction &MF); - void VisitCallPoint(MachineBasicBlock::iterator MI); - MCSymbol *InsertLabel(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, - DebugLoc DL) const; - - void FindStackOffsets(MachineFunction &MF); - - public: - static char ID; - - GCMachineCodeAnalysis(); - void getAnalysisUsage(AnalysisUsage &AU) const override; - - bool runOnMachineFunction(MachineFunction &MF) override; - }; +/// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or +/// llvm.gcwrite intrinsics, replacing them with simple loads and stores as +/// directed by the GCStrategy. It also performs automatic root initialization +/// and custom intrinsic lowering. +class LowerIntrinsics : public FunctionPass { + bool PerformDefaultLowering(Function &F, GCStrategy &Coll); +public: + static char ID; + + LowerIntrinsics(); + const char *getPassName() const override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool doInitialization(Module &M) override; + bool runOnFunction(Function &F) override; +}; + +/// GCMachineCodeAnalysis - This is a target-independent pass over the machine +/// function representation to identify safe points for the garbage collector +/// in the machine code. It inserts labels at safe points and populates a +/// GCMetadata record for each function. +class GCMachineCodeAnalysis : public MachineFunctionPass { + GCFunctionInfo *FI; + MachineModuleInfo *MMI; + const TargetInstrInfo *TII; + + void FindSafePoints(MachineFunction &MF); + void VisitCallPoint(MachineBasicBlock::iterator MI); + MCSymbol *InsertLabel(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + DebugLoc DL) const; + + void FindStackOffsets(MachineFunction &MF); + +public: + static char ID; + + GCMachineCodeAnalysis(); + void getAnalysisUsage(AnalysisUsage &AU) const override; + + bool runOnMachineFunction(MachineFunction &MF) override; +}; } // ----------------------------------------------------------------------------- -INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", - false, false) +INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false, + false) INITIALIZE_PASS_DEPENDENCY(GCModuleInfo) INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false) -FunctionPass *llvm::createGCLoweringPass() { - return new LowerIntrinsics(); -} +FunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); } char LowerIntrinsics::ID = 0; -LowerIntrinsics::LowerIntrinsics() - : FunctionPass(ID) { - initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry()); - } +LowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) { + initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry()); +} const char *LowerIntrinsics::getPassName() const { return "Lower Garbage Collection Instructions"; @@ -114,74 +103,27 @@ void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved(); } +static bool NeedsDefaultLoweringPass(const GCStrategy &C) { + // Default lowering is necessary only if read or write barriers have a default + // action. The default for roots is no action. + return !C.customWriteBarrier() || !C.customReadBarrier() || + C.initializeRoots(); +} + /// doInitialization - If this module uses the GC intrinsics, find them now. bool LowerIntrinsics::doInitialization(Module &M) { - // FIXME: This is rather antisocial in the context of a JIT since it performs - // work against the entire module. But this cannot be done at - // runFunction time (initializeCustomLowering likely needs to change - // the module). GCModuleInfo *MI = getAnalysisIfAvailable(); assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?"); for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration() && I->hasGC()) MI->getFunctionInfo(*I); // Instantiate the GC strategy. - bool MadeChange = false; - for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I) - if (NeedsCustomLoweringPass(**I)) - if ((*I)->initializeCustomLowering(M)) - MadeChange = true; - - return MadeChange; -} - -bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots, - unsigned Count) { - // Scroll past alloca instructions. - BasicBlock::iterator IP = F.getEntryBlock().begin(); - while (isa(IP)) ++IP; - - // Search for initializers in the initial BB. - SmallPtrSet InitedRoots; - for (; !CouldBecomeSafePoint(IP); ++IP) - if (StoreInst *SI = dyn_cast(IP)) - if (AllocaInst *AI = - dyn_cast(SI->getOperand(1)->stripPointerCasts())) - InitedRoots.insert(AI); - - // Add root initializers. - bool MadeChange = false; - - for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) - if (!InitedRoots.count(*I)) { - StoreInst* SI = new StoreInst(ConstantPointerNull::get(cast( - cast((*I)->getType())->getElementType())), - *I); - SI->insertAfter(*I); - MadeChange = true; - } - - return MadeChange; -} - -bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &C) { - // Default lowering is necessary only if read or write barriers have a default - // action. The default for roots is no action. - return !C.customWriteBarrier() - || !C.customReadBarrier() - || C.initializeRoots(); -} - -bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) { - // Custom lowering is only necessary if enabled for some action. - return C.customWriteBarrier() - || C.customReadBarrier() - || C.customRoots(); + return false; } /// CouldBecomeSafePoint - Predicate to conservatively determine whether the /// instruction could introduce a safe point. -bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) { +static bool CouldBecomeSafePoint(Instruction *I) { // The natural definition of instructions which could introduce safe points // are: // @@ -193,20 +135,51 @@ bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) { // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead // it is necessary to take a conservative approach. - if (isa(I) || isa(I) || - isa(I) || isa(I)) + if (isa(I) || isa(I) || isa(I) || + isa(I)) return false; // llvm.gcroot is safe because it doesn't do anything at runtime. if (CallInst *CI = dyn_cast(I)) if (Function *F = CI->getCalledFunction()) - if (unsigned IID = F->getIntrinsicID()) + if (Intrinsic::ID IID = F->getIntrinsicID()) if (IID == Intrinsic::gcroot) return false; return true; } +static bool InsertRootInitializers(Function &F, AllocaInst **Roots, + unsigned Count) { + // Scroll past alloca instructions. + BasicBlock::iterator IP = F.getEntryBlock().begin(); + while (isa(IP)) + ++IP; + + // Search for initializers in the initial BB. + SmallPtrSet InitedRoots; + for (; !CouldBecomeSafePoint(&*IP); ++IP) + if (StoreInst *SI = dyn_cast(IP)) + if (AllocaInst *AI = + dyn_cast(SI->getOperand(1)->stripPointerCasts())) + InitedRoots.insert(AI); + + // Add root initializers. + bool MadeChange = false; + + for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I) + if (!InitedRoots.count(*I)) { + StoreInst *SI = new StoreInst( + ConstantPointerNull::get(cast( + cast((*I)->getType())->getElementType())), + *I); + SI->insertAfter(*I); + MadeChange = true; + } + + return MadeChange; +} + /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores. /// Leave gcroot intrinsics; the code generator needs to see those. bool LowerIntrinsics::runOnFunction(Function &F) { @@ -222,17 +195,6 @@ bool LowerIntrinsics::runOnFunction(Function &F) { if (NeedsDefaultLoweringPass(S)) MadeChange |= PerformDefaultLowering(F, S); - bool UseCustomLoweringPass = NeedsCustomLoweringPass(S); - if (UseCustomLoweringPass) - MadeChange |= S.performCustomLowering(F); - - // Custom lowering may modify the CFG, so dominators must be recomputed. - if (UseCustomLoweringPass) { - if (DominatorTreeWrapperPass *DTWP = - getAnalysisIfAvailable()) - DTWP->getDomTree().recalculate(F); - } - return MadeChange; } @@ -241,7 +203,7 @@ bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { bool LowerRd = !S.customReadBarrier(); bool InitRoots = S.initializeRoots(); - SmallVector Roots; + SmallVector Roots; bool MadeChange = false; for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { @@ -252,8 +214,8 @@ bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { case Intrinsic::gcwrite: if (LowerWr) { // Replace a write barrier with a simple store. - Value *St = new StoreInst(CI->getArgOperand(0), - CI->getArgOperand(2), CI); + Value *St = + new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2), CI); CI->replaceAllUsesWith(St); CI->eraseFromParent(); } @@ -271,8 +233,8 @@ bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) { if (InitRoots) { // Initialize the GC root, but do not delete the intrinsic. The // backend needs the intrinsic to flag the stack slot. - Roots.push_back(cast( - CI->getArgOperand(0)->stripPointerCasts())); + Roots.push_back( + cast(CI->getArgOperand(0)->stripPointerCasts())); } break; default: @@ -298,8 +260,7 @@ char &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID; INITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis", "Analyze Machine Code For Garbage Collection", false, false) -GCMachineCodeAnalysis::GCMachineCodeAnalysis() - : MachineFunctionPass(ID) {} +GCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {} void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { MachineFunctionPass::getAnalysisUsage(AU); @@ -311,7 +272,7 @@ void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const { MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, DebugLoc DL) const { - MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol(); + MCSymbol *Label = MBB.getParent()->getContext().createTempSymbol(); BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label); return Label; } @@ -323,27 +284,34 @@ void GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) { ++RAI; if (FI->getStrategy().needsSafePoint(GC::PreCall)) { - MCSymbol* Label = InsertLabel(*CI->getParent(), CI, CI->getDebugLoc()); + MCSymbol *Label = InsertLabel(*CI->getParent(), CI, CI->getDebugLoc()); FI->addSafePoint(GC::PreCall, Label, CI->getDebugLoc()); } if (FI->getStrategy().needsSafePoint(GC::PostCall)) { - MCSymbol* Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc()); + MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc()); FI->addSafePoint(GC::PostCall, Label, CI->getDebugLoc()); } } void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) { - for (MachineFunction::iterator BBI = MF.begin(), - BBE = MF.end(); BBI != BBE; ++BBI) - for (MachineBasicBlock::iterator MI = BBI->begin(), - ME = BBI->end(); MI != ME; ++MI) - if (MI->isCall()) + for (MachineFunction::iterator BBI = MF.begin(), BBE = MF.end(); BBI != BBE; + ++BBI) + for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end(); + MI != ME; ++MI) + if (MI->isCall()) { + // Do not treat tail or sibling call sites as safe points. This is + // legal since any arguments passed to the callee which live in the + // remnants of the callers frame will be owned and updated by the + // callee if required. + if (MI->isTerminator()) + continue; VisitCallPoint(MI); + } } void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { - const TargetFrameLowering *TFI = TM->getSubtargetImpl()->getFrameLowering(); + const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); assert(TFI && "TargetRegisterInfo not available!"); for (GCFunctionInfo::roots_iterator RI = FI->roots_begin(); @@ -352,7 +320,9 @@ void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) { if (MF.getFrameInfo()->isDeadObjectIndex(RI->Num)) { RI = FI->removeStackRoot(RI); } else { - RI->StackOffset = TFI->getFrameIndexOffset(MF, RI->Num); + unsigned FrameReg; // FIXME: surely GCRoot ought to store the + // register that the offset is from? + RI->StackOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg); ++RI; } } @@ -364,24 +334,22 @@ bool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) { return false; FI = &getAnalysis().getFunctionInfo(*MF.getFunction()); - if (!FI->getStrategy().needsSafePoints()) - return false; - - TM = &MF.getTarget(); MMI = &getAnalysis(); - TII = TM->getSubtargetImpl()->getInstrInfo(); + TII = MF.getSubtarget().getInstrInfo(); - // Find the size of the stack frame. - FI->setFrameSize(MF.getFrameInfo()->getStackSize()); + // Find the size of the stack frame. There may be no correct static frame + // size, we use UINT64_MAX to represent this. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); + const bool DynamicFrameSize = MFI->hasVarSizedObjects() || + RegInfo->needsStackRealignment(MF); + FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI->getStackSize()); // Find all safe points. - if (FI->getStrategy().customSafePoints()) { - FI->getStrategy().findCustomSafePoints(*FI, MF); - } else { + if (FI->getStrategy().needsSafePoints()) FindSafePoints(MF); - } - // Find the stack offsets for all roots. + // Find the concrete stack offsets for all roots (stack slots) FindStackOffsets(MF); return false;