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

[DDG] Data Dependence Graph - Graph Simplification

Summary:
This is the last functional patch affecting the representation of DDG.
Here we try to simplify the DDG to reduce the number of nodes and edges by
iteratively merging pairs of nodes that satisfy the following conditions,
until no such pair can be identified. A pair of nodes consisting of a and b
can be merged if:

    1. the only edge from a is a def-use edge to b and
    2. the only edge to b is a def-use edge from a and
    3. there is no cyclic edge from b to a and
    4. all instructions in a and b belong to the same basic block and
    5. both a and b are simple (single or multi instruction) nodes.

These criteria allow us to fold many uninteresting def-use edges that
commonly exist in the graph while avoiding the risk of introducing
dependencies that didn't exist before.

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

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D72350
This commit is contained in:
Bardia Mahjour 2020-02-18 16:38:10 -05:00
parent 05986e5408
commit d2570e78cd
7 changed files with 250 additions and 209 deletions

View File

@ -104,6 +104,8 @@ public:
/// Subclass of DDGNode representing single or multi-instruction nodes.
class SimpleDDGNode : public DDGNode {
friend class DDGBuilder;
public:
SimpleDDGNode() = delete;
SimpleDDGNode(Instruction &I);
@ -388,6 +390,12 @@ public:
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;
};

View File

@ -58,6 +58,7 @@ public:
createFineGrainedNodes();
createDefUseEdges();
createMemoryDependencyEdges();
simplify();
createAndConnectRootNode();
createPiBlocks();
sortNodesTopologically();
@ -92,6 +93,15 @@ public:
/// 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,18 @@ protected:
/// 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() &&

View File

@ -16,6 +16,11 @@
using namespace llvm;
static cl::opt<bool> 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<bool>
CreatePiBlocks("ddg-pi-blocks", cl::init(true), cl::Hidden, cl::ZeroOrMore,
cl::desc("Create pi-block nodes."));
@ -257,10 +262,47 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, const DataDependenceGraph &G) {
return OS;
}
bool DDGBuilder::shouldCreatePiBlocks() const {
return CreatePiBlocks;
//===--------------------------------------------------------------------===//
// 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.
const auto *SimpleSrc = dyn_cast<const SimpleDDGNode>(&Src);
const auto *SimpleTgt = dyn_cast<const SimpleDDGNode>(&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<SimpleDDGNode>(&A) && isa<SimpleDDGNode>(&B) &&
"Expected simple nodes");
// Copy instructions from B to the end of A.
cast<SimpleDDGNode>(&A)->appendInstructions(*cast<SimpleDDGNode>(&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; }
//===--------------------------------------------------------------------===//
// DDG Analysis Passes
//===--------------------------------------------------------------------===//

View File

@ -374,6 +374,111 @@ void AbstractDependenceGraphBuilder<G>::createMemoryDependencyEdges() {
}
}
template <class G> void AbstractDependenceGraphBuilder<G>::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<NodeType *, 32> 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<NodeType *, unsigned> 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<NodeType *, 32> 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 <class G>
void AbstractDependenceGraphBuilder<G>::sortNodesTopologically() {

View File

@ -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,34 +31,29 @@
; 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: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %conv
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %conv
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N6]]
; 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 @@ for.end: ; preds = %test1.for.body, %en
; 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,41 +118,31 @@ for.end: ; preds = %test1.for.body, %en
; 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: Node Address:[[N20]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK: Node Address:[[N8]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N7]]
; CHECK: Node Address:[[N7]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx2, align 4
; CHECK-NEXT: Edges:none!

View File

@ -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: %arrayidx2 = getelementptr inbounds float, float* %a, i64 %sub1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK: Node Address:[[N4]]:multi-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK: Node Address:[[N8]]:pi-block
; CHECK-NEXT: --- start of nodes in pi-block ---
; 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 [[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: Node Address:[[N4]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %arrayidx = getelementptr inbounds float, float* %b, i64 %i.02
; CHECK-NEXT: %add = fadd float %0, %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: %0 = load float, float* %arrayidx, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK: Node Address:[[N9]]: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: %1 = load float, float* %arrayidx2, align 4
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N13:0x[0-9a-f]*]]
; CHECK: Node Address:[[N13]]: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: Node Address:[[N14]]: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 @@ for.end: ; preds = %test1.for.body, %en
; 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,48 +136,32 @@ for.end: ; preds = %test1.for.body, %en
; 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: Node Address:[[N12]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N9]]
; CHECK: Node Address:[[N9]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: %add = fadd float %0, %1
; CHECK-NEXT: Edges:
; CHECK-NEXT: [def-use] to [[N8]]
; CHECK: Node Address:[[N8]]:single-instruction
; CHECK-NEXT: Instructions:
; CHECK-NEXT: store float %add, float* %arrayidx3, align 4
; CHECK-NEXT: Edges:none!

View File

@ -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 @@ for.end14: ; preds = %for.inc12, %entry
; 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 @@ for.end14: ; preds = %for.inc12, %entry
; 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 @@ for.end14: ; preds = %for.inc12, %entry
; 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!