Jlm
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 
10 #include <jlm/rvsdg/TestType.hpp>
11 #include <jlm/rvsdg/view.hpp>
12 
14 {
15 public:
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),
21  Flags_(flags)
22  {}
23 
26  const noexcept override
27  {
28  auto n1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*operand1);
29  auto n2 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*operand2);
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 
79 private:
81 };
82 
83 TEST(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
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 
124 TEST(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
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 
166 TEST(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 
204 TEST(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 
238 TEST(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 
278 TEST(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 
309 TEST(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)
Definition: BinaryTests.cpp:83
std::string debug_string() const override
Definition: BinaryTests.cpp:68
std::unique_ptr< Operation > copy() const override
Definition: BinaryTests.cpp:74
enum jlm::rvsdg::BinaryOperation::flags flags() const noexcept override
Definition: BinaryTests.cpp:56
enum jlm::rvsdg::BinaryOperation::flags Flags_
Definition: BinaryTests.cpp:80
jlm::rvsdg::Output * reduce_operand_pair(jlm::rvsdg::unop_reduction_path_t path, jlm::rvsdg::Output *, jlm::rvsdg::Output *op2) const override
Definition: BinaryTests.cpp:41
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)
Definition: BinaryTests.cpp:16
bool operator==(const Operation &) const noexcept override
Definition: BinaryTests.cpp:62
jlm::rvsdg::binop_reduction_path_t can_reduce_operand_pair(const jlm::rvsdg::Output *operand1, const jlm::rvsdg::Output *operand2) const noexcept override
Definition: BinaryTests.cpp:25
jlm::rvsdg::Output * reduce(const FlattenedBinaryOperation::reduction &reduction, const std::vector< jlm::rvsdg::Output * > &operands) const
Definition: binary.cpp:209
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
size_t numNodes() const noexcept
Definition: region.hpp:481
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
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
#define JLM_UNREACHABLE(msg)
Definition: common.hpp:43
size_t unop_reduction_path_t
Definition: unary.hpp:18
std::optional< std::vector< rvsdg::Output * > > NormalizeBinaryOperation(const BinaryOperation &operation, const std::vector< rvsdg::Output * > &operands)
Applies the reductions implemented in the binary operations reduction functions.
Definition: binary.cpp:112
size_t binop_reduction_path_t
Definition: binary.hpp:19
std::string view(const rvsdg::Region *region)
Definition: view.cpp:142
std::optional< std::vector< rvsdg::Output * > > FlattenAssociativeBinaryOperation(const BinaryOperation &operation, const std::vector< rvsdg::Output * > &operands)
Flattens a cascade of the same binary operations into a single flattened binary operation.
Definition: binary.cpp:64