6 #include <gtest/gtest.h>
20 TEST(StoreOperationTests, StoreNonVolatileOperationEquality)
37 EXPECT_EQ(operation1, operation1);
38 EXPECT_NE(operation1, operation2);
39 EXPECT_NE(operation1, operation3);
40 EXPECT_NE(operation1, operation4);
41 EXPECT_NE(operation1, operation5);
44 TEST(StoreOperationTests, StoreVolatileOperationEquality)
61 EXPECT_EQ(operation1, operation1);
62 EXPECT_NE(operation1, operation2);
63 EXPECT_NE(operation1, operation3);
64 EXPECT_NE(operation1, operation4);
65 EXPECT_NE(operation1, operation5);
68 TEST(StoreOperationTests, StoreVolatileOperationCopy)
80 auto copiedOperation = operation.
copy();
83 EXPECT_EQ(*copiedOperation, operation);
86 TEST(StoreOperationTests, StoreVolatileOperationAccessors)
96 size_t numMemoryStates = 2;
105 numMemoryStates + 3);
106 EXPECT_EQ(operation.
nresults(), numMemoryStates + 1);
109 TEST(StoreOperationTests, StoreVolatileNodeCopy)
135 storeNode.
copy(&graph.
GetRootRegion(), { &address2, &value2, &ioState2, &memoryState2 });
138 EXPECT_EQ(storeNode.GetOperation(), storeNode.GetOperation());
145 TEST(StoreOperationTests, TestCopy)
165 auto node = jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::SimpleNode>(*storeResults[0]);
166 auto copiedNode = node->copy(&graph.
GetRootRegion(), { address2, value2, memoryState2 });
170 node->GetOperation(),
171 jlm::util::assertedCast<jlm::rvsdg::SimpleNode>(copiedNode)->GetOperation());
174 TEST(StoreOperationTests, TestStoreMuxNormalization)
180 auto vt = TestType::createValueType();
194 auto & ex = GraphExport::Create(*storeNode.output(0),
"s");
199 auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
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()));
219 TEST(StoreOperationTests, TestDuplicateStateReduction)
225 auto valueType = TestType::createValueType();
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");
247 auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
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));
267 TEST(StoreOperationTests, TestStoreAllocaReduction)
273 auto vt = TestType::createValueType();
289 GraphExport::Create(*storeNode2.output(0),
"s1");
290 GraphExport::Create(*storeNode2.output(1),
"s2");
291 GraphExport::Create(*storeNode2.output(2),
"s3");
296 auto success1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
299 auto success2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
307 EXPECT_TRUE(success1 && success2);
308 bool has_add_import =
false;
309 for (
size_t n = 0; n < graph.
GetRootRegion().nresults(); n++)
312 has_add_import =
true;
314 EXPECT_TRUE(has_add_import);
317 TEST(StoreOperationTests, TestStoreStoreReduction)
323 auto int64 = BitType::Create(64);
336 auto & ex = GraphExport::Create(*storeNode2.output(0),
"state");
341 auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
349 EXPECT_TRUE(success);
351 EXPECT_EQ(jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex.origin())->input(1)->origin(), v2);
354 TEST(StoreOperationTests, IOBarrierAllocaAddressNormalization)
360 const auto valueType = TestType::createValueType();
374 auto & ioBarrierNode = jlm::rvsdg::CreateOpNode<IOBarrierOperation>(
375 { allocaResults[0], ioStateImport },
379 *ioBarrierNode.output(0),
381 { allocaResults[1] },
387 auto & ex1 = GraphExport::Create(*storeNode1.output(0),
"store1");
388 auto & ex2 = GraphExport::Create(*storeNode2.output(0),
"store2");
393 const auto successStoreNode1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
397 const auto successStoreNode2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
405 EXPECT_TRUE(successStoreNode1);
407 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex1.origin())->input(0)->origin(),
412 EXPECT_FALSE(successStoreNode2);
414 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*ex2.origin())->input(0)->origin(),
418 TEST(StoreOperationTests, IOBarrierAllocaAddressNormalization_Gamma)
424 const auto valueType = TestType::createValueType();
428 const auto controlTye = ControlType::Create(2);
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);
444 auto & ioBarrierNode = jlm::rvsdg::CreateOpNode<IOBarrierOperation>(
445 { addressEntryVar.branchArgument[0], ioStateEntryVar.branchArgument[0] },
449 *ioBarrierNode.output(0),
450 *valueEntryVar.branchArgument[0],
451 { memoryStateEntryVar.branchArgument[0] },
455 gammaNode->AddExitVar({ storeNode.output(0), memoryStateEntryVar.branchArgument[1] });
457 GraphExport::Create(*exitVar.output,
"store");
462 const auto successStoreNode = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
470 EXPECT_TRUE(successStoreNode);
473 EXPECT_EQ(gammaNode->subregion(0)->numNodes(), 1u);
475 jlm::rvsdg::TryGetOwnerNode<jlm::rvsdg::Node>(*exitVar.branchResult[0]->origin())
478 addressEntryVar.branchArgument[0]);
481 TEST(StoreOperationTests, storeAllocaSingleUser)
487 const auto valueType = TestType::createValueType();
488 const auto bit32Type = BitType::Create(32);
499 { allocaResults[1] },
502 auto & x1 = GraphExport::Create(*storeNode.output(0),
"store");
507 const auto success = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
516 EXPECT_TRUE(success);
517 EXPECT_EQ(x1.origin(), allocaResults[1]);
520 TEST(StoreOperationTests, storeAllocaSingleUser_MultipleUsers)
526 const auto valueType = TestType::createValueType();
527 const auto bit32Type = BitType::Create(32);
538 { allocaResults[1] },
544 { storeNode1.output(0) },
547 auto & x1 = GraphExport::Create(*storeNode1.output(0),
"store1");
548 auto & x2 = GraphExport::Create(*storeNode2.output(0),
"store2");
553 const auto successStoreNode1 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
556 const auto successStoreNode2 = jlm::rvsdg::ReduceNode<StoreNonVolatileOperation>(
565 EXPECT_FALSE(successStoreNode1);
566 EXPECT_FALSE(successStoreNode2);
567 EXPECT_EQ(x1.origin(), storeNode1.output(0));
568 EXPECT_EQ(x2.origin(), storeNode2.output(0));
static std::vector< rvsdg::Output * > create(std::shared_ptr< const rvsdg::Type > allocatedType, rvsdg::Output *count, const size_t alignment)
static std::shared_ptr< const IOStateType > Create()
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
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 ...
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.
static std::optional< std::vector< rvsdg::Output * > > normalizeStoreAllocaSingleUser(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
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.
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.
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateStates(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
const rvsdg::Type & GetStoredType() const noexcept
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
size_t GetAlignment() const noexcept
size_t NumMemoryStates() const noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< StoreVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
static std::shared_ptr< const BitType > Create(std::size_t nbits)
Creates bit type of specified width.
static GraphImport & Create(Graph &graph, std::shared_ptr< const rvsdg::Type > type, std::string name)
Region & GetRootRegion() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
RegionResult * result(size_t index) const noexcept
size_t numNodes() const noexcept
Node * copy(Region *region, const std::vector< Output * > &operands) const override
size_t nresults() const noexcept
size_t narguments() const noexcept
static std::shared_ptr< const TestType > createValueType()
TEST(StoreTests, StoreConversion)
Global memory state passed between functions.
std::string view(const rvsdg::Region *region)
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)