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::PerformDefaultLowering(Function &F, GCStrategy &S) { InsertAutomaticGCRoots(F, S); // FIXME: Turn this back on after fixing gcregroot in SelectionDAG. //InsertGCRegisterRoots(F, S); bool LowerWr = !S.customWriteBarrier(); bool LowerRd = !S.customReadBarrier(); bool InitRoots = S.initializeRoots(); SmallVector<Instruction *, 32> Roots; bool MadeChange = false; for (Function::iterator BB = F.begin(), BE = F.end(); BB != BE; ++BB) { for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;) { if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) { Function *F = CI->getCalledFunction(); switch (F->getIntrinsicID()) { case Intrinsic::gcwrite: if (LowerWr) { // Replace a write barrier with a simple store. Value *St = new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2), CI); CI->replaceAllUsesWith(St); CI->eraseFromParent(); } break; case Intrinsic::gcread: if (LowerRd) { // Replace a read barrier with a simple load. Value *Ld = new LoadInst(CI->getArgOperand(1), "", CI); Ld->takeName(CI); CI->replaceAllUsesWith(Ld); CI->eraseFromParent(); } break; case Intrinsic::gcroot: if (InitRoots) { // Initialize the GC root, but do not delete the intrinsic. The // backend needs the intrinsic to flag the stack slot. Value *V = CI->getArgOperand(0)->stripPointerCastsOnly(); Roots.push_back(cast<Instruction>(V)); } break; default: continue; } MadeChange = true; } } } if (Roots.size()) MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size()); return MadeChange; }