1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[DDG] Data Dependence Graph - Pi Block

Summary:
    This patch adds Pi Blocks to the DDG. A pi-block represents a group of DDG
    nodes that are part of a strongly-connected component of the graph.
    Replacing all the SCCs with pi-blocks results in an acyclic representation
    of the DDG. For example if we have:
       {a -> b}, {b -> c, d}, {c -> a}
    the cycle a -> b -> c -> a is abstracted into a pi-block "p" as follows:
       {p -> d} with "p" containing: {a -> b}, {b -> c}, {c -> a}
    In this implementation the edges between nodes that are part of the pi-block
    are preserved. The crossing edges (edges where one end of the edge is in the
    set of nodes belonging to an SCC and the other end is outside that set) are
    replaced with corresponding edges to/from the pi-block node instead.

    Authored By: bmahjour

    Reviewer: Meinersbur, fhahn, myhsu, xtian, dmgreen, kbarton, jdoerfert

    Reviewed By: Meinersbur

    Subscribers: ychen, arphaman, simoll, a.elovikov, mgorny, hiraditya, jfb, wuzish, llvm-commits, jsji, Whitney, etiotto, ppc-slack

    Tag: #llvm

    Differential Revision: https://reviews.llvm.org/D68827
This commit is contained in:
bmahjour 2019-11-08 15:05:06 -05:00
parent 3ee2413d6c
commit d3fb929e1b
11 changed files with 827 additions and 394 deletions

View File

@ -0,0 +1,48 @@
//===- llvm/ADT/EnumeratedArray.h - Enumerated Array-------------*- C++ -*-===//
//
// 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 defines an array type that can be indexed using scoped enum values.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_ENUMERATEDARRAY_H
#define LLVM_ADT_ENUMERATEDARRAY_H
#include <cassert>
namespace llvm {
template <typename ValueType, typename Enumeration,
Enumeration LargestEnum = Enumeration::Last, typename IndexType = int,
IndexType Size = 1 + static_cast<IndexType>(LargestEnum)>
class EnumeratedArray {
public:
EnumeratedArray() = default;
EnumeratedArray(ValueType V) {
for (IndexType IX = 0; IX < Size; ++IX) {
Underlying[IX] = V;
}
}
inline const ValueType &operator[](const Enumeration Index) const {
auto IX = static_cast<const IndexType>(Index);
assert(IX >= 0 && IX < Size && "Index is out of bounds.");
return Underlying[IX];
}
inline ValueType &operator[](const Enumeration Index) {
return const_cast<ValueType &>(
static_cast<const EnumeratedArray<ValueType, Enumeration, LargestEnum,
IndexType, Size> &>(*this)[Index]);
}
private:
ValueType Underlying[Size];
};
} // namespace llvm
#endif // LLVM_ADT_ENUMERATEDARRAY_H

View File

