Jlm
StoreTests.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2017 Nico Reißmann <nico.reissmann@gmail.com>
3  * See COPYING for terms of redistribution.
4  */
5 
6 #include <gtest/gtest.h>
7 
14 #include <jlm/rvsdg/gamma.hpp>
17 #include <jlm/rvsdg/TestType.hpp>
18 #include <jlm/rvsdg/view.hpp>
19 
20 TEST(StoreOperationTests, StoreNonVolatileOperationEquality)
21 {
22  using namespace jlm::llvm;
23  using namespace jlm::rvsdg;
24 
25  // Arrange
26  MemoryStateType memoryType;
27  auto valueType = jlm::rvsdg::TestType::createValueType();
28  auto pointerType = PointerType::Create();
29 
30  StoreNonVolatileOperation operation1(valueType, 2, 4);
31  StoreNonVolatileOperation operation2(pointerType, 2, 4);
32  StoreNonVolatileOperation operation3(valueType, 4, 4);
33  StoreNonVolatileOperation operation4(valueType, 2, 8);
34  TestOperation operation5({ PointerType::Create() }, { PointerType::Create() });
35 
36  // Act & Assert
37  EXPECT_EQ(operation1, operation1);
38  EXPECT_NE(operation1, operation2); // stored type differs
39  EXPECT_NE(operation1, operation3); // number of memory states differs
40  EXPECT_NE(operation1, operation4); // alignment differs
41  EXPECT_NE(operation1, operation5); // operation differs
42 }
43 
44 TEST(StoreOperationTests, StoreVolatileOperationEquality)
45 {
46  using namespace jlm::llvm;
47  using namespace jlm::rvsdg;
48 
49  // Arrange
50  MemoryStateType memoryType;
51  auto valueType = jlm::rvsdg::TestType::createValueType();
52  auto pointerType = PointerType::Create();
53 
54  StoreVolatileOperation operation1(valueType, 2, 4);
55  StoreVolatileOperation operation2(pointerType, 2, 4);
56  StoreVolatileOperation operation3(valueType, 4, 4);
57  StoreVolatileOperation operation4(valueType, 2, 8);
58  TestOperation operation5({ PointerType::Create() }, { PointerType::Create() });
59 
60  // Assert
61  EXPECT_EQ(operation1, operation1);
62  EXPECT_NE(operation1, operation2); // stored type differs
63  EXPECT_NE(operation1, operation3); // number of memory states differs
64  EXPECT_NE(operation1, operation4); // alignment differs
65  EXPECT_NE(operation1, operation5); // operation differs
66 }
67 
68 TEST(StoreOperationTests, StoreVolatileOperationCopy)
69 {
70  using namespace jlm::llvm;
71 
72  // Arrange
73  MemoryStateType memoryType;
74  auto valueType = jlm::rvsdg::TestType::createValueType();
75  PointerType pointerType;
76 
77  StoreVolatileOperation operation(valueType, 2, 4);
78 
79  // Act
80  auto copiedOperation = operation.copy();
81 
82  // Assert
83  EXPECT_EQ(*copiedOperation, operation);
84 }
85 
86 TEST(StoreOperationTests, StoreVolatileOperationAccessors)
87 {
88  using namespace jlm::llvm;
89 
90  // Arrange
91  MemoryStateType memoryType;
92  auto valueType = jlm::rvsdg::TestType::createValueType();
93  PointerType pointerType;
94 
95  size_t alignment = 4;
96  size_t numMemoryStates = 2;
97  StoreVolatileOperation operation(valueType, numMemoryStates, alignment);
98 
99  // Assert
100  EXPECT_EQ(operation.GetStoredType(), *valueType);
101  EXPECT_EQ(operation.NumMemoryStates(), numMemoryStates);
102  EXPECT_EQ(operation.GetAlignment(), alignment);
103  EXPECT_EQ(
104  operation.narguments(),
105  numMemoryStates + 3); // [address, storedValue, ioState, memoryStates]
106  EXPECT_EQ(operation.nresults(), numMemoryStates + 1); // [ioState, memoryStates]
107 }
108 
109 TEST(StoreOperationTests, StoreVolatileNodeCopy)
110 {
111  using namespace jlm::llvm;
112 
113  // Arrange
114  auto pointerType = PointerType::Create();
115  auto ioStateType = IOStateType::Create();
116  auto memoryType = MemoryStateType::Create();
117  auto valueType = jlm::rvsdg::TestType::createValueType();
118 
119  jlm::rvsdg::Graph graph;
120  auto & address1 = jlm::rvsdg::GraphImport::Create(graph, pointerType, "address1");
121  auto & value1 = jlm::rvsdg::GraphImport::Create(graph, valueType, "value1");
122  auto & ioState1 = jlm::rvsdg::GraphImport::Create(graph, ioStateType, "ioState1");
123  auto & memoryState1 = jlm::rvsdg::GraphImport::Create(graph, memoryType, "memoryState1");
124 
125  auto & address2 = jlm::rvsdg::GraphImport::Create(graph, pointerType, "address2");
126  auto & value2 = jlm::rvsdg::GraphImport::Create(graph, valueType, "value2");
127  auto & ioState2 = jlm::rvsdg::GraphImport::Create(graph, ioStateType, "ioState2");
128  auto & memoryState2 = jlm::rvsdg::GraphImport::Create(graph, memoryType, "memoryState2");
129 
130  auto & storeNode =
131  StoreVolatileOperation::CreateNode(address1, value1, ioState1, { &memoryState1 }, 4);
132 
133  // Act
134  auto copiedNode =
135  storeNode.copy(&graph.GetRootRegion(), { &address2, &value2, &ioState2, &memoryState2 });
136 
137  // Assert
138  EXPECT_EQ(storeNode.GetOperation(), storeNode.GetOperation());
139  EXPECT_EQ(StoreOperation::AddressInput(*copiedNode).origin(), &address2);
140  EXPECT_EQ(StoreOperation::StoredValueInput(*copiedNode).origin(), &value2);
141  EXPECT_EQ(StoreVolatileOperation::IOStateInput(*copiedNode).origin(), &ioState2);
142  EXPECT_EQ(*StoreVolatileOperation::IOStateOutput(*copiedNode).Type(), *ioStateType);
143 }
144 
145 TEST(StoreOperationTests, TestCopy)
146 {
147  using namespace jlm::llvm;
148 
149  auto valueType = jlm::rvsdg::TestType::createValueType();
150  auto pointerType = PointerType::Create();
151  auto memoryStateType = MemoryStateType::Create();
152 
153  jlm::rvsdg::Graph graph;
154  auto address1 = &jlm::rvsdg::GraphImport::Create(graph, pointerType, "address1");
155  auto value1 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value1");
156  auto memoryState1 = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "state1");
157 
158  auto address2 = &jlm::rvsdg::GraphImport::Create(graph, pointerType, "address2");
159  auto value2 = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value2");
160  auto memoryState2 = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "state2");
161 
162  auto storeResults = StoreNonVolatileOperation::Create(address1, value1, { memoryState1 }, 4);
163 
164  // Act
165  auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*storeResults[0]);
166  auto copiedNode = node->copy(&graph.GetRootRegion(), { address2, value2, memoryState2 });
167 
168  // Assert
169  EXPECT_EQ(
170  node->GetOperation(),
171  jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(copiedNode)->GetOperation());
172 }
173 
174 TEST(StoreOperationTests, TestStoreMuxNormalization)
175 {
176  using namespace jlm::llvm;
177  using namespace jlm::rvsdg;
178 
179  // Arrange
180  auto vt = TestType::createValueType();
181  auto pt = PointerType::Create();
182  auto mt = MemoryStateType::Create();
183 
184  jlm::rvsdg::Graph graph;
185  auto a = &jlm::rvsdg::GraphImport::Create(graph, pt, "a");
186  auto v = &jlm::rvsdg::GraphImport::Create(graph, vt, "v");
187  auto s1 = &jlm::rvsdg::GraphImport::Create(graph, mt, "s1");
188  auto s2 = &jlm::rvsdg::GraphImport::Create(graph, mt, "s2");
189  auto s3 = &jlm::rvsdg::GraphImport::Create(graph, mt, "s3");
190 
191  auto mux = MemoryStateMergeOperation::Create({ s1, s2, s3 });
192  auto & storeNode = StoreNonVolatileOperation::CreateNode(*a, *v, { mux }, 4);
193 
194  auto & ex = GraphExport::Create(*storeNode.output(0), "s");
195 
196  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
197 
198  // Act
199  auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
201  storeNode);
202  graph.PruneNodes();
203 
204  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
205 
206  // Assert
207  EXPECT_TRUE(success);
208  auto muxNode = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex.origin());
209  EXPECT_TRUE(is<MemoryStateMergeOperation>(muxNode));
210  EXPECT_EQ(muxNode->ninputs(), 3u);
211  auto n0 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*muxNode->input(0)->origin());
212  auto n1 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*muxNode->input(1)->origin());
213  auto n2 = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*muxNode->input(2)->origin());
214  EXPECT_TRUE(jlm::rvsdg::is<StoreNonVolatileOperation>(n0->GetOperation()));
215  EXPECT_TRUE(jlm::rvsdg::is<StoreNonVolatileOperation>(n1->GetOperation()));
216  EXPECT_TRUE(jlm::rvsdg::is<StoreNonVolatileOperation>(n2->GetOperation()));
217 }
218 
219 TEST(StoreOperationTests, TestDuplicateStateReduction)
220 {
221  using namespace jlm::llvm;
222  using namespace jlm::rvsdg;
223 
224  // Arrange
225  auto valueType = TestType::createValueType();
226  auto pointerType = PointerType::Create();
227  auto memoryStateType = MemoryStateType::Create();
228 
229  jlm::rvsdg::Graph graph;
230  auto a = &jlm::rvsdg::GraphImport::Create(graph, pointerType, "a");
231  auto v = &jlm::rvsdg::GraphImport::Create(graph, valueType, "v");
232  auto s1 = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "s1");
233  auto s2 = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "s2");
234  auto s3 = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "s3");
235 
236  auto & storeNode = StoreNonVolatileOperation::CreateNode(*a, *v, { s1, s2, s1, s2, s3 }, 4);
237 
238  auto & exS1 = GraphExport::Create(*storeNode.output(0), "exS1");
239  auto & exS2 = GraphExport::Create(*storeNode.output(1), "exS2");
240  auto & exS3 = GraphExport::Create(*storeNode.output(2), "exS3");
241  auto & exS4 = GraphExport::Create(*storeNode.output(3), "exS4");
242  auto & exS5 = GraphExport::Create(*storeNode.output(4), "exS5");
243 
244  view(&graph.GetRootRegion(), stdout);
245 
246  // Act
247  auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
249  storeNode);
250  graph.PruneNodes();
251 
252  view(&graph.GetRootRegion(), stdout);
253 
254  // Assert
255  EXPECT_TRUE(success);
256  auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*exS1.origin());
257  EXPECT_TRUE(is<StoreNonVolatileOperation>(node));
258  EXPECT_EQ(node->ninputs(), 5u);
259  EXPECT_EQ(node->noutputs(), 3u);
260  EXPECT_EQ(exS1.origin(), node->output(0));
261  EXPECT_EQ(exS2.origin(), node->output(1));
262  EXPECT_EQ(exS3.origin(), node->output(0));
263  EXPECT_EQ(exS4.origin(), node->output(1));
264  EXPECT_EQ(exS5.origin(), node->output(2));
265 }
266 
267 TEST(StoreOperationTests, TestStoreAllocaReduction)
268 {
269  using namespace jlm::llvm;
270  using namespace jlm::rvsdg;
271 
272  // Arrange
273  auto vt = TestType::createValueType();
274  auto mt = MemoryStateType::Create();
275  auto bt = jlm::rvsdg::BitType::Create(32);
276 
277  jlm::rvsdg::Graph graph;
278  auto size = &jlm::rvsdg::GraphImport::Create(graph, bt, "size");
279  auto value = &jlm::rvsdg::GraphImport::Create(graph, vt, "value");
280  auto s = &jlm::rvsdg::GraphImport::Create(graph, mt, "s");
281 
282  auto alloca1 = AllocaOperation::create(vt, size, 4);
283  auto alloca2 = AllocaOperation::create(vt, size, 4);
284  auto & storeNode1 =
285  StoreNonVolatileOperation::CreateNode(*alloca1[0], *value, { alloca1[1], alloca2[1], s }, 4);
286  auto & storeNode2 =
287  StoreNonVolatileOperation::CreateNode(*alloca2[0], *value, outputs(&storeNode1), 4);
288 
289  GraphExport::Create(*storeNode2.output(0), "s1");
290  GraphExport::Create(*storeNode2.output(1), "s2");
291  GraphExport::Create(*storeNode2.output(2), "s3");
292 
293  view(&graph.GetRootRegion(), stdout);
294 
295  // Act
296  auto success1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
298  storeNode1);
299  auto success2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
301  storeNode2);
302  graph.PruneNodes();
303 
304  view(&graph.GetRootRegion(), stdout);
305 
306  // Assert
307  EXPECT_TRUE(success1 && success2);
308  bool has_add_import = false;
309  for (size_t n = 0; n < graph.GetRootRegion().nresults(); n++)
310  {
311  if (graph.GetRootRegion().result(n)->origin() == s)
312  has_add_import = true;
313  }
314  EXPECT_TRUE(has_add_import);
315 }
316 
317 TEST(StoreOperationTests, TestStoreStoreReduction)
318 {
319  using namespace jlm::llvm;
320  using namespace jlm::rvsdg;
321 
322  // Arrange
323  auto int64 = BitType::Create(64);
324  auto pt = PointerType::Create();
325  auto mt = MemoryStateType::Create();
326 
327  jlm::rvsdg::Graph graph;
328  auto a = &jlm::rvsdg::GraphImport::Create(graph, pt, "address");
329  auto v1 = &jlm::rvsdg::GraphImport::Create(graph, int64, "value");
330  auto v2 = &jlm::rvsdg::GraphImport::Create(graph, int64, "value");
331  auto s = &jlm::rvsdg::GraphImport::Create(graph, mt, "state");
332 
333  auto & storeNode1 = StoreNonVolatileOperation::CreateNode(*a, *v1, { s }, 4);
334  auto & storeNode2 = StoreNonVolatileOperation::CreateNode(*a, *v2, outputs(&storeNode1), 4);
335 
336  auto & ex = GraphExport::Create(*storeNode2.output(0), "state");
337 
338  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
339 
340  // Act
341  auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
343  storeNode2);
344  graph.PruneNodes();
345 
346  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
347 
348  // Assert
349  EXPECT_TRUE(success);
350  EXPECT_EQ(graph.GetRootRegion().numNodes(), 1u);
351  EXPECT_EQ(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex.origin())->input(1)->origin(), v2);
352 }
353 
354 TEST(StoreOperationTests, IOBarrierAllocaAddressNormalization)
355 {
356  using namespace jlm::llvm;
357  using namespace jlm::rvsdg;
358 
359  // Arrange
360  const auto valueType = TestType::createValueType();
361  const auto pointerType = PointerType::Create();
362  const auto memoryStateType = MemoryStateType::Create();
363  const auto bit32Type = jlm::rvsdg::BitType::Create(32);
364  const auto ioStateType = IOStateType::Create();
365 
366  jlm::rvsdg::Graph graph;
367  const auto addressImport = &jlm::rvsdg::GraphImport::Create(graph, pointerType, "address");
368  const auto valueImport = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value");
369  const auto sizeImport = &jlm::rvsdg::GraphImport::Create(graph, bit32Type, "value");
370  auto memoryStateImport = &jlm::rvsdg::GraphImport::Create(graph, memoryStateType, "memState");
371  auto ioStateImport = &jlm::rvsdg::GraphImport::Create(graph, ioStateType, "ioState");
372 
373  auto allocaResults = AllocaOperation::create(valueType, sizeImport, 4);
374  auto & ioBarrierNode = jlm::rvsdg::CreateOpNode<IOBarrierOperation>(
375  { allocaResults[0], ioStateImport },
376  pointerType);
377 
378  auto & storeNode1 = StoreNonVolatileOperation::CreateNode(
379  *ioBarrierNode.output(0),
380  *valueImport,
381  { allocaResults[1] },
382  4);
383 
384  auto & storeNode2 =
385  StoreNonVolatileOperation::CreateNode(*addressImport, *valueImport, { memoryStateImport }, 4);
386 
387  auto & ex1 = GraphExport::Create(*storeNode1.output(0), "store1");
388  auto & ex2 = GraphExport::Create(*storeNode2.output(0), "store2");
389 
390  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
391 
392  // Act
393  const auto successStoreNode1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
395  storeNode1);
396 
397  const auto successStoreNode2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
399  storeNode2);
400  graph.PruneNodes();
401 
402  jlm::rvsdg::view(&graph.GetRootRegion(), stdout);
403 
404  // Assert
405  EXPECT_TRUE(successStoreNode1);
406  EXPECT_EQ(
407  jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex1.origin())->input(0)->origin(),
408  allocaResults[0]);
409 
410  // There is no IOBarrierOperation node as producer for the store address. We expect the
411  // normalization not to trigger.
412  EXPECT_FALSE(successStoreNode2);
413  EXPECT_EQ(
414  jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex2.origin())->input(0)->origin(),
415  addressImport);
416 }
417 
418 TEST(StoreOperationTests, IOBarrierAllocaAddressNormalization_Gamma)
419 {
420  using namespace jlm::llvm;
421  using namespace jlm::rvsdg;
422 
423  // Arrange
424  const auto valueType = TestType::createValueType();
425  const auto pointerType = PointerType::Create();
426  const auto bit32Type = jlm::rvsdg::BitType::Create(32);
427  const auto ioStateType = IOStateType::Create();
428  const auto controlTye = ControlType::Create(2);
429 
430  Graph graph;
431  const auto valueImport = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value");
432  const auto sizeImport = &jlm::rvsdg::GraphImport::Create(graph, bit32Type, "value");
433  auto ioStateImport = &jlm::rvsdg::GraphImport::Create(graph, ioStateType, "ioState");
434  const auto controlImport = &jlm::rvsdg::GraphImport::Create(graph, controlTye, "control");
435 
436  auto allocaResults = AllocaOperation::create(valueType, sizeImport, 4);
437 
438  auto gammaNode = GammaNode::create(controlImport, 2);
439  auto addressEntryVar = gammaNode->AddEntryVar(allocaResults[0]);
440  auto memoryStateEntryVar = gammaNode->AddEntryVar(allocaResults[1]);
441  auto ioStateEntryVar = gammaNode->AddEntryVar(ioStateImport);
442  auto valueEntryVar = gammaNode->AddEntryVar(valueImport);
443 
444  auto & ioBarrierNode = jlm::rvsdg::CreateOpNode<IOBarrierOperation>(
445  { addressEntryVar.branchArgument[0], ioStateEntryVar.branchArgument[0] },
446  pointerType);
447 
448  auto & storeNode = StoreNonVolatileOperation::CreateNode(
449  *ioBarrierNode.output(0),
450  *valueEntryVar.branchArgument[0],
451  { memoryStateEntryVar.branchArgument[0] },
452  4);
453 
454  auto exitVar =
455  gammaNode->AddExitVar({ storeNode.output(0), memoryStateEntryVar.branchArgument[1] });
456 
457  GraphExport::Create(*exitVar.output, "store");
458 
459  view(&graph.GetRootRegion(), stdout);
460 
461  // Act
462  const auto successStoreNode = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
464  storeNode);
465  graph.PruneNodes();
466 
467  view(&graph.GetRootRegion(), stdout);
468 
469  // Assert
470  EXPECT_TRUE(successStoreNode);
471  // There should only be the store node left.
472  // The IOBarrier node should have been pruned.
473  EXPECT_EQ(gammaNode->subregion(0)->numNodes(), 1u);
474  EXPECT_EQ(
475  jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*exitVar.branchResult[0]->origin())
476  ->input(0)
477  ->origin(),
478  addressEntryVar.branchArgument[0]);
479 }
480 
481 TEST(StoreOperationTests, storeAllocaSingleUser)
482 {
483  using namespace jlm::llvm;
484  using namespace jlm::rvsdg;
485 
486  // Arrange
487  const auto valueType = TestType::createValueType();
488  const auto bit32Type = BitType::Create(32);
489 
490  Graph graph;
491  const auto valueImport = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value");
492  const auto sizeImport = &jlm::rvsdg::GraphImport::Create(graph, bit32Type, "value");
493 
494  auto allocaResults = AllocaOperation::create(valueType, sizeImport, 4);
495 
496  auto & storeNode = StoreNonVolatileOperation::CreateNode(
497  *allocaResults[0],
498  *valueImport,
499  { allocaResults[1] },
500  4);
501 
502  auto & x1 = GraphExport::Create(*storeNode.output(0), "store");
503 
504  view(&graph.GetRootRegion(), stdout);
505 
506  // Act
507  const auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
509  storeNode);
510 
511  graph.PruneNodes();
512 
513  view(&graph.GetRootRegion(), stdout);
514 
515  // Assert
516  EXPECT_TRUE(success);
517  EXPECT_EQ(x1.origin(), allocaResults[1]);
518 }
519 
520 TEST(StoreOperationTests, storeAllocaSingleUser_MultipleUsers)
521 {
522  using namespace jlm::llvm;
523  using namespace jlm::rvsdg;
524 
525  // Arrange
526  const auto valueType = TestType::createValueType();
527  const auto bit32Type = BitType::Create(32);
528 
529  Graph graph;
530  const auto valueImport = &jlm::rvsdg::GraphImport::Create(graph, valueType, "value");
531  const auto sizeImport = &jlm::rvsdg::GraphImport::Create(graph, bit32Type, "value");
532 
533  auto allocaResults = AllocaOperation::create(valueType, sizeImport, 4);
534 
535  auto & storeNode1 = StoreNonVolatileOperation::CreateNode(
536  *allocaResults[0],
537  *valueImport,
538  { allocaResults[1] },
539  4);
540 
541  auto & storeNode2 = StoreNonVolatileOperation::CreateNode(
542  *allocaResults[0],
543  *valueImport,
544  { storeNode1.output(0) },
545  4);
546 
547  auto & x1 = GraphExport::Create(*storeNode1.output(0), "store1");
548  auto & x2 = GraphExport::Create(*storeNode2.output(0), "store2");
549 
550  view(&graph.GetRootRegion(), stdout);
551 
552  // Act
553  const auto successStoreNode1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
555  storeNode1);
556  const auto successStoreNode2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
558  storeNode2);
559 
560  graph.PruneNodes();
561 
562  view(&graph.GetRootRegion(), stdout);
563 
564  // Assert
565  EXPECT_FALSE(successStoreNode1);
566  EXPECT_FALSE(successStoreNode2);
567  EXPECT_EQ(x1.origin(), storeNode1.output(0));
568  EXPECT_EQ(x2.origin(), storeNode2.output(0));
569 }
static const auto vt
Definition: PullTests.cpp:16
static std::vector< rvsdg::Output * > create(std::shared_ptr< const rvsdg::Type > allocatedType, rvsdg::Output *count, const size_t alignment)
Definition: alloca.hpp:131
static std::shared_ptr< const IOStateType > Create()
Definition: types.cpp:343
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
Memory state type class.
Definition: types.hpp:477
static std::shared_ptr< const MemoryStateType > Create()
Definition: types.cpp:379
PointerType class.
Definition: types.hpp:25
static std::shared_ptr< const PointerType > Create()
Definition: types.cpp:45
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
Definition: Store.hpp:304
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
Definition: Store.hpp:323
static std::optional< std::vector< rvsdg::Output * > > NormalizeIOBarrierAllocaAddress(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the StoreNonVolatileOperation from an IOBarrierOperation when it can ...
Definition: Store.cpp:254
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreMux(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Swaps a memory state merge operation and a store operation.
Definition: Store.cpp:210
static std::optional< std::vector< rvsdg::Output * > > normalizeStoreAllocaSingleUser(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Definition: Store.cpp:282
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreAlloca(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes unnecessary state from a store node when its address originates directly from an alloca node.
Definition: Store.cpp:232
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreStore(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes a duplicated store to the same address.
Definition: Store.cpp:221
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateStates(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
Definition: Store.cpp:243
const rvsdg::Type & GetStoredType() const noexcept
Definition: Store.hpp:63
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
Definition: Store.hpp:84
size_t GetAlignment() const noexcept
Definition: Store.hpp:57
size_t NumMemoryStates() const noexcept
Definition: Store.hpp:69
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Definition: Store.hpp:75
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node) noexcept
Definition: Store.hpp:430
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< StoreVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
Definition: Store.hpp:453
std::unique_ptr< Operation > copy() const override
Definition: Store.cpp:322
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
Definition: Store.hpp:421
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
Definition: type.cpp:45
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
Output * origin() const noexcept
Definition: node.hpp:58
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Definition: node.hpp:366
RegionResult * result(size_t index) const noexcept
Definition: region.hpp:471
size_t numNodes() const noexcept
Definition: region.hpp:481
Node * copy(Region *region, const std::vector< Output * > &operands) const override
Definition: simple-node.cpp:54
size_t nresults() const noexcept
Definition: operation.cpp:30
size_t narguments() const noexcept
Definition: operation.cpp:17
static std::shared_ptr< const TestType > createValueType()
Definition: TestType.cpp:67
TEST(StoreTests, StoreConversion)
Definition: StoreTests.cpp:17
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
Definition: view.cpp:142
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
Definition: node.hpp:1058