// Topologically sorts the basic blocks in the function and writes the ordering // into the supplied unique vector. The back and incoming edges must have been // computed first. void LiveIRVariables::computeTopologicalOrdering(Function &F, UniqueVector<BasicBlock *> &Ordering) { assert(IncomingEdges.size() == F.size() && "Incoming edges not computed yet!"); SmallVector<unsigned, 256> ProcessedIncomingEdges; ProcessedIncomingEdges.resize(F.size(), 0); SmallVector<BasicBlock *, 256> WorkList; WorkList.push_back(&F.getEntryBlock()); while (!WorkList.empty()) { BasicBlock *BB = WorkList.back(); WorkList.pop_back(); DEBUG(dbgs() << "Assigning topological order " << Ordering.size()); DEBUG(dbgs() << " to basic block with DFS order "); DEBUG(dbgs() << (DFSOrdering.idFor(BB) - 1) << "\n"); Ordering.insert(BB); for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) { if (BackEdges.count(std::make_pair(BB, *SI))) continue; unsigned DFSID = DFSOrdering.idFor(*SI) - 1; unsigned ProcessedEdges = ++ProcessedIncomingEdges[DFSID]; if (ProcessedEdges == IncomingEdges[DFSID]) WorkList.push_back(*SI); } } }
// Computes reduced reachability. A basic block B is reduced reachable from a // basic block A if A has a path to B that passes through no blocks that // dominate A. void LiveIRVariables::computeReducedReachability(Function &F) { // Compute a topological ordering. UniqueVector<BasicBlock *> TopologicalOrdering; computeTopologicalOrdering(F, TopologicalOrdering); // Initialize the reduced reachability matrix. ReducedReachability.resize(DFSOrdering.size()); // Iterate over the basic blocks in reverse order, building up the reduced // reachability matrix. for (unsigned i = TopologicalOrdering.size() - 1; i != (unsigned)-1; --i) { BasicBlock *BB = TopologicalOrdering[i + 1]; unsigned BBIndex = DFSOrdering.idFor(BB) - 1; BitVector &BV = ReducedReachability[BBIndex]; BV.resize(DFSOrdering.size()); BV[BBIndex] = true; for (succ_iterator SI = succ_begin(BB), SE = succ_end(BB); SI != SE; ++SI) { if (TopologicalOrdering.idFor(*SI) - 1 < i) continue; // Ignore back edges. unsigned SuccessorIndex = DFSOrdering.idFor(*SI) - 1; BV.set(SuccessorIndex); BV |= ReducedReachability[SuccessorIndex]; } } #ifndef NDEBUG for (unsigned i = 0, ie = ReducedReachability.size(); i != ie; ++i) { DEBUG(dbgs() << "Reduced reachability of " << i << ":"); BitVector &BV = ReducedReachability[i]; for (unsigned j = 0, je = BV.size(); j != je; ++j) { if (BV[j]) DEBUG(dbgs() << " " << j); } DEBUG(dbgs() << "\n"); } #endif }
bool GCOVProfiler::emitProfileArcs() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return false; bool Result = false; bool InsertIndCounterIncrCode = false; for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { DICompileUnit CU(CU_Nodes->getOperand(i)); DIArray SPs = CU.getSubprograms(); SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) { DISubprogram SP(SPs.getElement(i)); if (!SP.Verify()) continue; Function *F = SP.getFunction(); if (!F) continue; if (!Result) Result = true; unsigned Edges = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); if (isa<ReturnInst>(TI)) ++Edges; else Edges += TI->getNumSuccessors(); } ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(*Ctx), Edges); GlobalVariable *Counters = new GlobalVariable(*M, CounterTy, false, GlobalValue::InternalLinkage, Constant::getNullValue(CounterTy), "__llvm_gcov_ctr"); CountersBySP.push_back(std::make_pair(Counters, (MDNode*)SP)); UniqueVector<BasicBlock *> ComplexEdgePreds; UniqueVector<BasicBlock *> ComplexEdgeSuccs; unsigned Edge = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); if (Successors) { IRBuilder<> Builder(TI); if (Successors == 1) { Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Edge); Value *Count = Builder.CreateLoad(Counter); Count = Builder.CreateAdd(Count, ConstantInt::get(Type::getInt64Ty(*Ctx),1)); Builder.CreateStore(Count, Counter); } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { Value *Sel = Builder.CreateSelect( BI->getCondition(), ConstantInt::get(Type::getInt64Ty(*Ctx), Edge), ConstantInt::get(Type::getInt64Ty(*Ctx), Edge + 1)); SmallVector<Value *, 2> Idx; Idx.push_back(Constant::getNullValue(Type::getInt64Ty(*Ctx))); Idx.push_back(Sel); Value *Counter = Builder.CreateInBoundsGEP(Counters, Idx); Value *Count = Builder.CreateLoad(Counter); Count = Builder.CreateAdd(Count, ConstantInt::get(Type::getInt64Ty(*Ctx),1)); Builder.CreateStore(Count, Counter); } else { ComplexEdgePreds.insert(BB); for (int i = 0; i != Successors; ++i) ComplexEdgeSuccs.insert(TI->getSuccessor(i)); } Edge += Successors; } } if (!ComplexEdgePreds.empty()) { GlobalVariable *EdgeTable = buildEdgeLookupTable(F, Counters, ComplexEdgePreds, ComplexEdgeSuccs); GlobalVariable *EdgeState = getEdgeStateValue(); Type *Int32Ty = Type::getInt32Ty(*Ctx); for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { IRBuilder<> Builder(ComplexEdgePreds[i+1]->getTerminator()); Builder.CreateStore(ConstantInt::get(Int32Ty, i), EdgeState); } for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { // call runtime to perform increment BasicBlock::iterator InsertPt = ComplexEdgeSuccs[i+1]->getFirstInsertionPt(); IRBuilder<> Builder(InsertPt); Value *CounterPtrArray = Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, i * ComplexEdgePreds.size()); // Build code to increment the counter. InsertIndCounterIncrCode = true; Builder.CreateCall2(getIncrementIndirectCounterFunc(), EdgeState, CounterPtrArray); } } } insertCounterWriteout(CountersBySP); insertFlush(CountersBySP); } if (InsertIndCounterIncrCode) insertIndirectCounterIncrement(); return Result; }
/// IsFunctionMallocLike - A function is malloc-like if it returns either null /// or a pointer that doesn't alias any other pointer visible to the caller. bool FunctionAttrs::IsFunctionMallocLike(Function *F, SmallPtrSet<Function*, 8> &SCCNodes) const { UniqueVector<Value *> FlowsToReturn; for (Function::iterator I = F->begin(), E = F->end(); I != E; ++I) if (ReturnInst *Ret = dyn_cast<ReturnInst>(I->getTerminator())) FlowsToReturn.insert(Ret->getReturnValue()); for (unsigned i = 0; i != FlowsToReturn.size(); ++i) { Value *RetVal = FlowsToReturn[i+1]; // UniqueVector[0] is reserved. if (Constant *C = dyn_cast<Constant>(RetVal)) { if (!C->isNullValue() && !isa<UndefValue>(C)) return false; continue; } if (isa<Argument>(RetVal)) return false; if (Instruction *RVI = dyn_cast<Instruction>(RetVal)) switch (RVI->getOpcode()) { // Extend the analysis by looking upwards. case Instruction::BitCast: case Instruction::GetElementPtr: FlowsToReturn.insert(RVI->getOperand(0)); continue; case Instruction::Select: { SelectInst *SI = cast<SelectInst>(RVI); FlowsToReturn.insert(SI->getTrueValue()); FlowsToReturn.insert(SI->getFalseValue()); continue; } case Instruction::PHI: { PHINode *PN = cast<PHINode>(RVI); for (int i = 0, e = PN->getNumIncomingValues(); i != e; ++i) FlowsToReturn.insert(PN->getIncomingValue(i)); continue; } // Check whether the pointer came from an allocation. case Instruction::Alloca: break; case Instruction::Call: case Instruction::Invoke: { CallSite CS(RVI); if (CS.paramHasNoAliasAttr(0)) break; if (CS.getCalledFunction() && SCCNodes.count(CS.getCalledFunction())) break; } // fall-through default: return false; // Did not come from an allocation. } if (PointerMayBeCaptured(RetVal, false, /*StoreCaptures=*/false)) return false; } return true; }
bool GCOVProfiler::emitProfileArcs() { NamedMDNode *CU_Nodes = M->getNamedMetadata("llvm.dbg.cu"); if (!CU_Nodes) return false; bool Result = false; bool InsertIndCounterIncrCode = false; for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) { auto *CU = cast<DICompileUnit>(CU_Nodes->getOperand(i)); SmallVector<std::pair<GlobalVariable *, MDNode *>, 8> CountersBySP; for (auto *SP : CU->getSubprograms()) { Function *F = FnMap[SP]; if (!F) continue; if (!functionHasLines(F)) continue; if (!Result) Result = true; unsigned Edges = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); if (isa<ReturnInst>(TI)) ++Edges; else Edges += TI->getNumSuccessors(); } ArrayType *CounterTy = ArrayType::get(Type::getInt64Ty(*Ctx), Edges); GlobalVariable *Counters = new GlobalVariable(*M, CounterTy, false, GlobalValue::InternalLinkage, Constant::getNullValue(CounterTy), "__llvm_gcov_ctr"); CountersBySP.push_back(std::make_pair(Counters, SP)); UniqueVector<BasicBlock *> ComplexEdgePreds; UniqueVector<BasicBlock *> ComplexEdgeSuccs; unsigned Edge = 0; for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) { TerminatorInst *TI = BB->getTerminator(); int Successors = isa<ReturnInst>(TI) ? 1 : TI->getNumSuccessors(); if (Successors) { if (Successors == 1) { IRBuilder<> Builder(&*BB->getFirstInsertionPt()); Value *Counter = Builder.CreateConstInBoundsGEP2_64(Counters, 0, Edge); Value *Count = Builder.CreateLoad(Counter); Count = Builder.CreateAdd(Count, Builder.getInt64(1)); Builder.CreateStore(Count, Counter); } else if (BranchInst *BI = dyn_cast<BranchInst>(TI)) { IRBuilder<> Builder(BI); Value *Sel = Builder.CreateSelect(BI->getCondition(), Builder.getInt64(Edge), Builder.getInt64(Edge + 1)); SmallVector<Value *, 2> Idx; Idx.push_back(Builder.getInt64(0)); Idx.push_back(Sel); Value *Counter = Builder.CreateInBoundsGEP(Counters->getValueType(), Counters, Idx); Value *Count = Builder.CreateLoad(Counter); Count = Builder.CreateAdd(Count, Builder.getInt64(1)); Builder.CreateStore(Count, Counter); } else { ComplexEdgePreds.insert(&*BB); for (int i = 0; i != Successors; ++i) ComplexEdgeSuccs.insert(TI->getSuccessor(i)); } Edge += Successors; } } if (!ComplexEdgePreds.empty()) { GlobalVariable *EdgeTable = buildEdgeLookupTable(F, Counters, ComplexEdgePreds, ComplexEdgeSuccs); GlobalVariable *EdgeState = getEdgeStateValue(); for (int i = 0, e = ComplexEdgePreds.size(); i != e; ++i) { IRBuilder<> Builder(&*ComplexEdgePreds[i + 1]->getFirstInsertionPt()); Builder.CreateStore(Builder.getInt32(i), EdgeState); } for (int i = 0, e = ComplexEdgeSuccs.size(); i != e; ++i) { // Call runtime to perform increment. IRBuilder<> Builder(&*ComplexEdgeSuccs[i + 1]->getFirstInsertionPt()); Value *CounterPtrArray = Builder.CreateConstInBoundsGEP2_64(EdgeTable, 0, i * ComplexEdgePreds.size()); // Build code to increment the counter. InsertIndCounterIncrCode = true; Builder.CreateCall(getIncrementIndirectCounterFunc(), {EdgeState, CounterPtrArray}); } } } Function *WriteoutF = insertCounterWriteout(CountersBySP); Function *FlushF = insertFlush(CountersBySP); // Create a small bit of code that registers the "__llvm_gcov_writeout" to // be executed at exit and the "__llvm_gcov_flush" function to be executed // when "__gcov_flush" is called. FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, "__llvm_gcov_init", M); F->setUnnamedAddr(true); F->setLinkage(GlobalValue::InternalLinkage); F->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) F->addFnAttr(Attribute::NoRedZone); BasicBlock *BB = BasicBlock::Create(*Ctx, "entry", F); IRBuilder<> Builder(BB); FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); Type *Params[] = { PointerType::get(FTy, 0), PointerType::get(FTy, 0) }; FTy = FunctionType::get(Builder.getVoidTy(), Params, false); // Initialize the environment and register the local writeout and flush // functions. Constant *GCOVInit = M->getOrInsertFunction("llvm_gcov_init", FTy); Builder.CreateCall(GCOVInit, {WriteoutF, FlushF}); Builder.CreateRetVoid(); appendToGlobalCtors(*M, F, 0); } if (InsertIndCounterIncrCode) insertIndirectCounterIncrement(); return Result; }