Jlm
Loading...
Searching...
No Matches
IOBarrierEliminationTests.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2026 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/lambda.hpp>
17
18namespace jlm::llvm
19{
20
21static void
23{
24
26 IOBarrierElimination ioBarrierElimination;
27 ioBarrierElimination.Run(rvsdgModule, statisticsCollector);
28}
29
30TEST(IOBarrierEliminationTests, testLambdaArgument)
31{
32 using namespace jlm::rvsdg;
33
34 // Arrange
35 auto i32Type = BitType::Create(32);
36 auto pointerType = PointerType::Create();
37 auto ioStateType = IOStateType::Create();
38 auto functionType = FunctionType::Create({ pointerType, ioStateType }, { i32Type, ioStateType });
39
40 auto rvsdgModule = LlvmRvsdgModule::Create(util::FilePath(""), "", "");
41 auto & rvsdg = rvsdgModule->Rvsdg();
42
43 auto lambdaNode = LambdaNode::Create(
44 rvsdg.GetRootRegion(),
46 auto ptrArgument = lambdaNode->GetFunctionArguments()[0];
47 auto ioStateArgument = lambdaNode->GetFunctionArguments()[1];
48
49 auto & ioBarrierNode = IOBarrierOperation::createNode(*ptrArgument, *ioStateArgument);
50
51 auto & loadNode = LoadNonVolatileOperation::CreateNode(*ioBarrierNode.output(0), {}, i32Type, 4);
52
53 auto lambdaOutput = lambdaNode->finalize({ loadNode.output(0), ioStateArgument });
54 GraphExport::Create(*lambdaOutput, "test");
55
56 // Act
57 runIOBarrierElimination(*rvsdgModule);
58
59 // Assert
60 // We expect the IOBarrier node to be eliminated
61 EXPECT_FALSE(Region::containsOperation<IOBarrierOperation>(rvsdg.GetRootRegion(), true));
62}
63
64TEST(IOBarrierEliminationTests, testSizeIsRespected)
65{
66 using namespace jlm::rvsdg;
67
68 // Arrange
69 auto i8Type = BitType::Create(8);
70 auto i32Type = BitType::Create(32);
71 auto pointerType = PointerType::Create();
72 auto ioStateType = IOStateType::Create();
73 auto functionType =
74 FunctionType::Create({ pointerType, ioStateType }, { i8Type, i32Type, ioStateType });
75
76 auto rvsdgModule = LlvmRvsdgModule::Create(util::FilePath(""), "", "");
77 auto & rvsdg = rvsdgModule->Rvsdg();
78
79 auto lambdaNode = LambdaNode::Create(
80 rvsdg.GetRootRegion(),
82 auto ptrArgument = lambdaNode->GetFunctionArguments()[0];
83 auto ioStateArgument = lambdaNode->GetFunctionArguments()[1];
84
85 auto & loadNode1 = LoadNonVolatileOperation::CreateNode(*ptrArgument, {}, i8Type, 4);
86
87 auto testNode =
88 TestOperation::createNode(lambdaNode->subregion(), { ioStateArgument }, { ioStateType });
89
90 auto & ioBarrierNode = IOBarrierOperation::createNode(*ptrArgument, *testNode->output(0));
91
92 auto & loadNode2 = LoadNonVolatileOperation::CreateNode(*ioBarrierNode.output(0), {}, i32Type, 4);
93
94 auto lambdaOutput =
95 lambdaNode->finalize({ loadNode1.output(0), loadNode2.output(0), testNode->output(0) });
96 GraphExport::Create(*lambdaOutput, "test");
97
98 // Act
99 runIOBarrierElimination(*rvsdgModule);
100
101 // Assert
102 // We expect the IOBarrier node to NOT be eliminated as loadNode1 marks the pointer argument only
103 // dereferenceable with size i8, but loadNode2 requires size i32.
104 EXPECT_TRUE(Region::containsOperation<IOBarrierOperation>(rvsdg.GetRootRegion(), true));
105}
106
107TEST(IOBarrierEliminationTests, testSuccess)
108{
109 using namespace jlm::rvsdg;
110
111 // Arrange
112 auto i32Type = BitType::Create(32);
113 auto i64Type = BitType::Create(64);
114 auto pointerType = PointerType::Create();
115 auto ioStateType = IOStateType::Create();
116 auto functionType =
117 FunctionType::Create({ pointerType, ioStateType }, { i64Type, i32Type, ioStateType });
118
119 auto rvsdgModule = LlvmRvsdgModule::Create(util::FilePath(""), "", "");
120 auto & rvsdg = rvsdgModule->Rvsdg();
121
122 auto lambdaNode = LambdaNode::Create(
123 rvsdg.GetRootRegion(),
125 auto ptrArgument = lambdaNode->GetFunctionArguments()[0];
126 auto ioStateArgument = lambdaNode->GetFunctionArguments()[1];
127
128 auto & loadNode1 = LoadNonVolatileOperation::CreateNode(*ptrArgument, {}, i64Type, 4);
129
130 auto testNode =
131 TestOperation::createNode(lambdaNode->subregion(), { ioStateArgument }, { ioStateType });
132
133 auto & ioBarrierNode = IOBarrierOperation::createNode(*ptrArgument, *testNode->output(0));
134
135 auto & loadNode2 = LoadNonVolatileOperation::CreateNode(*ioBarrierNode.output(0), {}, i32Type, 4);
136
137 auto lambdaOutput =
138 lambdaNode->finalize({ loadNode1.output(0), loadNode2.output(0), testNode->output(0) });
139 GraphExport::Create(*lambdaOutput, "test");
140
141 // Act
142 runIOBarrierElimination(*rvsdgModule);
143
144 // Assert
145 // We expect the IOBarrier node to be eliminated as loadNode1 marks the pointer argument
146 // dereferenceable with size i64, but loadNode2 only requires size i32.
147 EXPECT_FALSE(Region::containsOperation<IOBarrierOperation>(rvsdg.GetRootRegion(), true));
148}
149
150TEST(IOBarrierEliminationTests, testInvidiualIOBarrierUserRerouting)
151{
152 using namespace jlm::rvsdg;
153
154 // Arrange
155 auto i8Type = BitType::Create(8);
156 auto i32Type = BitType::Create(32);
157 auto i64Type = BitType::Create(64);
158 auto pointerType = PointerType::Create();
159 auto ioStateType = IOStateType::Create();
160 auto functionType =
161 FunctionType::Create({ pointerType, ioStateType }, { i32Type, i8Type, i64Type, ioStateType });
162
163 auto rvsdgModule = LlvmRvsdgModule::Create(util::FilePath(""), "", "");
164 auto & rvsdg = rvsdgModule->Rvsdg();
165
166 auto lambdaNode = LambdaNode::Create(
167 rvsdg.GetRootRegion(),
169 auto ptrArgument = lambdaNode->GetFunctionArguments()[0];
170 auto ioStateArgument = lambdaNode->GetFunctionArguments()[1];
171
172 auto & load32Node = LoadNonVolatileOperation::CreateNode(*ptrArgument, {}, i32Type, 4);
173
174 auto testNode =
175 TestOperation::createNode(lambdaNode->subregion(), { ioStateArgument }, { ioStateType });
176
177 auto & ioBarrierNode = IOBarrierOperation::createNode(*ptrArgument, *testNode->output(0));
178
179 auto & load8Node = LoadNonVolatileOperation::CreateNode(*ioBarrierNode.output(0), {}, i8Type, 4);
180
181 auto & load64Node =
182 LoadNonVolatileOperation::CreateNode(*ioBarrierNode.output(0), {}, i64Type, 4);
183
184 auto lambdaOutput = lambdaNode->finalize(
185 { load32Node.output(0), load8Node.output(0), load64Node.output(0), testNode->output(0) });
186 GraphExport::Create(*lambdaOutput, "test");
187
188 // Act
189 runIOBarrierElimination(*rvsdgModule);
190
191 // Assert
192 EXPECT_TRUE(Region::containsOperation<IOBarrierOperation>(rvsdg.GetRootRegion(), true));
193
194 // We expect that the load8Node is not any longer barred behind the IOBarrier node as ptrArgument
195 // is dereferenceable for 32 bits.
196 EXPECT_EQ(LoadOperation::AddressInput(load8Node).origin(), ptrArgument);
197
198 // We expect that the load64Node is still barred behind the IOBarrier node as ptrArgument is only
199 // dereferenceable for 64 bits.
200 EXPECT_EQ(LoadOperation::AddressInput(load64Node).origin(), ioBarrierNode.output(0));
201}
202
203}
static jlm::util::StatisticsCollector statisticsCollector
void Run(rvsdg::RvsdgModule &module, util::StatisticsCollector &statisticsCollector) override
Perform RVSDG transformation.
static rvsdg::SimpleNode & createNode(rvsdg::Output &value, rvsdg::Output &ioState)
Definition IOBarrier.hpp:87
static std::shared_ptr< const IOStateType > Create()
Definition types.cpp:343
static std::unique_ptr< LlvmLambdaOperation > Create(std::shared_ptr< const jlm::rvsdg::FunctionType > type, std::string name, const jlm::llvm::Linkage &linkage, jlm::llvm::CallingConvention callingConvention, jlm::llvm::AttributeSet attributes)
Definition lambda.hpp:84
static std::unique_ptr< LlvmRvsdgModule > Create(const util::FilePath &sourceFileName, const std::string &targetTriple, const std::string &dataLayout)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region &region, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
Definition Load.hpp:469
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Definition Load.hpp:75
static std::shared_ptr< const PointerType > Create()
Definition types.cpp:45
Global memory state passed between functions.
static void runIOBarrierElimination(LlvmRvsdgModule &rvsdgModule)
TEST(ControlOperationsTests, foldConstants)