@ -13,12 +13,12 @@
#ifndef LLVM_ANALYSIS_DDG_H
#define LLVM_ANALYSIS_DDG_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DirectedGraph.h"
#include "llvm/Analysis/DependenceAnalysis.h"
#include "llvm/Analysis/DependenceGraphBuilder.h"
#include "llvm/Analysis/LoopAnalysisManager.h"
#include "llvm/IR/Instructions.h"
#include <unordered_map>
namespace llvm {
class DDGNode;
@ -33,7 +33,11 @@ class LPMUpdater;
/// 1. Single instruction node containing just one instruction.
/// 2. Multiple instruction node where two or more instructions from
/// the same basic block are merged into one node.
/// 3. Root node is a special node that connects to all components such that
/// 3. Pi-block node which is a group of other DDG nodes that are part of a
/// strongly-connected component of the graph.
/// A pi-block node contains more than one single or multiple instruction
/// nodes. The root node cannot be part of a pi-block.
/// 4. Root node is a special node that connects to all components such that
/// there is always a path from it to any node in the graph.
class DDGNode : public DDGNodeBase {
public:
@ -43,6 +47,7 @@ public:
Unknown,
SingleInstruction,
MultiInstruction,
PiBlock,
Root,
};
@ -155,6 +160,55 @@ private:
SmallVector<Instruction *, 2> InstList;
};
/// Subclass of DDGNode representing a pi-block. A pi-block represents a group
/// of DDG nodes that are part of a strongly-connected component of the graph.
/// Replacing all the SCCs with pi-blocks results in an acyclic representation
/// of the DDG. For example if we have:
/// {a -> b}, {b -> c, d}, {c -> a}
/// the cycle a -> b -> c -> a is abstracted into a pi-block "p" as follows:
/// {p -> d} with "p" containing: {a -> b}, {b -> c}, {c -> a}
class PiBlockDDGNode : public DDGNode {
public:
using PiNodeList = SmallVector<DDGNode *, 4>;
PiBlockDDGNode() = delete;
PiBlockDDGNode(const PiNodeList &List);
PiBlockDDGNode(const PiBlockDDGNode &N);
PiBlockDDGNode(PiBlockDDGNode &&N);
~PiBlockDDGNode();
PiBlockDDGNode &operator=(const PiBlockDDGNode &N) {
DDGNode::operator=(N);
NodeList = N.NodeList;
return *this;
}
PiBlockDDGNode &operator=(PiBlockDDGNode &&N) {
DDGNode::operator=(std::move(N));
NodeList = std::move(N.NodeList);
return *this;
}
/// Get the list of nodes in this pi-block.
const PiNodeList &getNodes() const {
assert(!NodeList.empty() && "Node list is empty.");
return NodeList;
}
PiNodeList &getNodes() {
return const_cast<PiNodeList &>(
static_cast<const PiBlockDDGNode *>(this)->getNodes());
}
/// Define classof to be able to use isa<>, cast<>, dyn_cast<>, etc.
static bool classof(const DDGNode *N) {
return N->getKind() == NodeKind::PiBlock;
}
private:
/// List of nodes in this pi-block.
PiNodeList NodeList;
};
/// Data Dependency Graph Edge.
/// An edge in the DDG can represent a def-use relationship or
/// a memory dependence based on the result of DependenceAnalysis.
@ -163,7 +217,13 @@ private:
class DDGEdge : public DDGEdgeBase {
public:
/// The kind of edge in the DDG
enum class EdgeKind { Unknown, RegisterDefUse, MemoryDependence, Rooted };
enum class EdgeKind {
Unknown,
RegisterDefUse,
MemoryDependence,
Rooted,
Last = Rooted // Must be equal to the largest enum value.
};
explicit DDGEdge(DDGNode &N) = delete;
DDGEdge(DDGNode &N, EdgeKind K) : DDGEdgeBase(N), Kind(K) {}
@ -254,11 +314,22 @@ public:
DataDependenceGraph(const Loop &L, DependenceInfo &DI);
~DataDependenceGraph();
/// If node \p N belongs to a pi-block return a pointer to the pi-block,
/// otherwise return null.
const PiBlockDDGNode *getPiBlock(const NodeType &N) const;
protected:
/// Add node \p N to the graph, if it's not added yet, and keep track of
/// the root node. Return true if node is successfully added.
/// Add node \p N to the graph, if it's not added yet, and keep track of the
/// root node as well as pi-blocks and their members. Return true if node is
/// successfully added.
bool addNode(NodeType &N);
private:
using PiBlockMapType = DenseMap<const NodeType *, const PiBlockDDGNode *>;
/// Mapping from graph nodes to their containing pi-blocks. If a node is not
/// part of a pi-block, it will not appear in this map.
PiBlockMapType PiBlockMap;
};
/// Concrete implementation of a pure data dependence graph builder. This class
@ -284,6 +355,12 @@ public:
Graph.addNode(*SN);
return *SN;
}
DDGNode &createPiBlock(const NodeListType &L) final override {
auto *Pi = new PiBlockDDGNode(L);
assert(Pi && "Failed to allocate memory for pi-block node.");
Graph.addNode(*Pi);
return *Pi;
}
DDGEdge &createDefUseEdge(DDGNode &Src, DDGNode &Tgt) final override {
auto *E = new DDGEdge(Tgt, DDGEdge::EdgeKind::RegisterDefUse);
assert(E && "Failed to allocate memory for edge");
@ -304,6 +381,7 @@ public:
return *E;
}
bool shouldCreatePiBlocks() const final override;
};
raw_ostream &operator<<(raw_ostream &OS, const DDGNode &N);

View File

@ -44,7 +44,9 @@ public:
/// The main entry to the graph construction algorithm. It starts by
/// creating nodes in increasing order of granularity and then
/// adds def-use and memory edges.
/// adds def-use and memory edges. As one of the final stages, it
/// also creates pi-block nodes to facilitate codegen in transformations
/// that use dependence graphs.
///
/// The algorithmic complexity of this implementation is O(V^2 * I^2), where V
/// is the number of vertecies (nodes) and I is the number of instructions in
@ -56,6 +58,7 @@ public:
createDefUseEdges();
createMemoryDependencyEdges();
createAndConnectRootNode();
createPiBlocks();
}
/// Create fine grained nodes. These are typically atomic nodes that
@ -74,6 +77,13 @@ public:
/// reachable from the root.
void createAndConnectRootNode();
/// Apply graph abstraction to groups of nodes that belong to a strongly
/// connected component of the graph to create larger compound nodes
/// called pi-blocks. The purpose of this abstraction is to isolate sets of
/// program elements that need to stay together during codegen and turn
/// the dependence graph into an acyclic graph.
void createPiBlocks();
protected:
/// Create the root node of the graph.
virtual NodeType &createRootNode() = 0;
@ -81,6 +91,10 @@ protected:
/// Create an atomic node in the graph given a single instruction.
virtual NodeType &createFineGrainedNode(Instruction &I) = 0;
/// Create a pi-block node in the graph representing a group of nodes in an
/// SCC of the graph.
virtual NodeType &createPiBlock(const NodeListType &L) = 0;
/// Create a def-use edge going from \p Src to \p Tgt.
virtual EdgeType &createDefUseEdge(NodeType &Src, NodeType &Tgt) = 0;
@ -96,6 +110,10 @@ protected:
/// Deallocate memory of node \p N.
virtual void destroyNode(NodeType &N) { delete &N; }
/// Return true if creation of pi-blocks are supported and desired,
/// and false otherwise.
virtual bool shouldCreatePiBlocks() const { return true; }
/// Map types to map instructions to nodes used when populating the graph.
using InstToNodeMap = DenseMap<Instruction *, NodeType *>;

