| //===- unittests/Support/GenericDomTreeTest.cpp - GenericDomTree.h tests --===// |
| // |
| // 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "llvm/Support/GenericDomTree.h" |
| #include "llvm/ADT/GraphTraits.h" |
| #include "llvm/Support/DataTypes.h" |
| #include "gtest/gtest.h" |
| using namespace llvm; |
| |
| namespace { |
| |
| // Very simple (fake) graph structure to test dominator tree on. |
| struct NumberedGraph; |
| |
| struct NumberedNode { |
| NumberedGraph *Parent; |
| unsigned Number; |
| |
| NumberedNode(NumberedGraph *Parent, unsigned Number) |
| : Parent(Parent), Number(Number) {} |
| |
| NumberedGraph *getParent() const { return Parent; } |
| }; |
| |
| struct NumberedGraph { |
| SmallVector<std::unique_ptr<NumberedNode>> Nodes; |
| unsigned NumberEpoch = 0; |
| |
| NumberedNode *addNode() { |
| unsigned Num = Nodes.size(); |
| return Nodes.emplace_back(std::make_unique<NumberedNode>(this, Num)).get(); |
| } |
| }; |
| } // namespace |
| |
| namespace llvm { |
| template <> struct GraphTraits<NumberedNode *> { |
| using NodeRef = NumberedNode *; |
| static unsigned getNumber(NumberedNode *Node) { return Node->Number; } |
| }; |
| |
| template <> struct GraphTraits<const NumberedNode *> { |
| using NodeRef = NumberedNode *; |
| static unsigned getNumber(const NumberedNode *Node) { return Node->Number; } |
| }; |
| |
| template <> struct GraphTraits<NumberedGraph *> { |
| using NodeRef = NumberedNode *; |
| static unsigned getMaxNumber(NumberedGraph *G) { return G->Nodes.size(); } |
| static unsigned getNumberEpoch(NumberedGraph *G) { return G->NumberEpoch; } |
| }; |
| |
| namespace DomTreeBuilder { |
| // Dummy specialization. Only needed so that we can call recalculate(), which |
| // sets DT.Parent -- but we can't access DT.Parent here. |
| template <> void Calculate(DomTreeBase<NumberedNode> &DT) {} |
| } // end namespace DomTreeBuilder |
| } // end namespace llvm |
| |
| namespace { |
| |
| TEST(GenericDomTree, BlockNumbers) { |
| NumberedGraph G; |
| NumberedNode *N1 = G.addNode(); |
| NumberedNode *N2 = G.addNode(); |
| |
| DomTreeBase<NumberedNode> DT; |
| DT.recalculate(G); // only sets parent |
| // Construct fake domtree: node 0 dominates all other nodes |
| DT.setNewRoot(N1); |
| DT.addNewBlock(N2, N1); |
| |
| // Roundtrip is correct |
| for (auto &N : G.Nodes) |
| EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); |
| // If we manually change a number, we should get a different node. |
| ASSERT_EQ(N1->Number, 0u); |
| ASSERT_EQ(N2->Number, 1u); |
| N1->Number = 1; |
| EXPECT_EQ(DT.getNode(N1)->getBlock(), N2); |
| EXPECT_EQ(DT.getNode(N2)->getBlock(), N2); |
| N2->Number = 0; |
| EXPECT_EQ(DT.getNode(N2)->getBlock(), N1); |
| |
| // Renumer blocks, should fix node domtree-internal node map |
| DT.updateBlockNumbers(); |
| for (auto &N : G.Nodes) |
| EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); |
| |
| // Adding a new node with a higher number is no problem |
| NumberedNode *N3 = G.addNode(); |
| EXPECT_EQ(DT.getNode(N3), nullptr); |
| // ... even if it exceeds getMaxNumber() |
| NumberedNode *N4 = G.addNode(); |
| N4->Number = 1000; |
| EXPECT_EQ(DT.getNode(N4), nullptr); |
| |
| DT.addNewBlock(N3, N1); |
| DT.addNewBlock(N4, N1); |
| for (auto &N : G.Nodes) |
| EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); |
| } |
| |
| } // namespace |