void IDFCalculator<NodeTy, IsPostDom>::calculate(
SmallVectorImpl<BasicBlock *> &PHIBlocks) {
// Use a priority queue keyed on dominator tree level so that inserted nodes
- // are handled from the bottom of the dominator tree upwards.
- typedef std::pair<DomTreeNode *, unsigned> DomTreeNodePair;
+ // are handled from the bottom of the dominator tree upwards. We also augment
+ // the level with a DFS number to ensure that the blocks are ordered in a
+ // deterministic way.
+ typedef std::pair<DomTreeNode *, std::pair<unsigned, unsigned>>
+ DomTreeNodePair;
typedef std::priority_queue<DomTreeNodePair, SmallVector<DomTreeNodePair, 32>,
less_second> IDFPriorityQueue;
IDFPriorityQueue PQ;
+ DT.updateDFSNumbers();
+
for (BasicBlock *BB : *DefBlocks) {
if (DomTreeNode *Node = DT.getNode(BB))
- PQ.push({Node, Node->getLevel()});
+ PQ.push({Node, std::make_pair(Node->getLevel(), Node->getDFSNumIn())});
}
SmallVector<DomTreeNode *, 32> Worklist;
DomTreeNodePair RootPair = PQ.top();
PQ.pop();
DomTreeNode *Root = RootPair.first;
- unsigned RootLevel = RootPair.second;
+ unsigned RootLevel = RootPair.second.first;
// Walk all dominator tree children of Root, inspecting their CFG edges with
// targets elsewhere on the dominator tree. Only targets whose level is at
PHIBlocks.emplace_back(SuccBB);
if (!DefBlocks->count(SuccBB))
- PQ.push(std::make_pair(SuccNode, SuccLevel));
+ PQ.push(std::make_pair(
+ SuccNode, std::make_pair(SuccLevel, SuccNode->getDFSNumIn())));
}
for (auto DomChild : *Node) {
#include <random>
#include "llvm/Analysis/PostDominators.h"
+#include "llvm/Analysis/IteratedDominanceFrontier.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Dominators.h"
});
}
+// Verify that the IDF returns blocks in a deterministic way.
+//
+// Test case:
+//
+// CFG
+//
+// (A)
+// / \
+// / \
+// (B) (C)
+// |\ /|
+// | X |
+// |/ \|
+// (D) (E)
+//
+// IDF for block B is {D, E}, and the order of blocks in this list is defined by
+// their 1) level in dom-tree and 2) DFSIn number if the level is the same.
+//
+TEST(DominatorTree, IDFDeterminismTest) {
+ StringRef ModuleString =
+ "define void @f() {\n"
+ "A:\n"
+ " br i1 undef, label %B, label %C\n"
+ "B:\n"
+ " br i1 undef, label %D, label %E\n"
+ "C:\n"
+ " br i1 undef, label %D, label %E\n"
+ "D:\n"
+ " ret void\n"
+ "E:\n"
+ " ret void\n"
+ "}\n";
+
+ // Parse the module.
+ LLVMContext Context;
+ std::unique_ptr<Module> M = makeLLVMModule(Context, ModuleString);
+
+ runWithDomTree(
+ *M, "f", [&](Function &F, DominatorTree *DT, PostDomTree *PDT) {
+ Function::iterator FI = F.begin();
+
+ BasicBlock *A = &*FI++;
+ BasicBlock *B = &*FI++;
+ BasicBlock *C = &*FI++;
+ BasicBlock *D = &*FI++;
+ BasicBlock *E = &*FI++;
+ (void)C;
+
+ DT->updateDFSNumbers();
+ ForwardIDFCalculator IDF(*DT);
+ SmallPtrSet<BasicBlock *, 1> DefBlocks;
+ DefBlocks.insert(B);
+ IDF.setDefiningBlocks(DefBlocks);
+
+ SmallVector<BasicBlock *, 32> IDFBlocks;
+ SmallPtrSet<BasicBlock *, 32> LiveInBlocks;
+ IDF.resetLiveInBlocks();
+ IDF.calculate(IDFBlocks);
+
+
+ EXPECT_EQ(IDFBlocks.size(), 2UL);
+ EXPECT_EQ(DT->getNode(A)->getDFSNumIn(), 0UL);
+ EXPECT_EQ(IDFBlocks[0], D);
+ EXPECT_EQ(IDFBlocks[1], E);
+ EXPECT_TRUE(DT->getNode(IDFBlocks[0])->getDFSNumIn() <
+ DT->getNode(IDFBlocks[1])->getDFSNumIn());
+ });
+}
+
namespace {
const auto Insert = CFGBuilder::ActionKind::Insert;
const auto Delete = CFGBuilder::ActionKind::Delete;