1*c2f92fa3SAlexis Engelke //===- unittests/Support/GenericDomTreeTest.cpp - GenericDomTree.h tests --===// 2*c2f92fa3SAlexis Engelke // 3*c2f92fa3SAlexis Engelke // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*c2f92fa3SAlexis Engelke // See https://llvm.org/LICENSE.txt for license information. 5*c2f92fa3SAlexis Engelke // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*c2f92fa3SAlexis Engelke // 7*c2f92fa3SAlexis Engelke //===----------------------------------------------------------------------===// 8*c2f92fa3SAlexis Engelke 9*c2f92fa3SAlexis Engelke #include "llvm/Support/GenericDomTree.h" 10*c2f92fa3SAlexis Engelke #include "llvm/ADT/GraphTraits.h" 11*c2f92fa3SAlexis Engelke #include "llvm/Support/DataTypes.h" 12*c2f92fa3SAlexis Engelke #include "gtest/gtest.h" 13*c2f92fa3SAlexis Engelke using namespace llvm; 14*c2f92fa3SAlexis Engelke 15*c2f92fa3SAlexis Engelke namespace { 16*c2f92fa3SAlexis Engelke 17*c2f92fa3SAlexis Engelke // Very simple (fake) graph structure to test dominator tree on. 18*c2f92fa3SAlexis Engelke struct NumberedGraph; 19*c2f92fa3SAlexis Engelke 20*c2f92fa3SAlexis Engelke struct NumberedNode { 21*c2f92fa3SAlexis Engelke NumberedGraph *Parent; 22*c2f92fa3SAlexis Engelke unsigned Number; 23*c2f92fa3SAlexis Engelke 24*c2f92fa3SAlexis Engelke NumberedNode(NumberedGraph *Parent, unsigned Number) 25*c2f92fa3SAlexis Engelke : Parent(Parent), Number(Number) {} 26*c2f92fa3SAlexis Engelke 27*c2f92fa3SAlexis Engelke NumberedGraph *getParent() const { return Parent; } 28*c2f92fa3SAlexis Engelke }; 29*c2f92fa3SAlexis Engelke 30*c2f92fa3SAlexis Engelke struct NumberedGraph { 31*c2f92fa3SAlexis Engelke SmallVector<std::unique_ptr<NumberedNode>> Nodes; 32*c2f92fa3SAlexis Engelke unsigned NumberEpoch = 0; 33*c2f92fa3SAlexis Engelke 34*c2f92fa3SAlexis Engelke NumberedNode *addNode() { 35*c2f92fa3SAlexis Engelke unsigned Num = Nodes.size(); 36*c2f92fa3SAlexis Engelke return Nodes.emplace_back(std::make_unique<NumberedNode>(this, Num)).get(); 37*c2f92fa3SAlexis Engelke } 38*c2f92fa3SAlexis Engelke }; 39*c2f92fa3SAlexis Engelke } // namespace 40*c2f92fa3SAlexis Engelke 41*c2f92fa3SAlexis Engelke namespace llvm { 42*c2f92fa3SAlexis Engelke template <> struct GraphTraits<NumberedNode *> { 43*c2f92fa3SAlexis Engelke using NodeRef = NumberedNode *; 44*c2f92fa3SAlexis Engelke static unsigned getNumber(NumberedNode *Node) { return Node->Number; } 45*c2f92fa3SAlexis Engelke }; 46*c2f92fa3SAlexis Engelke 47*c2f92fa3SAlexis Engelke template <> struct GraphTraits<const NumberedNode *> { 48*c2f92fa3SAlexis Engelke using NodeRef = NumberedNode *; 49*c2f92fa3SAlexis Engelke static unsigned getNumber(const NumberedNode *Node) { return Node->Number; } 50*c2f92fa3SAlexis Engelke }; 51*c2f92fa3SAlexis Engelke 52*c2f92fa3SAlexis Engelke template <> struct GraphTraits<NumberedGraph *> { 53*c2f92fa3SAlexis Engelke using NodeRef = NumberedNode *; 54*c2f92fa3SAlexis Engelke static unsigned getMaxNumber(NumberedGraph *G) { return G->Nodes.size(); } 55*c2f92fa3SAlexis Engelke static unsigned getNumberEpoch(NumberedGraph *G) { return G->NumberEpoch; } 56*c2f92fa3SAlexis Engelke }; 57*c2f92fa3SAlexis Engelke 58*c2f92fa3SAlexis Engelke namespace DomTreeBuilder { 59*c2f92fa3SAlexis Engelke // Dummy specialization. Only needed so that we can call recalculate(), which 60*c2f92fa3SAlexis Engelke // sets DT.Parent -- but we can't access DT.Parent here. 61*c2f92fa3SAlexis Engelke template <> void Calculate(DomTreeBase<NumberedNode> &DT) {} 62*c2f92fa3SAlexis Engelke } // end namespace DomTreeBuilder 63*c2f92fa3SAlexis Engelke } // end namespace llvm 64*c2f92fa3SAlexis Engelke 65*c2f92fa3SAlexis Engelke namespace { 66*c2f92fa3SAlexis Engelke 67*c2f92fa3SAlexis Engelke TEST(GenericDomTree, BlockNumbers) { 68*c2f92fa3SAlexis Engelke NumberedGraph G; 69*c2f92fa3SAlexis Engelke NumberedNode *N1 = G.addNode(); 70*c2f92fa3SAlexis Engelke NumberedNode *N2 = G.addNode(); 71*c2f92fa3SAlexis Engelke 72*c2f92fa3SAlexis Engelke DomTreeBase<NumberedNode> DT; 73*c2f92fa3SAlexis Engelke DT.recalculate(G); // only sets parent 74*c2f92fa3SAlexis Engelke // Construct fake domtree: node 0 dominates all other nodes 75*c2f92fa3SAlexis Engelke DT.setNewRoot(N1); 76*c2f92fa3SAlexis Engelke DT.addNewBlock(N2, N1); 77*c2f92fa3SAlexis Engelke 78*c2f92fa3SAlexis Engelke // Roundtrip is correct 79*c2f92fa3SAlexis Engelke for (auto &N : G.Nodes) 80*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); 81*c2f92fa3SAlexis Engelke // If we manually change a number, we should get a different node. 82*c2f92fa3SAlexis Engelke ASSERT_EQ(N1->Number, 0u); 83*c2f92fa3SAlexis Engelke ASSERT_EQ(N2->Number, 1u); 84*c2f92fa3SAlexis Engelke N1->Number = 1; 85*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N1)->getBlock(), N2); 86*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N2)->getBlock(), N2); 87*c2f92fa3SAlexis Engelke N2->Number = 0; 88*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N2)->getBlock(), N1); 89*c2f92fa3SAlexis Engelke 90*c2f92fa3SAlexis Engelke // Renumer blocks, should fix node domtree-internal node map 91*c2f92fa3SAlexis Engelke DT.updateBlockNumbers(); 92*c2f92fa3SAlexis Engelke for (auto &N : G.Nodes) 93*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); 94*c2f92fa3SAlexis Engelke 95*c2f92fa3SAlexis Engelke // Adding a new node with a higher number is no problem 96*c2f92fa3SAlexis Engelke NumberedNode *N3 = G.addNode(); 97*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N3), nullptr); 98*c2f92fa3SAlexis Engelke // ... even if it exceeds getMaxNumber() 99*c2f92fa3SAlexis Engelke NumberedNode *N4 = G.addNode(); 100*c2f92fa3SAlexis Engelke N4->Number = 1000; 101*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N4), nullptr); 102*c2f92fa3SAlexis Engelke 103*c2f92fa3SAlexis Engelke DT.addNewBlock(N3, N1); 104*c2f92fa3SAlexis Engelke DT.addNewBlock(N4, N1); 105*c2f92fa3SAlexis Engelke for (auto &N : G.Nodes) 106*c2f92fa3SAlexis Engelke EXPECT_EQ(DT.getNode(N.get())->getBlock(), N.get()); 107*c2f92fa3SAlexis Engelke } 108*c2f92fa3SAlexis Engelke 109*c2f92fa3SAlexis Engelke } // namespace 110