1*06c3fb27SDimitry Andric //===-- BlockCoverageInference.h - Minimal Execution Coverage ---*- C++ -*-===// 2*06c3fb27SDimitry Andric // 3*06c3fb27SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*06c3fb27SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*06c3fb27SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*06c3fb27SDimitry Andric // 7*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 8*06c3fb27SDimitry Andric /// 9*06c3fb27SDimitry Andric /// \file 10*06c3fb27SDimitry Andric /// This file finds the minimum set of blocks on a CFG that must be instrumented 11*06c3fb27SDimitry Andric /// to infer execution coverage for the whole graph. 12*06c3fb27SDimitry Andric /// 13*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 14*06c3fb27SDimitry Andric 15*06c3fb27SDimitry Andric #ifndef LLVM_TRANSFORMS_INSTRUMENTATION_BLOCKCOVERAGEINFERENCE_H 16*06c3fb27SDimitry Andric #define LLVM_TRANSFORMS_INSTRUMENTATION_BLOCKCOVERAGEINFERENCE_H 17*06c3fb27SDimitry Andric 18*06c3fb27SDimitry Andric #include "llvm/ADT/ArrayRef.h" 19*06c3fb27SDimitry Andric #include "llvm/ADT/DenseMap.h" 20*06c3fb27SDimitry Andric #include "llvm/ADT/SetVector.h" 21*06c3fb27SDimitry Andric #include "llvm/Support/raw_ostream.h" 22*06c3fb27SDimitry Andric 23*06c3fb27SDimitry Andric namespace llvm { 24*06c3fb27SDimitry Andric 25*06c3fb27SDimitry Andric class Function; 26*06c3fb27SDimitry Andric class BasicBlock; 27*06c3fb27SDimitry Andric class DotFuncBCIInfo; 28*06c3fb27SDimitry Andric 29*06c3fb27SDimitry Andric class BlockCoverageInference { 30*06c3fb27SDimitry Andric friend class DotFuncBCIInfo; 31*06c3fb27SDimitry Andric 32*06c3fb27SDimitry Andric public: 33*06c3fb27SDimitry Andric using BlockSet = SmallSetVector<const BasicBlock *, 4>; 34*06c3fb27SDimitry Andric 35*06c3fb27SDimitry Andric BlockCoverageInference(const Function &F, bool ForceInstrumentEntry); 36*06c3fb27SDimitry Andric 37*06c3fb27SDimitry Andric /// \return true if \p BB should be instrumented for coverage. 38*06c3fb27SDimitry Andric bool shouldInstrumentBlock(const BasicBlock &BB) const; 39*06c3fb27SDimitry Andric 40*06c3fb27SDimitry Andric /// \return the set of blocks \p Deps such that \p BB is covered iff any 41*06c3fb27SDimitry Andric /// blocks in \p Deps are covered. 42*06c3fb27SDimitry Andric BlockSet getDependencies(const BasicBlock &BB) const; 43*06c3fb27SDimitry Andric 44*06c3fb27SDimitry Andric /// \return a hash that depends on the set of instrumented blocks. 45*06c3fb27SDimitry Andric uint64_t getInstrumentedBlocksHash() const; 46*06c3fb27SDimitry Andric 47*06c3fb27SDimitry Andric /// Dump the inference graph. 48*06c3fb27SDimitry Andric void dump(raw_ostream &OS) const; 49*06c3fb27SDimitry Andric 50*06c3fb27SDimitry Andric /// View the inferred block coverage as a dot file. 51*06c3fb27SDimitry Andric /// Filled gray blocks are instrumented, red outlined blocks are found to be 52*06c3fb27SDimitry Andric /// covered, red edges show that a block's coverage can be inferred from its 53*06c3fb27SDimitry Andric /// successors, and blue edges show that a block's coverage can be inferred 54*06c3fb27SDimitry Andric /// from its predecessors. 55*06c3fb27SDimitry Andric void viewBlockCoverageGraph( 56*06c3fb27SDimitry Andric const DenseMap<const BasicBlock *, bool> *Coverage = nullptr) const; 57*06c3fb27SDimitry Andric 58*06c3fb27SDimitry Andric private: 59*06c3fb27SDimitry Andric const Function &F; 60*06c3fb27SDimitry Andric bool ForceInstrumentEntry; 61*06c3fb27SDimitry Andric 62*06c3fb27SDimitry Andric /// Maps blocks to a minimal list of predecessors that can be used to infer 63*06c3fb27SDimitry Andric /// this block's coverage. 64*06c3fb27SDimitry Andric DenseMap<const BasicBlock *, BlockSet> PredecessorDependencies; 65*06c3fb27SDimitry Andric 66*06c3fb27SDimitry Andric /// Maps blocks to a minimal list of successors that can be used to infer 67*06c3fb27SDimitry Andric /// this block's coverage. 68*06c3fb27SDimitry Andric DenseMap<const BasicBlock *, BlockSet> SuccessorDependencies; 69*06c3fb27SDimitry Andric 70*06c3fb27SDimitry Andric /// Compute \p PredecessorDependencies and \p SuccessorDependencies. 71*06c3fb27SDimitry Andric void findDependencies(); 72*06c3fb27SDimitry Andric 73*06c3fb27SDimitry Andric /// Find the set of basic blocks that are reachable from \p Start without the 74*06c3fb27SDimitry Andric /// basic block \p Avoid. 75*06c3fb27SDimitry Andric void getReachableAvoiding(const BasicBlock &Start, const BasicBlock &Avoid, 76*06c3fb27SDimitry Andric bool IsForward, BlockSet &Reachable) const; 77*06c3fb27SDimitry Andric 78*06c3fb27SDimitry Andric static std::string getBlockNames(ArrayRef<const BasicBlock *> BBs); getBlockNames(BlockSet BBs)79*06c3fb27SDimitry Andric static std::string getBlockNames(BlockSet BBs) { 80*06c3fb27SDimitry Andric return getBlockNames(ArrayRef<const BasicBlock *>(BBs.begin(), BBs.end())); 81*06c3fb27SDimitry Andric } 82*06c3fb27SDimitry Andric }; 83*06c3fb27SDimitry Andric 84*06c3fb27SDimitry Andric } // end namespace llvm 85*06c3fb27SDimitry Andric 86*06c3fb27SDimitry Andric #endif // LLVM_TRANSFORMS_INSTRUMENTATION_BLOCKCOVERAGEINFERENCE_H 87