Jlm
Loading...
Searching...
No Matches
BinaryTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 Nico Reißmann <nico.reissmann@gmail.com>
3 * See COPYING for terms of redistribution.
4 */
5
6#include <gtest/gtest.h>
7
11#include <jlm/rvsdg/view.hpp>
12
14{
15public:
17 const std::shared_ptr<const jlm::rvsdg::Type> operandType,
18 const std::shared_ptr<const jlm::rvsdg::Type> resultType,
20 : jlm::rvsdg::BinaryOperation({ operandType, operandType }, resultType),
22 {}
23
26 const noexcept override
27 {
30
31 if (n1 && n2 && jlm::rvsdg::is<jlm::rvsdg::UnaryOperation>(n1->GetOperation())
32 && jlm::rvsdg::is<jlm::rvsdg::UnaryOperation>(n2->GetOperation()))
33 {
34 return 1;
35 }
36
37 return 0;
38 }
39
44 jlm::rvsdg::Output * op2) const override
45 {
46
47 if (path == 1)
48 {
49 return op2;
50 }
51
52 return nullptr;
53 }
54
55 [[nodiscard]] enum jlm::rvsdg::BinaryOperation::flags
56 flags() const noexcept override
57 {
58 return Flags_;
59 }
60
61 bool
62 operator==(const Operation &) const noexcept override
63 {
64 JLM_UNREACHABLE("Not implemented.");
65 }
66
67 [[nodiscard]] std::string
68 debug_string() const override
69 {
70 return "BinaryOperation";
71 }
72
73 [[nodiscard]] std::unique_ptr<Operation>
74 copy() const override
75 {
76 return std::make_unique<BinaryOperation>(this->argument(0), this->result(0), Flags_);
77 }
78
79private:
81};
82
83TEST(BinaryOperationTests, ReduceFlattenedBinaryReductionParallel)
84{
85 using namespace jlm::rvsdg;
86
87 // Arrange
88 const auto valueType = TestType::createValueType();
89 const TestBinaryOperation binaryOperation(
90 valueType,
91 valueType,
93
94 Graph graph;
95 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
96 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
97 auto i2 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
98 auto i3 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
99
100 auto & node = CreateOpNode<FlattenedBinaryOperation>({ i0, i1, i2, i3 }, binaryOperation, 4);
101
102 auto & ex = GraphExport::Create(*node.output(0), "");
103
104 view(graph, stdout);
105
106 // Act
107 FlattenedBinaryOperation::reduce(&graph, FlattenedBinaryOperation::reduction::parallel);
108 graph.PruneNodes();
109 view(graph, stdout);
110
111 // Assert
112 EXPECT_EQ(graph.GetRootRegion().numNodes(), 3u);
113
114 auto node0 = TryGetOwnerNode<SimpleNode>(*ex.origin());
115 EXPECT_TRUE(is<TestBinaryOperation>(node0->GetOperation()));
116
117 auto node1 = TryGetOwnerNode<SimpleNode>(*node0->input(0)->origin());
118 EXPECT_TRUE(is<TestBinaryOperation>(node1->GetOperation()));
119
120 auto node2 = TryGetOwnerNode<SimpleNode>(*node0->input(1)->origin());
121 EXPECT_TRUE(is<TestBinaryOperation>(node2->GetOperation()));
122}
123
124TEST(BinaryOperationTests, ReduceFlattenedBinaryReductionLinear)
125{
126 using namespace jlm::rvsdg;
127
128 // Arrange
129 const auto valueType = TestType::createValueType();
130 const TestBinaryOperation binaryOperation(
131 valueType,
132 valueType,
134
135 Graph graph;
136 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
137 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
138 auto i2 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
139 auto i3 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "");
140
141 auto & node = CreateOpNode<FlattenedBinaryOperation>({ i0, i1, i2, i3 }, binaryOperation, 4);
142
143 auto & ex = GraphExport::Create(*node.output(0), "");
144
145 view(graph, stdout);
146
147 // Act
148 FlattenedBinaryOperation::reduce(&graph, FlattenedBinaryOperation::reduction::linear);
149 graph.PruneNodes();
150
151 view(graph, stdout);
152
153 // Assert
154 EXPECT_EQ(graph.GetRootRegion().numNodes(), 3u);
155
156 auto node0 = TryGetOwnerNode<SimpleNode>(*ex.origin());
157 EXPECT_TRUE(is<TestBinaryOperation>(node0->GetOperation()));
158
159 auto node1 = TryGetOwnerNode<SimpleNode>(*node0->input(0)->origin());
160 EXPECT_TRUE(is<TestBinaryOperation>(node1->GetOperation()));
161
162 auto node2 = TryGetOwnerNode<SimpleNode>(*node1->input(0)->origin());
163 EXPECT_TRUE(is<TestBinaryOperation>(node2->GetOperation()));
164}
165
166TEST(BinaryOperationTests, FlattenAssociativeBinaryOperation_NotAssociativeBinary)
167{
168 using namespace jlm::rvsdg;
169
170 // Arrange
171 auto valueType = TestType::createValueType();
172
173 Graph graph;
174 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i0");
175 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i1");
176 auto i2 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i2");
177
178 auto o1 = &CreateOpNode<TestBinaryOperation>(
179 { i0, i1 },
180 valueType,
181 valueType,
183 auto o2 = &CreateOpNode<TestBinaryOperation>(
184 { o1->output(0), i2 },
185 valueType,
186 valueType,
188
189 auto & ex = GraphExport::Create(*o2->output(0), "o2");
190
191 jlm::rvsdg::view(graph, stdout);
192
193 // Act
194 auto node = TryGetOwnerNode<SimpleNode>(*ex.origin());
195 auto success = ReduceNode<TestBinaryOperation>(FlattenAssociativeBinaryOperation, *node);
196
197 jlm::rvsdg::view(graph, stdout);
198
199 // Assert
200 EXPECT_FALSE(success);
201 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*ex.origin()), node);
202}
203
204TEST(BinaryOperationTests, FlattenAssociativeBinaryOperation_NoNewOperands)
205{
206 using namespace jlm::rvsdg;
207
208 // Arrange
209 auto valueType = TestType::createValueType();
210
211 Graph graph;
212 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i0");
213 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i1");
214
215 auto u1 = &CreateOpNode<TestUnaryOperation>({ i0 }, valueType, valueType);
216 auto u2 = &CreateOpNode<TestUnaryOperation>({ i1 }, valueType, valueType);
217 auto b2 = &CreateOpNode<TestBinaryOperation>(
218 { u1->output(0), u2->output(0) },
219 valueType,
220 valueType,
222
223 auto & ex = GraphExport::Create(*b2->output(0), "o2");
224
225 jlm::rvsdg::view(graph, stdout);
226
227 // Act
228 auto node = TryGetOwnerNode<SimpleNode>(*ex.origin());
229 auto success = ReduceNode<TestBinaryOperation>(FlattenAssociativeBinaryOperation, *node);
230
231 jlm::rvsdg::view(graph, stdout);
232
233 // Assert
234 EXPECT_FALSE(success);
235 EXPECT_EQ(TryGetOwnerNode<SimpleNode>(*ex.origin()), node);
236}
237
238TEST(BinaryOperationTests, FlattenAssociativeBinaryOperation_Success)
239{
240 using namespace jlm::rvsdg;
241
242 // Arrange
243 auto valueType = TestType::createValueType();
244
245 Graph graph;
246 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i0");
247 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i1");
248 auto i2 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i2");
249
250 auto o1 = &CreateOpNode<TestBinaryOperation>(
251 { i0, i1 },
252 valueType,
253 valueType,
255 auto o2 = &CreateOpNode<TestBinaryOperation>(
256 { o1->output(0), i2 },
257 valueType,
258 valueType,
260
261 auto & ex = GraphExport::Create(*o2->output(0), "o2");
262
263 jlm::rvsdg::view(graph, stdout);
264
265 // Act
266 auto node = TryGetOwnerNode<SimpleNode>(*ex.origin());
267 auto success = ReduceNode<TestBinaryOperation>(FlattenAssociativeBinaryOperation, *node);
268
269 jlm::rvsdg::view(graph, stdout);
270
271 // Assert
272 EXPECT_TRUE(success);
273 auto flattenedBinaryNode = TryGetOwnerNode<SimpleNode>(*ex.origin());
274 EXPECT_TRUE(is<FlattenedBinaryOperation>(flattenedBinaryNode->GetOperation()));
275 EXPECT_EQ(flattenedBinaryNode->ninputs(), 3u);
276}
277
278TEST(BinaryOperationTests, NormalizeBinaryOperation_NoNewOperands)
279{
280 using namespace jlm::rvsdg;
281
282 // Arrange
283 auto valueType = TestType::createValueType();
284
285 Graph graph;
286 auto i0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i0");
287 auto i1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "i1");
288
289 auto o1 = &CreateOpNode<TestBinaryOperation>(
290 { i0, i1 },
291 valueType,
292 valueType,
294
295 auto & ex = GraphExport::Create(*o1->output(0), "o2");
296
297 jlm::rvsdg::view(graph, stdout);
298
299 // Act
300 auto node = TryGetOwnerNode<SimpleNode>(*ex.origin());
301 auto success = ReduceNode<TestBinaryOperation>(NormalizeBinaryOperation, *node);
302
303 jlm::rvsdg::view(graph, stdout);
304
305 // Assert
306 EXPECT_FALSE(success);
307}
308
309TEST(BinaryOperationTests, NormalizeBinaryOperation_SingleOperand)
310{
311 using namespace jlm::rvsdg;
312
313 // Arrange
314 auto valueType = TestType::createValueType();
315
316 Graph graph;
317 auto s0 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "s0");
318 auto s1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "s1");
319
320 auto u1 = &CreateOpNode<TestUnaryOperation>({ s0 }, valueType, valueType);
321 auto u2 = &CreateOpNode<TestUnaryOperation>({ s1 }, valueType, valueType);
322
323 auto o1 = &CreateOpNode<::BinaryOperation>(
324 { u1->output(0), u2->output(0) },
325 valueType,
326 valueType,
328
329 auto & ex = GraphExport::Create(*o1->output(0), "ex");
330
331 jlm::rvsdg::view(graph, stdout);
332
333 // Act
334 auto node = TryGetOwnerNode<SimpleNode>(*ex.origin());
335 auto success = ReduceNode<::BinaryOperation>(NormalizeBinaryOperation, *node);
336
337 jlm::rvsdg::view(graph, stdout);
338
339 // Assert
340 EXPECT_TRUE(success);
341 EXPECT_EQ(ex.origin(), u2->output(0));
342}
TEST(BinaryOperationTests, ReduceFlattenedBinaryReductionParallel)
std::string debug_string() const override
enum jlm::rvsdg::BinaryOperation::flags flags() const noexcept override
enum jlm::rvsdg::BinaryOperation::flags Flags_
std::unique_ptr< Operation > copy() const override
BinaryOperation(const std::shared_ptr< const jlm::rvsdg::Type > operandType, const std::shared_ptr< const jlm::rvsdg::Type > resultType, const enum jlm::rvsdg::BinaryOperation::flags &flags)
jlm::rvsdg::Output * reduce_operand_pair(jlm::rvsdg::binop_reduction_path_t path, jlm::rvsdg::Output *, jlm::rvsdg::Output *op2) const override
bool operator==(const Operation &) const noexcept override
jlm::rvsdg::binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *operand1, const jlm::rvsdg::Output *operand2) const noexcept override
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Definition graph.cpp:36
Region & GetRootRegion() const noexcept
Definition graph.hpp:99
void PruneNodes()
Definition graph.hpp:116
size_t numNodes() const noexcept
Definition region.hpp:510
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
Definition operation.cpp:23
const std::shared_ptr< const rvsdg::Type > & result(size_t index) const noexcept
Definition operation.cpp:36
#define JLM_UNREACHABLE(msg)
Definition common.hpp:43
size_t binop_reduction_path_t
Definition binary.hpp:19
std::string view(const rvsdg::Region *region)
Definition view.cpp:142
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.
Definition node.hpp:872