diff --git a/llvm/include/llvm/Analysis/DDG.h b/llvm/include/llvm/Analysis/DDG.h --- a/llvm/include/llvm/Analysis/DDG.h +++ b/llvm/include/llvm/Analysis/DDG.h @@ -104,6 +104,7 @@ /// Subclass of DDGNode representing single or multi-instruction nodes. class SimpleDDGNode : public DDGNode { + friend class DDGBuilder; public: SimpleDDGNode() = delete; SimpleDDGNode(Instruction &I); @@ -388,6 +389,12 @@ return PiNode->getNodes(); } + /// Return true if the two nodes \pSrc and \pTgt are both simple nodes and + /// the consecutive instructions after merging belong to the same basic block. + bool areNodesMergeable(const DDGNode &Src, + const DDGNode &Tgt) const final override; + void mergeNodes(DDGNode &Src, DDGNode &Tgt) final override; + bool shouldSimplify() const final override; bool shouldCreatePiBlocks() const final override; }; diff --git a/llvm/include/llvm/Analysis/DependenceGraphBuilder.h b/llvm/include/llvm/Analysis/DependenceGraphBuilder.h --- a/llvm/include/llvm/Analysis/DependenceGraphBuilder.h +++ b/llvm/include/llvm/Analysis/DependenceGraphBuilder.h @@ -58,6 +58,7 @@ createFineGrainedNodes(); createDefUseEdges(); createMemoryDependencyEdges(); + simplify(); createAndConnectRootNode(); createPiBlocks(); sortNodesTopologically(); @@ -92,6 +93,15 @@ /// the dependence graph into an acyclic graph. void createPiBlocks(); + /// Go through all the nodes in the graph and collapse any two nodes + /// 'a' and 'b' if all of the following are true: + /// - the only edge from 'a' is a def-use edge to 'b' and + /// - the only edge to 'b' is a def-use edge from 'a' and + /// - there is no cyclic edge from 'b' to 'a' and + /// - all instructions in 'a' and 'b' belong to the same basic block and + /// - both 'a' and 'b' are simple (single or multi instruction) nodes. + void simplify(); + /// Topologically sort the graph nodes. void sortNodesTopologically(); @@ -129,6 +139,17 @@ /// and false otherwise. virtual bool shouldCreatePiBlocks() const { return true; } + /// Return true if graph simplification step is requested, and false + /// otherwise. + virtual bool shouldSimplify() const { return true; } + + /// Return true if it's safe to merge the two nodes. + virtual bool areNodesMergeable(const NodeType &A, const NodeType &B) const = 0; + + /// Append the content of node \p B into node \p A and remove \p B and + /// the edge between \p A and \p B from the graph. + virtual void mergeNodes(NodeType &A, NodeType &B) = 0; + /// Given an instruction \p I return its associated ordinal number. size_t getOrdinal(Instruction &I) { assert(InstOrdinalMap.find(&I) != InstOrdinalMap.end() && diff --git a/llvm/lib/Analysis/DDG.cpp b/llvm/lib/Analysis/DDG.cpp --- a/llvm/lib/Analysis/DDG.cpp +++ b/llvm/lib/Analysis/DDG.cpp @@ -16,6 +16,11 @@ using namespace llvm; +static cl::opt SimplifyDDG( + "ddg-simplify", cl::init(true), cl::Hidden, cl::ZeroOrMore, + cl::desc( + "Simplify DDG by merging nodes that have less interesting edges.")); + static cl::opt CreatePiBlocks("ddg-pi-blocks", cl::init(true), cl::Hidden, cl::ZeroOrMore, cl::desc("Create pi-block nodes.")); @@ -257,6 +262,47 @@ return OS; } +//===--------------------------------------------------------------------===// +// DDGBuilder implementation +//===--------------------------------------------------------------------===// + +bool DDGBuilder::areNodesMergeable(const DDGNode &Src, + const DDGNode &Tgt) const { + // Only merge two nodes if they are both simple nodes and the consecutive + // instructions after merging belong to the same BB. + auto *SimpleSrc = dyn_cast(&Src); + auto *SimpleTgt = dyn_cast(&Tgt); + if (!SimpleSrc || !SimpleTgt) + return false; + + return SimpleSrc->getLastInstruction()->getParent() == + SimpleTgt->getFirstInstruction()->getParent(); +} + +void DDGBuilder::mergeNodes(DDGNode &A, DDGNode &B) { + DDGEdge &EdgeToFold = A.back(); + assert(A.getEdges().size() == 1 && EdgeToFold.getTargetNode() == B && + "Expected A to have a single edge to B."); + assert(isa(&A) && isa(&B) && + "Expected simple nodes"); + + // Copy instructions from B to the end of A. + cast(&A)->appendInstructions(*cast(&B)); + + // Move to A any outgoing edges from B. + for (DDGEdge *BE : B) + Graph.connect(A, BE->getTargetNode(), *BE); + + A.removeEdge(EdgeToFold); + destroyEdge(EdgeToFold); + Graph.removeNode(B); + destroyNode(B); +} + +bool DDGBuilder::shouldSimplify() const { + return SimplifyDDG; +} + bool DDGBuilder::shouldCreatePiBlocks() const { return CreatePiBlocks; } diff --git a/llvm/lib/Analysis/DependenceGraphBuilder.cpp b/llvm/lib/Analysis/DependenceGraphBuilder.cpp --- a/llvm/lib/Analysis/DependenceGraphBuilder.cpp +++ b/llvm/lib/Analysis/DependenceGraphBuilder.cpp @@ -374,6 +374,111 @@ } } +template void AbstractDependenceGraphBuilder::simplify() { + if (!shouldSimplify()) + return; + LLVM_DEBUG(dbgs() << "==== Start of Graph Simplification ===\n"); + + // This algorithm works by first collecting a set of candidate nodes that have + // an out-degree of one (in terms of def-use edges), and then ignoring those + // whose targets have an in-degree more than one. Each node in the resulting + // set can then be merged with its corresponding target and put back into the + // worklist until no further merge candidates are available. + SmallPtrSet CandidateSourceNodes; + + // A mapping between nodes and their in-degree. To save space, this map + // only contains nodes that are targets of nodes in the CandidateSourceNodes. + DenseMap TargetInDegreeMap; + + for (NodeType *N : Graph) { + if (N->getEdges().size() != 1) + continue; + EdgeType &Edge = N->back(); + if (!Edge.isDefUse()) + continue; + CandidateSourceNodes.insert(N); + + // Insert an element into the in-degree map and initialize to zero. The + // count will get updated in the next step. + TargetInDegreeMap.insert({&Edge.getTargetNode(), 0}); + } + + LLVM_DEBUG({ + dbgs() << "Size of candidate src node list:" << CandidateSourceNodes.size() + << "\nNode with single outgoing def-use edge:\n"; + for (NodeType *N : CandidateSourceNodes) { + dbgs() << N << "\n"; + } + }); + + for (NodeType *N : Graph) { + for (EdgeType *E : *N) { + NodeType *Tgt = &E->getTargetNode(); + auto TgtIT = TargetInDegreeMap.find(Tgt); + if (TgtIT != TargetInDegreeMap.end()) + ++(TgtIT->second); + } + } + + LLVM_DEBUG({ + dbgs() << "Size of target in-degree map:" << TargetInDegreeMap.size() + << "\nContent of in-degree map:\n"; + for (auto &I : TargetInDegreeMap) { + dbgs() << I.first << " --> " << I.second << "\n"; + } + }); + + SmallVector Worklist(CandidateSourceNodes.begin(), + CandidateSourceNodes.end()); + while (!Worklist.empty()) { + NodeType &Src = *Worklist.pop_back_val(); + // As nodes get merged, we need to skip any node that has been removed from + // the candidate set (see below). + if (CandidateSourceNodes.find(&Src) == CandidateSourceNodes.end()) + continue; + CandidateSourceNodes.erase(&Src); + + assert(Src.getEdges().size() == 1 && + "Expected a single edge from the candidate src node."); + NodeType &Tgt = Src.back().getTargetNode(); + assert(TargetInDegreeMap.find(&Tgt) != TargetInDegreeMap.end() && + "Expected target to be in the in-degree map."); + + if (TargetInDegreeMap[&Tgt] != 1) + continue; + + if (!areNodesMergeable(Src, Tgt)) + continue; + + // Do not merge if there is also an edge from target to src (immediate + // cycle). + if (Tgt.hasEdgeTo(Src)) + continue; + + LLVM_DEBUG(dbgs() << "Merging:" << Src << "\nWith:" << Tgt << "\n"); + + mergeNodes(Src, Tgt); + + // If the target node is in the candidate set itself, we need to put the + // src node back into the worklist again so it gives the target a chance + // to get merged into it. For example if we have: + // {(a)->(b), (b)->(c), (c)->(d), ...} and the worklist is initially {b, a}, + // then after merging (a) and (b) together, we need to put (a,b) back in + // the worklist so that (c) can get merged in as well resulting in + // {(a,b,c) -> d} + // We also need to remove the old target (b), from the worklist. We first + // remove it from the candidate set here, and skip any item from the + // worklist that is not in the set. + if (CandidateSourceNodes.find(&Tgt) != CandidateSourceNodes.end()) { + Worklist.push_back(&Src); + CandidateSourceNodes.insert(&Src); + CandidateSourceNodes.erase(&Tgt); + LLVM_DEBUG(dbgs() << "Putting " << &Src << " back in the worklist.\n"); + } + } + LLVM_DEBUG(dbgs() << "=== End of Graph Simplification ===\n"); +} + template void AbstractDependenceGraphBuilder::sortNodesTopologically() { diff --git a/llvm/test/Analysis/DDG/basic-a.ll b/llvm/test/Analysis/DDG/basic-a.ll --- a/llvm/test/Analysis/DDG/basic-a.ll +++ b/llvm/test/Analysis/DDG/basic-a.ll @@ -21,14 +21,9 @@ ; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]] -; CHECK: Node Address:[[N5]]:single-instruction +; CHECK: Node Address:[[N5]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %exitcond = icmp ne i64 %inc, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N6]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %exitcond, label %test1.for.body, label %for.end.loopexit ; CHECK-NEXT: Edges:none! @@ -36,33 +31,28 @@ ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx1 = getelementptr inbounds float, float* %a, i64 %i.02 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]] -; CHECK: Node Address:[[N3]]:single-instruction +; CHECK: Node Address:[[N3]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N8]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] -; CHECK: Node Address:[[N10:0x[0-9a-f]*]]:single-instruction +; CHECK: Node Address:[[N8:0x[0-9a-f]*]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %conv = uitofp i64 %n to float ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9]] +; CHECK-NEXT: [def-use] to [[N7]] -; CHECK: Node Address:[[N9]]:single-instruction +; CHECK: Node Address:[[N7]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %add = fadd float %0, %conv ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N7]] +; CHECK-NEXT: [def-use] to [[N6]] -; CHECK: Node Address:[[N7]]:single-instruction +; CHECK: Node Address:[[N6]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: store float %add, float* %arrayidx1, align 4 ; CHECK-NEXT: Edges:none! @@ -118,14 +108,9 @@ ; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]] -; CHECK: Node Address:[[N6]]:single-instruction +; CHECK: Node Address:[[N6]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %exitcond = icmp ne i64 %inc, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N7]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %exitcond, label %test2.for.body, label %for.end.loopexit ; CHECK-NEXT: Edges:none! @@ -133,40 +118,30 @@ ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %i.02 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] -; CHECK: Node Address:[[N4]]:single-instruction +; CHECK: Node Address:[[N4]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx1 = getelementptr inbounds float, float* %a, i64 %i.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N9]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %1 = load float, float* %arrayidx1, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N20:0x[0-9a-f]*]] -; CHECK-NEXT: [memory] to [[N8]] +; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] +; CHECK-NEXT: [memory] to [[N7]] -; CHECK: Node Address:[[N3]]:single-instruction +; CHECK: Node Address:[[N3]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N10]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N20]] +; CHECK-NEXT: [def-use] to [[N8]] -; CHECK: Node Address:[[N20]]:single-instruction +; CHECK: Node Address:[[N8]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %add = fadd float %0, %1 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N8]] +; CHECK-NEXT: [def-use] to [[N7]] -; CHECK: Node Address:[[N8]]:single-instruction +; CHECK: Node Address:[[N7]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: store float %add, float* %arrayidx2, align 4 ; CHECK-NEXT: Edges:none! diff --git a/llvm/test/Analysis/DDG/basic-b.ll b/llvm/test/Analysis/DDG/basic-b.ll --- a/llvm/test/Analysis/DDG/basic-b.ll +++ b/llvm/test/Analysis/DDG/basic-b.ll @@ -22,14 +22,9 @@ ; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] -; CHECK: Node Address:[[N7]]:single-instruction +; CHECK: Node Address:[[N7]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp = icmp ult i64 %inc, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N8]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp, label %test1.for.body, label %for.end.loopexit ; CHECK-NEXT: Edges:none! @@ -37,51 +32,41 @@ ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, float* %a, i64 %i.02 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] -; CHECK: Node Address:[[N5]]:single-instruction +; CHECK: Node Address:[[N5]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %sub1 = add i64 %i.02, -1 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N10]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %sub1 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9]] +; CHECK-NEXT: [def-use] to [[N8]] -; CHECK: Node Address:[[N4]]:single-instruction +; CHECK: Node Address:[[N4]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N11]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9]] +; CHECK-NEXT: [def-use] to [[N8]] -; CHECK: Node Address:[[N9]]:pi-block +; CHECK: Node Address:[[N8]]:pi-block ; CHECK-NEXT: --- start of nodes in pi-block --- -; CHECK: Node Address:[[N12:0x[0-9a-f]*]]:single-instruction +; CHECK: Node Address:[[N9:0x[0-9a-f]*]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %1 = load float, float* %arrayidx2, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]] -; CHECK: Node Address:[[N13]]:single-instruction +; CHECK: Node Address:[[N10]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %add = fadd float %0, %1 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]] -; CHECK: Node Address:[[N14]]:single-instruction +; CHECK: Node Address:[[N11]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: store float %add, float* %arrayidx3, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [memory] to [[N12]] +; CHECK-NEXT: [memory] to [[N9]] ; CHECK-NEXT:--- end of nodes in pi-block --- ; CHECK-NEXT: Edges:none! @@ -141,14 +126,9 @@ ; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]] -; CHECK: Node Address:[[N7]]:single-instruction +; CHECK: Node Address:[[N7]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp = icmp ult i64 %inc, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N8]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp, label %test2.for.body, label %for.end.loopexit ; CHECK-NEXT: Edges:none! @@ -156,47 +136,31 @@ ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, float* %a, i64 %i.02 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]] +; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]] -; CHECK: Node Address:[[N5]]:single-instruction +; CHECK: Node Address:[[N5]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %add1 = add i64 %i.02, 1 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N10]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %add1 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N11]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %1 = load float, float* %arrayidx2, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]] -; CHECK-NEXT: [memory] to [[N9]] +; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]] +; CHECK-NEXT: [memory] to [[N8]] -; CHECK: Node Address:[[N4]]:single-instruction +; CHECK: Node Address:[[N4]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N13]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N12]] - +; CHECK-NEXT: [def-use] to [[N9]] -; CHECK: Node Address:[[N12]]:single-instruction +; CHECK: Node Address:[[N9]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %add = fadd float %0, %1 ; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N9]] +; CHECK-NEXT: [def-use] to [[N8]] -; CHECK: Node Address:[[N9]]:single-instruction +; CHECK: Node Address:[[N8]]:single-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: store float %add, float* %arrayidx3, align 4 ; CHECK-NEXT: Edges:none! diff --git a/llvm/test/Analysis/DDG/basic-loopnest.ll b/llvm/test/Analysis/DDG/basic-loopnest.ll --- a/llvm/test/Analysis/DDG/basic-loopnest.ll +++ b/llvm/test/Analysis/DDG/basic-loopnest.ll @@ -49,25 +49,15 @@ ; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N15:0x[0-9a-f]*]] -; CHECK: Node Address:[[N15]]:single-instruction +; CHECK: Node Address:[[N15]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %exitcond = icmp ne i64 %inc13, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N16:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N16]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %exitcond, label %test1.for.cond1.preheader, label %for.end14.loopexit ; CHECK-NEXT: Edges:none! -; CHECK: Node Address:[[N14]]:single-instruction +; CHECK: Node Address:[[N14]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %4 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N17:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N17]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx10 = getelementptr inbounds float, float* %a, i64 %4 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N6]] @@ -78,14 +68,9 @@ ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N18:0x[0-9a-f]*]] -; CHECK: Node Address:[[N13]]:single-instruction +; CHECK: Node Address:[[N13]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %2 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N19]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N8]] @@ -96,26 +81,16 @@ ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N18]] -; CHECK: Node Address:[[N12]]:single-instruction +; CHECK: Node Address:[[N12]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N20:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N20]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %0 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N4]] -; CHECK: Node Address:[[N4]]:single-instruction +; CHECK: Node Address:[[N4]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N21:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N21]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N18]] @@ -159,25 +134,15 @@ ; CHECK-NEXT: [def-use] to [[N7]] ; CHECK-NEXT: [def-use] to [[N28:0x[0-9a-f]*]] -; CHECK: Node Address:[[N28]]:single-instruction +; CHECK: Node Address:[[N28]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp21 = icmp ult i64 1, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N29:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N29]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12 ; CHECK-NEXT: Edges:none! -; CHECK: Node Address:[[N7]]:single-instruction +; CHECK: Node Address:[[N7]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp2 = icmp ult i64 %inc, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N30:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N30]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp2, label %for.body4, label %for.inc12.loopexit ; CHECK-NEXT: Edges:none! @@ -279,25 +244,15 @@ ; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]] ; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]] -; CHECK: Node Address:[[N14]]:single-instruction +; CHECK: Node Address:[[N14]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %exitcond = icmp ne i64 %inc13, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N15:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N15]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %exitcond, label %test2.for.cond1.preheader, label %for.end14.loopexit ; CHECK-NEXT: Edges:none! -; CHECK: Node Address:[[N13]]:single-instruction +; CHECK: Node Address:[[N13]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %4 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N16:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N16]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx10 = getelementptr inbounds float, float* %a, i64 %4 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N5]] @@ -308,51 +263,31 @@ ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N17:0x[0-9a-f]*]] -; CHECK: Node Address:[[N12]]:single-instruction +; CHECK: Node Address:[[N12]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %2 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N18:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N18]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N7]] -; CHECK: Node Address:[[N7]]:single-instruction +; CHECK: Node Address:[[N7]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx8 = getelementptr inbounds float, float* %arrayidx6, i64 %add7 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N19]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %3 = load float, float* %arrayidx8, align 4 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N20:0x[0-9a-f]*]] ; CHECK-NEXT: [memory] to [[N17]] -; CHECK: Node Address:[[N11]]:single-instruction +; CHECK: Node Address:[[N11]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %0 = mul nsw i64 %i.04, %n -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N21:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N21]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %0 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N3]] -; CHECK: Node Address:[[N3]]:single-instruction +; CHECK: Node Address:[[N3]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.02 -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N22:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N22]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4 ; CHECK-NEXT: Edges: ; CHECK-NEXT: [def-use] to [[N20]] @@ -385,25 +320,15 @@ ; CHECK-NEXT: [def-use] to [[N6]] ; CHECK-NEXT: [def-use] to [[N26:0x[0-9a-f]*]] -; CHECK: Node Address:[[N26]]:single-instruction +; CHECK: Node Address:[[N26]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp21 = icmp ult i64 1, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N27:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N27]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12 ; CHECK-NEXT: Edges:none! -; CHECK: Node Address:[[N6]]:single-instruction +; CHECK: Node Address:[[N6]]:multi-instruction ; CHECK-NEXT: Instructions: ; CHECK-NEXT: %cmp2 = icmp ult i64 %inc, %sub -; CHECK-NEXT: Edges: -; CHECK-NEXT: [def-use] to [[N28:0x[0-9a-f]*]] - -; CHECK: Node Address:[[N28]]:single-instruction -; CHECK-NEXT: Instructions: ; CHECK-NEXT: br i1 %cmp2, label %for.body4, label %for.inc12.loopexit ; CHECK-NEXT: Edges:none!