View File

@ -13,6 +13,10 @@
using namespace llvm;
static cl::opt<bool>
CreatePiBlocks("ddg-pi-blocks", cl::init(true), cl::Hidden, cl::ZeroOrMore,
cl::desc("Create pi-block nodes."));
#define DEBUG_TYPE "ddg"
template class llvm::DGEdge<DDGNode, DDGEdge>;
@ -29,9 +33,16 @@ bool DDGNode::collectInstructions(
InstructionListType &IList) const {
assert(IList.empty() && "Expected the IList to be empty on entry.");
if (isa<SimpleDDGNode>(this)) {
for (auto *I : cast<const SimpleDDGNode>(this)->getInstructions())
for (Instruction *I : cast<const SimpleDDGNode>(this)->getInstructions())
if (Pred(I))
IList.push_back(I);
} else if (isa<PiBlockDDGNode>(this)) {
for (const DDGNode *PN : cast<const PiBlockDDGNode>(this)->getNodes()) {
assert(!isa<PiBlockDDGNode>(PN) && "Nested PiBlocks are not supported.");
SmallVector<Instruction *, 8> TmpIList;
PN->collectInstructions(Pred, TmpIList);
IList.insert(IList.end(), TmpIList.begin(), TmpIList.end());
}
} else
llvm_unreachable("unimplemented type of node");
return !IList.empty();
@ -46,11 +57,14 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGNode::NodeKind K) {
case DDGNode::NodeKind::MultiInstruction:
Out = "multi-instruction";
break;
case DDGNode::NodeKind::PiBlock:
Out = "pi-block";
break;
case DDGNode::NodeKind::Root:
Out = "root";
break;
case DDGNode::NodeKind::Unknown:
Out = "??";
Out = "?? (error)";
break;
}
OS << Out;
@ -61,8 +75,15 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGNode &N) {
OS << "Node Address:" << &N << ":" << N.getKind() << "\n";
if (isa<SimpleDDGNode>(N)) {
OS << " Instructions:\n";
for (auto *I : cast<const SimpleDDGNode>(N).getInstructions())
for (const Instruction *I : cast<const SimpleDDGNode>(N).getInstructions())
OS.indent(2) << *I << "\n";
} else if (isa<PiBlockDDGNode>(&N)) {
OS << "--- start of nodes in pi-block ---\n";
auto &Nodes = cast<const PiBlockDDGNode>(&N)->getNodes();
unsigned Count = 0;
for (const DDGNode *N : Nodes)
OS << *N << (++Count == Nodes.size() ? "" : "\n");
OS << "--- end of nodes in pi-block ---\n";
} else if (!isa<RootDDGNode>(N))
llvm_unreachable("unimplemented type of node");
@ -98,6 +119,29 @@ SimpleDDGNode::SimpleDDGNode(SimpleDDGNode &&N)
SimpleDDGNode::~SimpleDDGNode() { InstList.clear(); }
//===--------------------------------------------------------------------===//
// PiBlockDDGNode implementation
//===--------------------------------------------------------------------===//
PiBlockDDGNode::PiBlockDDGNode(const PiNodeList &List)
: DDGNode(NodeKind::PiBlock), NodeList(List) {
assert(!NodeList.empty() && "pi-block node constructed with an empty list.");
}
PiBlockDDGNode::PiBlockDDGNode(const PiBlockDDGNode &N)
: DDGNode(N), NodeList(N.NodeList) {
assert(getKind() == NodeKind::PiBlock && !NodeList.empty() &&
"constructing from invalid pi-block node.");
}
PiBlockDDGNode::PiBlockDDGNode(PiBlockDDGNode &&N)
: DDGNode(std::move(N)), NodeList(std::move(N.NodeList)) {
assert(getKind() == NodeKind::PiBlock && !NodeList.empty() &&
"constructing from invalid pi-block node.");
}
PiBlockDDGNode::~PiBlockDDGNode() { NodeList.clear(); }
//===--------------------------------------------------------------------===//
// DDGEdge implementation
//===--------------------------------------------------------------------===//
@ -115,7 +159,7 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const DDGEdge::EdgeKind K) {
Out = "rooted";
break;
case DDGEdge::EdgeKind::Unknown:
Out = "??";
Out = "?? (error)";
break;
}
OS << Out;
@ -164,23 +208,46 @@ bool DataDependenceGraph::addNode(DDGNode &N) {
return false;
// In general, if the root node is already created and linked, it is not safe
// to add new nodes since they may be unreachable by the root.
// TODO: Allow adding Pi-block nodes after root is created. Pi-blocks are an
// exception because they represent components that are already reachable by
// root.
assert(!Root && "Root node is already added. No more nodes can be added.");
// to add new nodes since they may be unreachable by the root. However,
// pi-block nodes need to be added after the root node is linked, and they are
// always reachable by the root, because they represent components that are
// already reachable by root.
auto *Pi = dyn_cast<PiBlockDDGNode>(&N);
assert(!Root || Pi && "Root node is already added. No more nodes can be added.");
if (isa<RootDDGNode>(N))
Root = &N;
if (Pi)
for (DDGNode *NI : Pi->getNodes())
PiBlockMap.insert(std::make_pair(NI, Pi));
return true;
}
const PiBlockDDGNode *DataDependenceGraph::getPiBlock(const NodeType &N) const {
if (PiBlockMap.find(&N) == PiBlockMap.end())
return nullptr;
auto *Pi = PiBlockMap.find(&N)->second;
assert(PiBlockMap.find(Pi) == PiBlockMap.end() &&
"Nested pi-blocks detected.");
return Pi;
}
raw_ostream &llvm::operator<<(raw_ostream &OS, const DataDependenceGraph &G) {
for (auto *Node : G)
OS << *Node << "\n";
for (DDGNode *Node : G)
// Avoid printing nodes that are part of a pi-block twice. They will get
// printed when the pi-block is printed.
if (!G.getPiBlock(*Node))
OS << *Node << "\n";
OS << "\n";
return OS;
}
bool DDGBuilder::shouldCreatePiBlocks() const {
return CreatePiBlocks;
}
//===--------------------------------------------------------------------===//
// DDG Analysis Passes
//===--------------------------------------------------------------------===//

