Jlm
GammaTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2014 2015 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
8 #include <jlm/rvsdg/control.hpp>
9 #include <jlm/rvsdg/gamma.hpp>
10 #include <jlm/rvsdg/TestType.hpp>
11 #include <jlm/rvsdg/view.hpp>
12 
13 TEST(GammaTests, test_gamma)
14 {
15  using namespace jlm::rvsdg;
16 
17  Graph graph;
18  auto cmp = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(2), "");
19  auto v0 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
20  auto v1 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
21  auto v2 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
22  auto v3 = &jlm::rvsdg::GraphImport::Create(graph, ControlType::Create(2), "");
23 
24  auto & matchNode = MatchOperation::CreateNode(*cmp, { { 0, 0 }, { 1, 1 } }, 2, 3);
25 
26  auto gamma = GammaNode::create(matchNode.output(0), 3);
27  auto ev0 = gamma->AddEntryVar(v0);
28  auto ev1 = gamma->AddEntryVar(v1);
29  auto ev2 = gamma->AddEntryVar(v2);
30  gamma->AddExitVar({ ev0.branchArgument[0], ev1.branchArgument[1], ev2.branchArgument[2] });
31 
32  GraphExport::Create(*gamma->output(0), "dummy");
33 
34  EXPECT_NE(gamma, nullptr);
35  EXPECT_EQ(gamma->GetOperation(), GammaOperation(3));
36 
37  /* test gamma copy */
38 
39  auto gamma2 = static_cast<StructuralNode *>(gamma)->copy(
40  &graph.GetRootRegion(),
41  { matchNode.output(0), v0, v1, v2 });
42  view(&graph.GetRootRegion(), stdout);
43  EXPECT_NE(dynamic_cast<const GammaNode *>(gamma2), nullptr);
44 
45  /* test entry and exit variable iterators */
46 
47  auto gamma3 = GammaNode::create(v3, 2);
48  EXPECT_TRUE(gamma3->GetEntryVars().empty());
49  EXPECT_TRUE(gamma3->GetExitVars().empty());
50 }
51 
52 TEST(GammaTests, test_predicate_reduction)
53 {
54  using namespace jlm::rvsdg;
55 
56  // Arrange
57  Graph graph;
58  BitType bits2(2);
59 
60  auto v0 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
61  auto v1 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
62  auto v2 = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(32), "");
63 
64  auto pred = &ControlConstantOperation::create(graph.GetRootRegion(), 3, 1);
65 
66  auto gamma = GammaNode::create(pred, 3);
67  auto ev0 = gamma->AddEntryVar(v0);
68  auto ev1 = gamma->AddEntryVar(v1);
69  auto ev2 = gamma->AddEntryVar(v2);
70  gamma->AddExitVar({ ev0.branchArgument[0], ev1.branchArgument[1], ev2.branchArgument[2] });
71 
72  auto & r = GraphExport::Create(*gamma->output(0), "");
73 
74  view(&graph.GetRootRegion(), stdout);
75 
76  // Act
77  auto gammaNode = TryGetOwnerNode<GammaNode>(*r.origin());
79  view(&graph.GetRootRegion(), stdout);
80 
81  // Assert
82  EXPECT_EQ(r.origin(), v1);
83 
84  graph.PruneNodes();
85  EXPECT_EQ(graph.GetRootRegion().numNodes(), 0u);
86 }
87 
88 TEST(GammaTests, test_invariant_reduction)
89 {
90  using namespace jlm::rvsdg;
91 
92  // Arrange
93  Graph graph;
94  const auto valueType = TestType::createValueType();
95 
96  const auto predicate = &jlm::rvsdg::GraphImport::Create(graph, ControlType::Create(2), "");
97  const auto value = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
98 
99  const auto gammaNode = GammaNode::create(predicate, 2);
100  auto [input, branchArgument] = gammaNode->AddEntryVar(value);
101  gammaNode->AddExitVar(branchArgument);
102 
103  auto & ex = GraphExport::Create(*gammaNode->output(0), "");
104 
105  view(&graph.GetRootRegion(), stdout);
106 
107  // Act
108  const auto success = ReduceGammaInvariantVariables(*gammaNode);
109  view(&graph.GetRootRegion(), stdout);
110 
111  // Assert
112  EXPECT_TRUE(success);
113  EXPECT_EQ(ex.origin(), value);
114 
115  graph.PruneNodes();
116  EXPECT_EQ(graph.GetRootRegion().numNodes(), 0u);
117 }
118 
119 TEST(GammaTests, test_control_constant_reduction)
120 {
121  using namespace jlm::rvsdg;
122 
123  // Arrange
124  Graph graph;
125 
126  auto x = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(1), "x");
127 
128  auto & matchNode = MatchOperation::CreateNode(*x, { { 0, 0 } }, 1, 2);
129 
130  auto gamma = GammaNode::create(matchNode.output(0), 2);
131 
132  auto t = &ControlConstantOperation::createTrue(*gamma->subregion(0));
133  auto f = &ControlConstantOperation::createFalse(*gamma->subregion(1));
134 
135  auto n0 = &ControlConstantOperation::create(*gamma->subregion(0), 3, 0);
136  auto n1 = &ControlConstantOperation::create(*gamma->subregion(1), 3, 1);
137 
138  auto xv1 = gamma->AddExitVar({ t, f });
139  auto xv2 = gamma->AddExitVar({ n0, n1 });
140 
141  auto & ex1 = GraphExport::Create(*xv1.output, "");
142  auto & ex2 = GraphExport::Create(*xv2.output, "");
143 
144  view(&graph.GetRootRegion(), stdout);
145 
146  // Act
147  auto gammaNode = TryGetOwnerNode<GammaNode>(*ex1.origin());
148  ReduceGammaControlConstant(*gammaNode);
149  view(&graph.GetRootRegion(), stdout);
150 
151  // Assert
152  {
153  auto [matchNode, matchOperation] = TryGetSimpleNodeAndOptionalOp<MatchOperation>(*ex1.origin());
154  EXPECT_TRUE(matchNode && matchOperation);
155  EXPECT_EQ(matchOperation->default_alternative(), 0u);
156 
157  EXPECT_EQ(TryGetOwnerNode<Node>(*ex2.origin()), gamma);
158  }
159 }
160 
161 TEST(GammaTests, test_control_constant_reduction2)
162 {
163  using namespace jlm::rvsdg;
164 
165  // Arrange
166  Graph graph;
167 
168  auto import = &jlm::rvsdg::GraphImport::Create(graph, BitType::Create(2), "import");
169 
170  auto & matchNode = MatchOperation::CreateNode(*import, { { 3, 2 }, { 2, 1 }, { 1, 0 } }, 3, 4);
171 
172  auto gamma = GammaNode::create(matchNode.output(0), 4);
173 
174  auto t1 = &ControlConstantOperation::createTrue(*gamma->subregion(0));
175  auto t2 = &ControlConstantOperation::createTrue(*gamma->subregion(1));
176  auto t3 = &ControlConstantOperation::createTrue(*gamma->subregion(2));
177  auto f = &ControlConstantOperation::createFalse(*gamma->subregion(3));
178 
179  auto xv = gamma->AddExitVar({ t1, t2, t3, f });
180 
181  auto & ex = GraphExport::Create(*xv.output, "");
182 
183  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
184 
185  // Act
186  auto gammaNode = TryGetOwnerNode<GammaNode>(*ex.origin());
187  ReduceGammaControlConstant(*gammaNode);
188  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
189 
190  // Assert
191  auto match = TryGetOwnerNode<SimpleNode>(*ex.origin());
192  EXPECT_TRUE(is<MatchOperation>(match->GetOperation()));
193 }
194 
195 TEST(GammaTests, TestPruneOutputs)
196 {
197  using namespace jlm::rvsdg;
198 
199  // Arrange
200  Graph rvsdg;
201  auto vt = TestType::createValueType();
202  ControlType ct(2);
203 
204  auto predicate = &jlm::rvsdg::GraphImport::Create(rvsdg, ControlType::Create(2), "");
205  auto v0 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
206  auto v1 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
207  auto v2 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
208  auto v3 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
209 
210  auto gammaNode = GammaNode::create(predicate, 2);
211  auto gammaInput0 = gammaNode->AddEntryVar(v0);
212  auto gammaInput1 = gammaNode->AddEntryVar(v1);
213  auto gammaInput2 = gammaNode->AddEntryVar(v2);
214  auto gammaInput3 = gammaNode->AddEntryVar(v3);
215 
216  auto gammaOutput0 = gammaNode->AddExitVar(gammaInput0.branchArgument);
217  gammaNode->AddExitVar(gammaInput1.branchArgument);
218  auto gammaOutput2 = gammaNode->AddExitVar(gammaInput2.branchArgument);
219  gammaNode->AddExitVar(gammaInput3.branchArgument);
220 
221  GraphExport::Create(*gammaOutput0.output, "");
222  GraphExport::Create(*gammaOutput2.output, "");
223 
224  // Act
225  gammaNode->PruneExitVars();
226 
227  // Assert
228  EXPECT_EQ(gammaNode->noutputs(), 2u);
229  EXPECT_EQ(gammaNode->subregion(0)->nresults(), 2u);
230  EXPECT_EQ(gammaNode->subregion(1)->nresults(), 2u);
231 
232  EXPECT_EQ(gammaOutput0.output->index(), 0u);
233  EXPECT_EQ(gammaNode->GetExitVars()[0].output, gammaOutput0.output);
234 
235  EXPECT_EQ(gammaOutput2.output->index(), 1u);
236  EXPECT_EQ(gammaNode->GetExitVars()[1].output, gammaOutput2.output);
237 }
238 
239 TEST(GammaTests, TestIsInvariant)
240 {
241  using namespace jlm::rvsdg;
242 
243  // Arrange
244  Graph rvsdg;
245  auto vt = TestType::createValueType();
246  ControlType ct(2);
247 
248  auto predicate = &jlm::rvsdg::GraphImport::Create(rvsdg, ControlType::Create(2), "");
249  auto v0 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
250  auto v1 = &jlm::rvsdg::GraphImport::Create(rvsdg, vt, "");
251 
252  auto gammaNode = GammaNode::create(predicate, 2);
253  auto gammaInput0 = gammaNode->AddEntryVar(v0);
254  auto gammaInput1 = gammaNode->AddEntryVar(v1);
255  auto gammaInput2 = gammaNode->AddEntryVar(v1);
256 
257  auto gammaOutput0 = gammaNode->AddExitVar(gammaInput0.branchArgument);
258  auto gammaOutput1 =
259  gammaNode->AddExitVar({ gammaInput1.branchArgument[0], gammaInput2.branchArgument[1] });
260  auto gammaOutput2 =
261  gammaNode->AddExitVar({ gammaInput0.branchArgument[0], gammaInput2.branchArgument[1] });
262 
263  // Act & Assert
264  std::optional<jlm::rvsdg::Output *> invariantOrigin;
265  invariantOrigin = jlm::rvsdg::GetGammaInvariantOrigin(*gammaNode, gammaOutput0);
266  EXPECT_NE(invariantOrigin, nullptr);
267  EXPECT_EQ(*invariantOrigin, v0);
268 
269  invariantOrigin = jlm::rvsdg::GetGammaInvariantOrigin(*gammaNode, gammaOutput1);
270  EXPECT_NE(invariantOrigin, nullptr);
271  EXPECT_EQ(*invariantOrigin, v1);
272 
273  invariantOrigin = jlm::rvsdg::GetGammaInvariantOrigin(*gammaNode, gammaOutput2);
274  EXPECT_EQ(invariantOrigin, std::nullopt);
275 }
static const auto vt
Definition: PullTests.cpp:16
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
static Output & createTrue(Region &region)
Definition: control.hpp:140
static Output & create(Region &region, ControlValueRepresentation value)
Definition: control.hpp:122
static Output & createFalse(Region &region)
Definition: control.hpp:134
static std::shared_ptr< const ControlType > Create(std::size_t nalternatives)
Instantiates control type.
Definition: control.cpp:50
Conditional operator / pattern matching.
Definition: gamma.hpp:99
static GammaNode * create(jlm::rvsdg::Output *predicate, size_t nalternatives)
Definition: gamma.hpp:161
static GraphExport & Create(Output &origin, std::string name)
Definition: graph.cpp:62
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Definition: graph.cpp:36
void PruneNodes()
Definition: graph.hpp:116
Region & GetRootRegion() const noexcept
Definition: graph.hpp:99
static Node & CreateNode(Output &predicate, const std::unordered_map< uint64_t, uint64_t > &mapping, const uint64_t defaultAlternative, const size_t numAlternatives)
Definition: control.hpp:226
size_t numNodes() const noexcept
Definition: region.hpp:481
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
TEST(GammaConversionTests, TestWithMatch)
Definition: GammaTests.cpp:18
bool ReduceGammaControlConstant(Node &node)
Definition: gamma.cpp:171
bool ReduceGammaWithStaticallyKnownPredicate(Node &node)
Definition: gamma.cpp:158
std::string view(const rvsdg::Region *region)
Definition: view.cpp:142
std::optional< rvsdg::Output * > GetGammaInvariantOrigin(const GammaNode &gamma, const GammaNode::ExitVar &exitvar)
Determines whether a gamma exit var is path-invariant.
Definition: gamma.cpp:509
bool ReduceGammaInvariantVariables(Node &node)
Definition: gamma.cpp:186