003 File Manager
Current Path:
/usr/src/contrib/llvm-project/llvm/lib/Analysis
usr
/
src
/
contrib
/
llvm-project
/
llvm
/
lib
/
Analysis
/
📁
..
📄
AliasAnalysis.cpp
(33.55 KB)
📄
AliasAnalysisEvaluator.cpp
(15.64 KB)
📄
AliasAnalysisSummary.cpp
(3.49 KB)
📄
AliasAnalysisSummary.h
(10.17 KB)
📄
AliasSetTracker.cpp
(25.86 KB)
📄
Analysis.cpp
(5.29 KB)
📄
AssumeBundleQueries.cpp
(7.96 KB)
📄
AssumptionCache.cpp
(10.94 KB)
📄
BasicAliasAnalysis.cpp
(85.81 KB)
📄
BlockFrequencyInfo.cpp
(12.39 KB)
📄
BlockFrequencyInfoImpl.cpp
(28.6 KB)
📄
BranchProbabilityInfo.cpp
(43.48 KB)
📄
CFG.cpp
(9.9 KB)
📄
CFGPrinter.cpp
(11.2 KB)
📄
CFLAndersAliasAnalysis.cpp
(33.01 KB)
📄
CFLGraph.h
(21.23 KB)
📄
CFLSteensAliasAnalysis.cpp
(13.24 KB)
📄
CGSCCPassManager.cpp
(31.2 KB)
📄
CallGraph.cpp
(12.86 KB)
📄
CallGraphSCCPass.cpp
(26.31 KB)
📄
CallPrinter.cpp
(9.48 KB)
📄
CaptureTracking.cpp
(15.38 KB)
📄
CmpInstAnalysis.cpp
(4.63 KB)
📄
CodeMetrics.cpp
(6.99 KB)
📄
ConstantFolding.cpp
(105.15 KB)
📄
CostModel.cpp
(3.87 KB)
📄
DDG.cpp
(11.29 KB)
📄
Delinearization.cpp
(4.49 KB)
📄
DemandedBits.cpp
(16.27 KB)
📄
DependenceAnalysis.cpp
(150.78 KB)
📄
DependenceGraphBuilder.cpp
(19.24 KB)
📄
DivergenceAnalysis.cpp
(15.59 KB)
📄
DomPrinter.cpp
(9.67 KB)
📄
DomTreeUpdater.cpp
(15.21 KB)
📄
DominanceFrontier.cpp
(3.2 KB)
📄
EHPersonalities.cpp
(5.89 KB)
📄
GlobalsModRef.cpp
(41 KB)
📄
GuardUtils.cpp
(3.27 KB)
📄
HeatUtils.cpp
(2.85 KB)
📄
IVDescriptors.cpp
(42.28 KB)
📄
IVUsers.cpp
(16.12 KB)
📄
IndirectCallPromotionAnalysis.cpp
(4.33 KB)
📄
InlineAdvisor.cpp
(15.28 KB)
📄
InlineCost.cpp
(99.47 KB)
📄
InlineFeaturesAnalysis.cpp
(1.59 KB)
📄
InlineSizeEstimatorAnalysis.cpp
(10.95 KB)
📄
InstCount.cpp
(2.45 KB)
📄
InstructionPrecedenceTracking.cpp
(4.8 KB)
📄
InstructionSimplify.cpp
(216.91 KB)
📄
Interval.cpp
(1.78 KB)
📄
IntervalPartition.cpp
(4.5 KB)
📄
LazyBlockFrequencyInfo.cpp
(2.81 KB)
📄
LazyBranchProbabilityInfo.cpp
(2.96 KB)
📄
LazyCallGraph.cpp
(67.33 KB)
📄
LazyValueInfo.cpp
(76.38 KB)
📄
LegacyDivergenceAnalysis.cpp
(14.82 KB)
📄
Lint.cpp
(29.07 KB)
📄
Loads.cpp
(20.6 KB)
📄
LoopAccessAnalysis.cpp
(88.02 KB)
📄
LoopAnalysisManager.cpp
(6.6 KB)
📄
LoopCacheAnalysis.cpp
(23.53 KB)
📄
LoopInfo.cpp
(37.15 KB)
📄
LoopNestAnalysis.cpp
(10.62 KB)
📄
LoopPass.cpp
(12.89 KB)
📄
LoopUnrollAnalyzer.cpp
(7.26 KB)
📄
MLInlineAdvisor.cpp
(11.36 KB)
📄
MemDepPrinter.cpp
(5.13 KB)
📄
MemDerefPrinter.cpp
(2.53 KB)
📄
MemoryBuiltins.cpp
(41.14 KB)
📄
MemoryDependenceAnalysis.cpp
(69.89 KB)
📄
MemoryLocation.cpp
(7.92 KB)
📄
MemorySSA.cpp
(90.16 KB)
📄
MemorySSAUpdater.cpp
(57.9 KB)
📄
ModuleDebugInfoPrinter.cpp
(4.02 KB)
📄
ModuleSummaryAnalysis.cpp
(38.13 KB)
📄
MustExecute.cpp
(31.18 KB)
📄
ObjCARCAliasAnalysis.cpp
(5.81 KB)
📄
ObjCARCAnalysisUtils.cpp
(1.07 KB)
📄
ObjCARCInstKind.cpp
(23.15 KB)
📄
OptimizationRemarkEmitter.cpp
(4.23 KB)
📄
PHITransAddr.cpp
(16.05 KB)
📄
PhiValues.cpp
(8.4 KB)
📄
PostDominators.cpp
(3.59 KB)
📄
ProfileSummaryInfo.cpp
(18.07 KB)
📄
PtrUseVisitor.cpp
(1.28 KB)
📄
RegionInfo.cpp
(6.5 KB)
📄
RegionPass.cpp
(9.23 KB)
📄
RegionPrinter.cpp
(8.61 KB)
📄
ReleaseModeModelRunner.cpp
(2.83 KB)
📄
ScalarEvolution.cpp
(475.26 KB)
📄
ScalarEvolutionAliasAnalysis.cpp
(5.96 KB)
📄
ScalarEvolutionDivision.cpp
(7.51 KB)
📄
ScalarEvolutionNormalization.cpp
(4.59 KB)
📄
ScopedNoAliasAA.cpp
(7.38 KB)
📄
StackLifetime.cpp
(12.22 KB)
📄
StackSafetyAnalysis.cpp
(31.81 KB)
📄
StratifiedSets.h
(18.67 KB)
📄
SyncDependenceAnalysis.cpp
(12.97 KB)
📄
SyntheticCountsUtils.cpp
(3.81 KB)
📄
TFUtils.cpp
(8.99 KB)
📄
TargetLibraryInfo.cpp
(58.98 KB)
📄
TargetTransformInfo.cpp
(48.15 KB)
📄
Trace.cpp
(1.8 KB)
📄
TypeBasedAliasAnalysis.cpp
(26.04 KB)
📄
TypeMetadataUtils.cpp
(5.93 KB)
📄
VFABIDemangling.cpp
(16.46 KB)
📄
ValueLattice.cpp
(1.19 KB)
📄
ValueLatticeUtils.cpp
(1.53 KB)
📄
ValueTracking.cpp
(243.08 KB)
📄
VectorUtils.cpp
(48.57 KB)
📁
models
Editing: SyncDependenceAnalysis.cpp
//===- SyncDependenceAnalysis.cpp - Divergent Branch Dependence Calculation //--===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements an algorithm that returns for a divergent branch // the set of basic blocks whose phi nodes become divergent due to divergent // control. These are the blocks that are reachable by two disjoint paths from // the branch or loop exits that have a reaching path that is disjoint from a // path to the loop latch. // // The SyncDependenceAnalysis is used in the DivergenceAnalysis to model // control-induced divergence in phi nodes. // // -- Summary -- // The SyncDependenceAnalysis lazily computes sync dependences [3]. // The analysis evaluates the disjoint path criterion [2] by a reduction // to SSA construction. The SSA construction algorithm is implemented as // a simple data-flow analysis [1]. // // [1] "A Simple, Fast Dominance Algorithm", SPI '01, Cooper, Harvey and Kennedy // [2] "Efficiently Computing Static Single Assignment Form // and the Control Dependence Graph", TOPLAS '91, // Cytron, Ferrante, Rosen, Wegman and Zadeck // [3] "Improving Performance of OpenCL on CPUs", CC '12, Karrenberg and Hack // [4] "Divergence Analysis", TOPLAS '13, Sampaio, Souza, Collange and Pereira // // -- Sync dependence -- // Sync dependence [4] characterizes the control flow aspect of the // propagation of branch divergence. For example, // // %cond = icmp slt i32 %tid, 10 // br i1 %cond, label %then, label %else // then: // br label %merge // else: // br label %merge // merge: // %a = phi i32 [ 0, %then ], [ 1, %else ] // // Suppose %tid holds the thread ID. Although %a is not data dependent on %tid // because %tid is not on its use-def chains, %a is sync dependent on %tid // because the branch "br i1 %cond" depends on %tid and affects which value %a // is assigned to. // // -- Reduction to SSA construction -- // There are two disjoint paths from A to X, if a certain variant of SSA // construction places a phi node in X under the following set-up scheme [2]. // // This variant of SSA construction ignores incoming undef values. // That is paths from the entry without a definition do not result in // phi nodes. // // entry // / \ // A \ // / \ Y // B C / // \ / \ / // D E // \ / // F // Assume that A contains a divergent branch. We are interested // in the set of all blocks where each block is reachable from A // via two disjoint paths. This would be the set {D, F} in this // case. // To generally reduce this query to SSA construction we introduce // a virtual variable x and assign to x different values in each // successor block of A. // entry // / \ // A \ // / \ Y // x = 0 x = 1 / // \ / \ / // D E // \ / // F // Our flavor of SSA construction for x will construct the following // entry // / \ // A \ // / \ Y // x0 = 0 x1 = 1 / // \ / \ / // x2=phi E // \ / // x3=phi // The blocks D and F contain phi nodes and are thus each reachable // by two disjoins paths from A. // // -- Remarks -- // In case of loop exits we need to check the disjoint path criterion for loops // [2]. To this end, we check whether the definition of x differs between the // loop exit and the loop header (_after_ SSA construction). // //===----------------------------------------------------------------------===// #include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/PostDominators.h" #include "llvm/Analysis/SyncDependenceAnalysis.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include <stack> #include <unordered_set> #define DEBUG_TYPE "sync-dependence" namespace llvm { ConstBlockSet SyncDependenceAnalysis::EmptyBlockSet; SyncDependenceAnalysis::SyncDependenceAnalysis(const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI) : FuncRPOT(DT.getRoot()->getParent()), DT(DT), PDT(PDT), LI(LI) {} SyncDependenceAnalysis::~SyncDependenceAnalysis() {} using FunctionRPOT = ReversePostOrderTraversal<const Function *>; // divergence propagator for reducible CFGs struct DivergencePropagator { const FunctionRPOT &FuncRPOT; const DominatorTree &DT; const PostDominatorTree &PDT; const LoopInfo &LI; // identified join points std::unique_ptr<ConstBlockSet> JoinBlocks; // reached loop exits (by a path disjoint to a path to the loop header) SmallPtrSet<const BasicBlock *, 4> ReachedLoopExits; // if DefMap[B] == C then C is the dominating definition at block B // if DefMap[B] ~ undef then we haven't seen B yet // if DefMap[B] == B then B is a join point of disjoint paths from X or B is // an immediate successor of X (initial value). using DefiningBlockMap = std::map<const BasicBlock *, const BasicBlock *>; DefiningBlockMap DefMap; // all blocks with pending visits std::unordered_set<const BasicBlock *> PendingUpdates; DivergencePropagator(const FunctionRPOT &FuncRPOT, const DominatorTree &DT, const PostDominatorTree &PDT, const LoopInfo &LI) : FuncRPOT(FuncRPOT), DT(DT), PDT(PDT), LI(LI), JoinBlocks(new ConstBlockSet) {} // set the definition at @block and mark @block as pending for a visit void addPending(const BasicBlock &Block, const BasicBlock &DefBlock) { bool WasAdded = DefMap.emplace(&Block, &DefBlock).second; if (WasAdded) PendingUpdates.insert(&Block); } void printDefs(raw_ostream &Out) { Out << "Propagator::DefMap {\n"; for (const auto *Block : FuncRPOT) { auto It = DefMap.find(Block); Out << Block->getName() << " : "; if (It == DefMap.end()) { Out << "\n"; } else { const auto *DefBlock = It->second; Out << (DefBlock ? DefBlock->getName() : "<null>") << "\n"; } } Out << "}\n"; } // process @succBlock with reaching definition @defBlock // the original divergent branch was in @parentLoop (if any) void visitSuccessor(const BasicBlock &SuccBlock, const Loop *ParentLoop, const BasicBlock &DefBlock) { // @succBlock is a loop exit if (ParentLoop && !ParentLoop->contains(&SuccBlock)) { DefMap.emplace(&SuccBlock, &DefBlock); ReachedLoopExits.insert(&SuccBlock); return; } // first reaching def? auto ItLastDef = DefMap.find(&SuccBlock); if (ItLastDef == DefMap.end()) { addPending(SuccBlock, DefBlock); return; } // a join of at least two definitions if (ItLastDef->second != &DefBlock) { // do we know this join already? if (!JoinBlocks->insert(&SuccBlock).second) return; // update the definition addPending(SuccBlock, SuccBlock); } } // find all blocks reachable by two disjoint paths from @rootTerm. // This method works for both divergent terminators and loops with // divergent exits. // @rootBlock is either the block containing the branch or the header of the // divergent loop. // @nodeSuccessors is the set of successors of the node (Loop or Terminator) // headed by @rootBlock. // @parentLoop is the parent loop of the Loop or the loop that contains the // Terminator. template <typename SuccessorIterable> std::unique_ptr<ConstBlockSet> computeJoinPoints(const BasicBlock &RootBlock, SuccessorIterable NodeSuccessors, const Loop *ParentLoop) { assert(JoinBlocks); LLVM_DEBUG(dbgs() << "SDA:computeJoinPoints. Parent loop: " << (ParentLoop ? ParentLoop->getName() : "<null>") << "\n" ); // bootstrap with branch targets for (const auto *SuccBlock : NodeSuccessors) { DefMap.emplace(SuccBlock, SuccBlock); if (ParentLoop && !ParentLoop->contains(SuccBlock)) { // immediate loop exit from node. ReachedLoopExits.insert(SuccBlock); } else { // regular successor PendingUpdates.insert(SuccBlock); } } LLVM_DEBUG( dbgs() << "SDA: rpo order:\n"; for (const auto * RpoBlock : FuncRPOT) { dbgs() << "- " << RpoBlock->getName() << "\n"; } ); auto ItBeginRPO = FuncRPOT.begin(); auto ItEndRPO = FuncRPOT.end(); // skip until term (TODO RPOT won't let us start at @term directly) for (; *ItBeginRPO != &RootBlock; ++ItBeginRPO) { assert(ItBeginRPO != ItEndRPO && "Unable to find RootBlock"); } // propagate definitions at the immediate successors of the node in RPO auto ItBlockRPO = ItBeginRPO; while ((++ItBlockRPO != ItEndRPO) && !PendingUpdates.empty()) { const auto *Block = *ItBlockRPO; LLVM_DEBUG(dbgs() << "SDA::joins. visiting " << Block->getName() << "\n"); // skip Block if not pending update auto ItPending = PendingUpdates.find(Block); if (ItPending == PendingUpdates.end()) continue; PendingUpdates.erase(ItPending); // propagate definition at Block to its successors auto ItDef = DefMap.find(Block); const auto *DefBlock = ItDef->second; assert(DefBlock); auto *BlockLoop = LI.getLoopFor(Block); if (ParentLoop && (ParentLoop != BlockLoop && ParentLoop->contains(BlockLoop))) { // if the successor is the header of a nested loop pretend its a // single node with the loop's exits as successors SmallVector<BasicBlock *, 4> BlockLoopExits; BlockLoop->getExitBlocks(BlockLoopExits); for (const auto *BlockLoopExit : BlockLoopExits) { visitSuccessor(*BlockLoopExit, ParentLoop, *DefBlock); } } else { // the successors are either on the same loop level or loop exits for (const auto *SuccBlock : successors(Block)) { visitSuccessor(*SuccBlock, ParentLoop, *DefBlock); } } } LLVM_DEBUG(dbgs() << "SDA::joins. After propagation:\n"; printDefs(dbgs())); // We need to know the definition at the parent loop header to decide // whether the definition at the header is different from the definition at // the loop exits, which would indicate a divergent loop exits. // // A // loop header // | // B // nested loop header // | // C -> X (exit from B loop) -..-> (A latch) // | // D -> back to B (B latch) // | // proper exit from both loops // // analyze reached loop exits if (!ReachedLoopExits.empty()) { const BasicBlock *ParentLoopHeader = ParentLoop ? ParentLoop->getHeader() : nullptr; assert(ParentLoop); auto ItHeaderDef = DefMap.find(ParentLoopHeader); const auto *HeaderDefBlock = (ItHeaderDef == DefMap.end()) ? nullptr : ItHeaderDef->second; LLVM_DEBUG(printDefs(dbgs())); assert(HeaderDefBlock && "no definition at header of carrying loop"); for (const auto *ExitBlock : ReachedLoopExits) { auto ItExitDef = DefMap.find(ExitBlock); assert((ItExitDef != DefMap.end()) && "no reaching def at reachable loop exit"); if (ItExitDef->second != HeaderDefBlock) { JoinBlocks->insert(ExitBlock); } } } return std::move(JoinBlocks); } }; const ConstBlockSet &SyncDependenceAnalysis::join_blocks(const Loop &Loop) { using LoopExitVec = SmallVector<BasicBlock *, 4>; LoopExitVec LoopExits; Loop.getExitBlocks(LoopExits); if (LoopExits.size() < 1) { return EmptyBlockSet; } // already available in cache? auto ItCached = CachedLoopExitJoins.find(&Loop); if (ItCached != CachedLoopExitJoins.end()) { return *ItCached->second; } // compute all join points DivergencePropagator Propagator{FuncRPOT, DT, PDT, LI}; auto JoinBlocks = Propagator.computeJoinPoints<const LoopExitVec &>( *Loop.getHeader(), LoopExits, Loop.getParentLoop()); auto ItInserted = CachedLoopExitJoins.emplace(&Loop, std::move(JoinBlocks)); assert(ItInserted.second); return *ItInserted.first->second; } const ConstBlockSet & SyncDependenceAnalysis::join_blocks(const Instruction &Term) { // trivial case if (Term.getNumSuccessors() < 1) { return EmptyBlockSet; } // already available in cache? auto ItCached = CachedBranchJoins.find(&Term); if (ItCached != CachedBranchJoins.end()) return *ItCached->second; // compute all join points DivergencePropagator Propagator{FuncRPOT, DT, PDT, LI}; const auto &TermBlock = *Term.getParent(); auto JoinBlocks = Propagator.computeJoinPoints<const_succ_range>( TermBlock, successors(Term.getParent()), LI.getLoopFor(&TermBlock)); auto ItInserted = CachedBranchJoins.emplace(&Term, std::move(JoinBlocks)); assert(ItInserted.second); return *ItInserted.first->second; } } // namespace llvm
Upload File
Create Folder