View File

@ -10,6 +10,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/DependenceGraphBuilder.h"
#include "llvm/ADT/EnumeratedArray.h"
#include "llvm/ADT/SCCIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/DDG.h"
@ -22,6 +23,7 @@ STATISTIC(TotalGraphs, "Number of dependence graphs created.");
STATISTIC(TotalDefUseEdges, "Number of def-use edges created.");
STATISTIC(TotalMemoryEdges, "Number of memory dependence edges created.");
STATISTIC(TotalFineGrainedNodes, "Number of fine-grained nodes created.");
STATISTIC(TotalPiBlockNodes, "Number of pi-block nodes created.");
STATISTIC(TotalConfusedEdges,
"Number of confused memory dependencies between two nodes.");
STATISTIC(TotalEdgeReversals,
@ -74,6 +76,133 @@ void AbstractDependenceGraphBuilder<G>::createAndConnectRootNode() {
}
}
template <class G> void AbstractDependenceGraphBuilder<G>::createPiBlocks() {
if (!shouldCreatePiBlocks())
return;
LLVM_DEBUG(dbgs() << "==== Start of Creation of Pi-Blocks ===\n");
// The overall algorithm is as follows:
// 1. Identify SCCs and for each SCC create a pi-block node containing all
// the nodes in that SCC.
// 2. Identify incoming edges incident to the nodes inside of the SCC and
// reconnect them to the pi-block node.
// 3. Identify outgoing edges from the nodes inside of the SCC to nodes
// outside of it and reconnect them so that the edges are coming out of the
// SCC node instead.
// Adding nodes as we iterate through the SCCs cause the SCC
// iterators to get invalidated. To prevent this invalidation, we first
// collect a list of nodes that are part of an SCC, and then iterate over
// those lists to create the pi-block nodes. Each element of the list is a
// list of nodes in an SCC. Note: trivial SCCs containing a single node are
// ignored.
SmallVector<NodeListType, 4> ListOfSCCs;
for (auto &SCC : make_range(scc_begin(&Graph), scc_end(&Graph))) {
if (SCC.size() > 1)
ListOfSCCs.emplace_back(SCC.begin(), SCC.end());
}
for (NodeListType &NL : ListOfSCCs) {
LLVM_DEBUG(dbgs() << "Creating pi-block node with " << NL.size()
<< " nodes in it.\n");
NodeType &PiNode = createPiBlock(NL);
++TotalPiBlockNodes;
// Build a set to speed up the lookup for edges whose targets
// are inside the SCC.
SmallPtrSet<NodeType *, 4> NodesInSCC(NL.begin(), NL.end());
// We have the set of nodes in the SCC. We go through the set of nodes
// that are outside of the SCC and look for edges that cross the two sets.
for (NodeType *N : Graph) {
// Skip the SCC node and all the nodes inside of it.
if (*N == PiNode || NodesInSCC.count(N))
continue;
for (NodeType *SCCNode : NL) {
enum Direction {
Incoming, // Incoming edges to the SCC
Outgoing, // Edges going ot of the SCC
DirectionCount // To make the enum usable as an array index.
};
// Use these flags to help us avoid creating redundant edges. If there
// are more than one edges from an outside node to inside nodes, we only
// keep one edge from that node to the pi-block node. Similarly, if
// there are more than one edges from inside nodes to an outside node,
// we only keep one edge from the pi-block node to the outside node.
// There is a flag defined for each direction (incoming vs outgoing) and
// for each type of edge supported, using a two-dimensional boolean
// array.
using EdgeKind = typename EdgeType::EdgeKind;
EnumeratedArray<bool, EdgeKind> EdgeAlreadyCreated[DirectionCount]{
false, false};
auto createEdgeOfKind = [this](NodeType &Src, NodeType &Dst,
const EdgeKind K) {
switch (K) {
case EdgeKind::RegisterDefUse:
createDefUseEdge(Src, Dst);
break;
case EdgeKind::MemoryDependence:
createMemoryEdge(Src, Dst);
break;
case EdgeKind::Rooted:
createRootedEdge(Src, Dst);
break;
default:
llvm_unreachable("Unsupported type of edge.");
}
};
auto reconnectEdges = [&](NodeType *Src, NodeType *Dst, NodeType *New,
const Direction Dir) {
if (!Src->hasEdgeTo(*Dst))
return;
LLVM_DEBUG(dbgs()
<< "reconnecting("
<< (Dir == Direction::Incoming ? "incoming)" : "outgoing)")
<< ":\nSrc:" << *Src << "\nDst:" << *Dst
<< "\nNew:" << *New << "\n");
assert((Dir == Direction::Incoming || Dir == Direction::Outgoing) &&
"Invalid direction.");
SmallVector<EdgeType *, 10> EL;
Src->findEdgesTo(*Dst, EL);
for (EdgeType *OldEdge : EL) {
EdgeKind Kind = OldEdge->getKind();
if (!EdgeAlreadyCreated[Dir][Kind]) {
if (Dir == Direction::Incoming) {
createEdgeOfKind(*Src, *New, Kind);
LLVM_DEBUG(dbgs() << "created edge from Src to New.\n");
} else if (Dir == Direction::Outgoing) {
createEdgeOfKind(*New, *Dst, Kind);
LLVM_DEBUG(dbgs() << "created edge from New to Dst.\n");
}
EdgeAlreadyCreated[Dir][Kind] = true;
}
Src->removeEdge(*OldEdge);
destroyEdge(*OldEdge);
LLVM_DEBUG(dbgs() << "removed old edge between Src and Dst.\n\n");
}
};
// Process incoming edges incident to the pi-block node.
reconnectEdges(N, SCCNode, &PiNode, Direction::Incoming);
// Process edges that are coming out of the pi-block node.
reconnectEdges(SCCNode, N, &PiNode, Direction::Outgoing);
}
}
}
LLVM_DEBUG(dbgs() << "==== End of Creation of Pi-Blocks ===\n");
}
template <class G> void AbstractDependenceGraphBuilder<G>::createDefUseEdges() {
for (NodeType *N : Graph) {
InstructionListType SrcIList;

View File

@ -3,65 +3,70 @@
; CHECK-LABEL: 'DDG' for loop 'test1.for.body':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test1.for.body ], [ 0, %test1.for.body.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK: Node Address:[[N7:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N4: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 [[N6]]
; CHECK: Node Address:[[N6]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %conv
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %conv
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N6:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx1 = getelementptr inbounds float, float* %a, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK-NEXT: [def-use] to [[N5]]
; CHECK: Node Address:[[N8]]:single-instruction
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx1, align 4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK: Node Address:[[N7:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %exitcond = icmp ne i64 %inc, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]]
; CHECK: Node Address:[[N10]]:single-instruction
; CHECK: Node Address:[[N8]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %exitcond, label %test1.for.body, label %for.end.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N9:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT: --- start of nodes in pi-block ---
; CHECK-NEXT: Node Address:[[N10:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test1.for.body ], [ 0, %test1.for.body.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK-NEXT: --- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK-NEXT: [def-use] to [[N6]]
; CHECK-NEXT: [def-use] to [[N7]]
;; No memory dependencies.
;; void test1(unsigned long n, float * restrict a, float * restrict b) {
;; for (unsigned long i = 0; i < n; i++)
@ -93,73 +98,78 @@ for.end: ; preds = %test1.for.body, %en
; CHECK-LABEL: 'DDG' for loop 'test2.for.body':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test2.for.body ], [ 0, %test2.for.body.preheader ]
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx1 = getelementptr inbounds float, float* %a, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]]
; CHECK: Node Address:[[N6]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx1 = getelementptr inbounds float, float* %a, 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: %1 = load float, float* %arrayidx1, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [memory] to [[N9:0x[0-9a-f]*]]
; CHECK: Node Address:[[N7]]: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 [[N3]]
; CHECK-NEXT: [memory] to [[N6:0x[0-9a-f]*]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6]]
; CHECK: Node Address:[[N7:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK-NEXT: [def-use] to [[N6]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK: Node Address:[[N6]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx2, align 4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK: Node Address:[[N10]]:single-instruction
; CHECK: Node Address:[[N8:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %exitcond = icmp ne i64 %inc, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]]
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %exitcond, label %test2.for.body, label %for.end.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N10:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT: --- start of nodes in pi-block ---
; CHECK: Node Address:[[N11:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK: Node Address:[[N12]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test2.for.body ], [ 0, %test2.for.body.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11]]
; CHECK-NEXT: --- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK-NEXT: [def-use] to [[N4]]
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [def-use] to [[N8]]
;; Loop-independent memory dependencies.
;; void test2(unsigned long n, float * restrict a, float * restrict b) {
;; for (unsigned long i = 0; i < n; i++)

View File

@ -3,78 +3,87 @@
; CHECK-LABEL: 'DDG' for loop 'test1.for.body':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test1.for.body ], [ 1, %test1.for.body.preheader ]
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %sub1 = add i64 %i.02, -1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %sub1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3]]
; CHECK: Node Address:[[N6]]:single-instruction
; CHECK: Node Address:[[N6:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: %arrayidx3 = 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 [[N3]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK: Node Address:[[N7:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %sub1 = add i64 %i.02, -1
; 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: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %sub1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]]
; CHECK-NEXT: br i1 %cmp, label %test1.for.body, label %for.end.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %1 = load float, float* %arrayidx2, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK: Node Address:[[N3]]:pi-block
; CHECK-NEXT: --- start of nodes in pi-block ---
; CHECK: Node Address:[[N10:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK: Node Address:[[N12:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, float* %a, i64 %i.02
; CHECK-NEXT: %1 = load float, float* %arrayidx2, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK: Node Address:[[N10]]: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 [[N9]]
; CHECK-NEXT: [memory] to [[N12]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK: Node Address:[[N9:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N13:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]]
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK: Node Address:[[N14]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %cmp = icmp ult i64 %inc, %sub
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test1.for.body ], [ 1, %test1.for.body.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N13]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK-NEXT: [def-use] to [[N4]]
; CHECK-NEXT: [def-use] to [[N6]]
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N12]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp, label %test1.for.body, label %for.end.loopexit
; CHECK-NEXT: Edges:none!
;; Loop-carried dependence requiring edge-reversal to expose a cycle
;; in the graph.
@ -107,83 +116,86 @@ for.end: ; preds = %test1.for.body, %en
ret void
}
; CHECK-LABEL: 'DDG' for loop 'test2.for.body':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test2.for.body ], [ 1, %test2.for.body.preheader ]
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add1 = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %add1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6:0x[0-9a-f]*]]
; CHECK: Node Address:[[N6]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add1 = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8:0x[0-9a-f]*]]
; CHECK: Node Address:[[N8]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %add1
; 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* %arrayidx2, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [memory] to [[N10:0x[0-9a-f]*]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK-NEXT: [def-use] to [[N3]]
; CHECK-NEXT: [memory] to [[N7:0x[0-9a-f]*]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N8:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx3 = getelementptr inbounds float, float* %a, i64 %i.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N10]]:single-instruction
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx3, align 4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK: Node Address:[[N9:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %cmp = icmp ult i64 %inc, %sub
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N10:0x[0-9a-f]*]]
; CHECK: Node Address:[[N12]]:single-instruction
; CHECK: Node Address:[[N10]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp, label %test2.for.body, label %for.end.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N11:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N12:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %i.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]]
; CHECK: Node Address:[[N13]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.02 = phi i64 [ %inc, %test2.for.body ], [ 1, %test2.for.body.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK-NEXT: [def-use] to [[N4]]
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK-NEXT: [def-use] to [[N9]]
;; Forward loop-carried dependence *not* causing a cycle.
;; void test2(unsigned long n, float * restrict a, float * restrict b) {

View File

@ -4,170 +4,182 @@
; CHECK-LABEL: 'DDG' for loop 'test1.for.cond1.preheader':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.04 = phi i64 [ %inc13, %for.inc12 ], [ 0, %test1.for.cond1.preheader.preheader ]
; CHECK-NEXT: %sub = add i64 %n, -1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N6:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %sub = add i64 %n, -1
; CHECK-NEXT: %cmp21 = icmp ult i64 1, %sub
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N5:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = mul nsw i64 %i.04, %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: %arrayidx = getelementptr inbounds float, float* %b, i64 %0
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.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: %cmp21 = icmp ult i64 1, %sub
; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N10:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %j.02 = phi i64 [ %inc, %for.body4 ], [ 1, %for.body4.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = mul nsw i64 %i.04, %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: %arrayidx = getelementptr inbounds float, float* %b, i64 %0
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N14]]
; CHECK: Node Address:[[N14]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N16:0x[0-9a-f]*]]
; CHECK: Node Address:[[N16]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N17:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-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-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK: Node Address:[[N18]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK: Node Address:[[N13]]:single-instruction
; CHECK: Node Address:[[N13:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %sub7 = add i64 %j.02, -1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N19]]
; CHECK: Node Address:[[N19]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx8 = getelementptr inbounds float, float* %arrayidx6, i64 %sub7
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N20:0x[0-9a-f]*]]
; CHECK: Node Address:[[N20]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %3 = load float, float* %arrayidx8, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N17]]
; CHECK: Node Address:[[N17]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %1, %3
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26:0x[0-9a-f]*]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %4 = mul nsw i64 %i.04, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N27:0x[0-9a-f]*]]
; CHECK: Node Address:[[N27]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx10 = getelementptr inbounds float, float* %a, i64 %4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12]]
; CHECK: Node Address:[[N12]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx8 = getelementptr inbounds float, float* %arrayidx6, i64 %sub7
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK: Node Address:[[N14:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %4 = mul nsw i64 %i.04, %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: %arrayidx10 = getelementptr inbounds float, float* %a, i64 %4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N16:0x[0-9a-f]*]]
; CHECK: Node Address:[[N16]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx11 = getelementptr inbounds float, float* %arrayidx10, i64 %j.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26]]
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK: Node Address:[[N26]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx11, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [memory] to [[N20]]
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %j.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %cmp2 = icmp ult i64 %inc, %sub
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N21:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N17:0x[0-9a-f]*]]
; CHECK: Node Address:[[N21]]:single-instruction
; CHECK: Node Address:[[N17]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp2, label %for.body4, label %for.inc12.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc13 = add i64 %i.04, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N22:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK: Node Address:[[N22]]:single-instruction
; CHECK: Node Address:[[N18:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %exitcond = icmp ne i64 %inc13, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N23:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]]
; CHECK: Node Address:[[N23]]:single-instruction
; CHECK: Node Address:[[N19]]: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:[[N24:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N20:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br label %for.body4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N25:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N21:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N9]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N22:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %1, %3
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N23:0x[0-9a-f]*]]
; CHECK: Node Address:[[N24:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %3 = load float, float* %arrayidx8, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N22]]
; CHECK: Node Address:[[N23]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx11, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [memory] to [[N24]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N25:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N26:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc13 = add i64 %i.04, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N27:0x[0-9a-f]*]]
; CHECK: Node Address:[[N27]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.04 = phi i64 [ %inc13, %for.inc12 ], [ 0, %test1.for.cond1.preheader.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5]]
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK-NEXT: [def-use] to [[N14]]
; CHECK-NEXT: [def-use] to [[N18]]
; CHECK: Node Address:[[N28:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N29:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %j.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N30:0x[0-9a-f]*]]
; CHECK: Node Address:[[N30]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %j.02 = phi i64 [ %inc, %for.body4 ], [ 1, %for.body4.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N29]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [def-use] to [[N13]]
; CHECK-NEXT: [def-use] to [[N16]]
; CHECK-NEXT: [def-use] to [[N2]]
;; This test has a cycle.
@ -222,170 +234,179 @@ for.end14: ; preds = %for.inc12, %entry
; CHECK-LABEL: 'DDG' for loop 'test2.for.cond1.preheader':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.04 = phi i64 [ %inc13, %for.inc12 ], [ 0, %test2.for.cond1.preheader.preheader ]
; CHECK-NEXT: %sub = add i64 %n, -1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N2:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N3:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N5:0x[0-9a-f]*]]
; CHECK: Node Address:[[N6:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %sub = add i64 %n, -1
; CHECK-NEXT: %cmp21 = icmp ult i64 1, %sub
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N4:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N5:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = mul nsw i64 %i.04, %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: %arrayidx = getelementptr inbounds float, float* %b, i64 %0
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7:0x[0-9a-f]*]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.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: %cmp21 = icmp ult i64 1, %sub
; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9:0x[0-9a-f]*]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp21, label %for.body4.preheader, label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N10:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %j.02 = phi i64 [ %inc, %for.body4 ], [ 1, %for.body4.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]]
; CHECK: Node Address:[[N5]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %0 = mul nsw i64 %i.04, %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: %arrayidx = getelementptr inbounds float, float* %b, i64 %0
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N14]]
; CHECK: Node Address:[[N14]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx5 = getelementptr inbounds float, float* %arrayidx, i64 %j.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N16:0x[0-9a-f]*]]
; CHECK: Node Address:[[N16]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %1 = load float, float* %arrayidx5, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N17:0x[0-9a-f]*]]
; CHECK: Node Address:[[N4]]:single-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-NEXT: [def-use] to [[N11:0x[0-9a-f]*]]
; CHECK: Node Address:[[N18]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx6 = getelementptr inbounds float, float* %a, i64 %2
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N12:0x[0-9a-f]*]]
; CHECK: Node Address:[[N13]]:single-instruction
; CHECK: Node Address:[[N13:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add7 = add i64 %j.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N19]]
; CHECK: Node Address:[[N19]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx8 = getelementptr inbounds float, float* %arrayidx6, i64 %add7
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N20:0x[0-9a-f]*]]
; CHECK: Node Address:[[N20]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %3 = load float, float* %arrayidx8, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N17]]
; CHECK-NEXT: [memory] to [[N26:0x[0-9a-f]*]]
; CHECK: Node Address:[[N17]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %1, %3
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26]]
; CHECK: Node Address:[[N3]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %4 = mul nsw i64 %i.04, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N27:0x[0-9a-f]*]]
; CHECK: Node Address:[[N27]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx10 = getelementptr inbounds float, float* %a, i64 %4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N12]]
; CHECK: Node Address:[[N12]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx8 = getelementptr inbounds float, float* %arrayidx6, i64 %add7
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N14:0x[0-9a-f]*]]
; CHECK: Node Address:[[N14]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %3 = load float, float* %arrayidx8, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK-NEXT: [memory] to [[N15:0x[0-9a-f]*]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %1, %3
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N15]]
; CHECK: Node Address:[[N16:0x[0-9a-f]*]]:single-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 [[N18:0x[0-9a-f]*]]
; CHECK: Node Address:[[N18]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx11 = getelementptr inbounds float, float* %arrayidx10, i64 %j.02
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26]]
; CHECK-NEXT: [def-use] to [[N15]]
; CHECK: Node Address:[[N26]]:single-instruction
; CHECK: Node Address:[[N15]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx11, align 4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N11]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %j.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %cmp2 = icmp ult i64 %inc, %sub
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N19:0x[0-9a-f]*]]
; CHECK: Node Address:[[N19]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br i1 %cmp2, label %for.body4, label %for.inc12.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N20:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %exitcond = icmp ne i64 %inc13, %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: br i1 %cmp2, label %for.body4, label %for.inc12.loopexit
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N2]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc13 = add i64 %i.04, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N22:0x[0-9a-f]*]]
; CHECK-NEXT: [def-use] to [[N1]]
; CHECK: Node Address:[[N22]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %exitcond = icmp ne i64 %inc13, %n
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N23:0x[0-9a-f]*]]
; CHECK: Node Address:[[N23]]: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:[[N24:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N22:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br label %for.body4
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N25:0x[0-9a-f]*]]:single-instruction
; CHECK: Node Address:[[N23:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: br label %for.inc12
; CHECK-NEXT: Edges:none!
; CHECK: Node Address:[[N24:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N25:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc13 = add i64 %i.04, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N26:0x[0-9a-f]*]]
; CHECK: Node Address:[[N26]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i.04 = phi i64 [ %inc13, %for.inc12 ], [ 0, %test2.for.cond1.preheader.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N25]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N5]]
; CHECK-NEXT: [def-use] to [[N10]]
; CHECK-NEXT: [def-use] to [[N16]]
; CHECK-NEXT: [def-use] to [[N20]]
; CHECK: Node Address:[[N27:0x[0-9a-f]*]]:pi-block
; CHECK-NEXT:--- start of nodes in pi-block ---
; CHECK: Node Address:[[N28:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %inc = add i64 %j.02, 1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N29:0x[0-9a-f]*]]
; CHECK: Node Address:[[N29]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %j.02 = phi i64 [ %inc, %for.body4 ], [ 1, %for.body4.preheader ]
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N28]]
; CHECK-NEXT:--- end of nodes in pi-block ---
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK-NEXT: [def-use] to [[N13]]
; CHECK-NEXT: [def-use] to [[N18]]
; CHECK-NEXT: [def-use] to [[N2]]
;; This test has no cycles.
;; void test2(unsigned long n, float a[][n], float b[][n]) {
;; for (unsigned long i = 0; i < n; i++)

View File

@ -2,18 +2,16 @@
; CHECK-LABEL: 'DDG' for loop 'test1.for.body':
; CHECK: Node Address:[[N1:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i2.03 = phi i64 [ 0, %for.body.lr.ph ], [ %inc2, %test1.for.body ]
; CHECK: Node Address:[[N2:0x[0-9a-f]*]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %i1.02 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %test1.for.body ]
; CHECK: Node Address:[[ROOT:0x[0-9a-f]*]]:root
; CHECK-NEXT: Edges:
; CHECK-NEXT: [rooted] to [[N1]]
; CHECK-NEXT: [rooted] to [[N2]]
; CHECK-NEXT: [rooted] to [[N1:0x[0-9a-f]*]]
; CHECK-NEXT: [rooted] to [[N2:0x[0-9a-f]*]]
; CHECK: Node Address:[[N1]]:pi-block
; CHECK: %i2.03 = phi i64 [ 0, %for.body.lr.ph ], [ %inc2, %test1.for.body ]
; CHECK: Node Address:[[N2]]:pi-block
; CHECK: %i1.02 = phi i64 [ 0, %for.body.lr.ph ], [ %inc, %test1.for.body ]
;; // Two separate components in the graph. Root node must link to both.

View File

@ -18,6 +18,7 @@ add_llvm_unittest(ADTTests
DenseSetTest.cpp
DepthFirstIteratorTest.cpp
DirectedGraphTest.cpp
EnumeratedArrayTest.cpp
EquivalenceClassesTest.cpp
FallibleIteratorTest.cpp
FoldingSet.cpp

View File

@ -0,0 +1,51 @@
//===- llvm/unittest/ADT/EnumeratedArrayTest.cpp ----------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// EnumeratedArray unit tests.
//
//===----------------------------------------------------------------------===//
#include "llvm/ADT/EnumeratedArray.h"
#include "gtest/gtest.h"
namespace llvm {
//===--------------------------------------------------------------------===//
// Test initialization and use of operator[] for both read and write.
//===--------------------------------------------------------------------===//
TEST(EnumeratedArray, InitAndIndex) {
enum class Colors { Red, Blue, Green, Last = Green };
EnumeratedArray<float, Colors, Colors::Last, size_t> Array1;
Array1[Colors::Red] = 1.0;
Array1[Colors::Blue] = 2.0;
Array1[Colors::Green] = 3.0;
EXPECT_EQ(Array1[Colors::Red], 1.0);
EXPECT_EQ(Array1[Colors::Blue], 2.0);
EXPECT_EQ(Array1[Colors::Green], 3.0);
EnumeratedArray<bool, Colors> Array2(true);
EXPECT_TRUE(Array2[Colors::Red]);
EXPECT_TRUE(Array2[Colors::Blue]);
EXPECT_TRUE(Array2[Colors::Green]);
Array2[Colors::Red] = true;
Array2[Colors::Blue] = false;
Array2[Colors::Green] = true;
EXPECT_TRUE(Array2[Colors::Red]);
EXPECT_FALSE(Array2[Colors::Blue]);
EXPECT_TRUE(Array2[Colors::Green]);
}
} // namespace llvm