xref: /llvm-project/llvm/unittests/Support/GenericDomTreeTest.cpp (revision c2f92fa3ab496a5a8edfe73297ad4f593413af27)
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