23 return operation && operation->
narguments() == narguments()
24 && operation->GetLoadedType() == GetLoadedType()
25 && operation->GetAlignment() == GetAlignment();
34 std::unique_ptr<rvsdg::Operation>
37 return std::make_unique<LoadNonVolatileOperation>(*
this);
57 auto [allocaNode, allocaOperation] =
58 rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(*address);
62 for (
size_t n = 1; n <
operands.size(); n++)
64 const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*
operands[n]);
65 if (is<AllocaOperation>(node) && node != allocaNode)
75 auto [storeNode, storeOperation] =
76 rvsdg::TryGetSimpleNodeAndOptionalOp<StoreNonVolatileOperation>(*state);
80 auto [allocaNode, allocaOperation] =
81 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(*address);
82 if (allocaOperation && allocaNode != loadalloca)
102 const std::vector<rvsdg::Output *> &
operands)
109 auto [allocaNode, allocaOperation] =
110 jlm::rvsdg::TryGetSimpleNodeAndOptionalOp<AllocaOperation>(*address);
111 if (!allocaOperation)
116 size_t redstates = 0;
117 for (
size_t n = 1; n <
operands.size(); n++)
124 return redstates == op.
NumMemoryStates() || redstates == 0 ? false :
true;
139 static std::vector<rvsdg::Output *>
142 const std::vector<rvsdg::Output *> &
operands)
144 const auto allocaNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*
operands[0]);
146 std::vector<rvsdg::Output *> loadstates;
147 std::vector<rvsdg::Output *> otherstates;
148 for (
size_t n = 1; n <
operands.size(); n++)
150 const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*
operands[n]);
151 if (!is<AllocaOperation>(node) || node == allocaNode)
163 std::vector<rvsdg::Output *> results(1, ld[0]);
164 results.insert(results.end(), std::next(ld.begin()), ld.end());
165 results.insert(results.end(), otherstates.begin(), otherstates.end());
169 static std::vector<rvsdg::Output *>
172 const std::vector<rvsdg::Output *> &
operands)
175 const auto allocaNode = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*address);
177 std::vector<rvsdg::Output *> new_loadstates;
178 std::vector<rvsdg::Output *> results(
operands.size(),
nullptr);
179 for (
size_t n = 1; n <
operands.size(); n++)
185 new_loadstates.push_back(state);
195 for (
size_t n = 1, s = 1; n < results.size(); n++)
197 if (results[n] ==
nullptr)
198 results[n] = ld[s++];
204 static std::vector<rvsdg::Output *>
207 const std::vector<rvsdg::Output *> &
operands)
212 std::vector<rvsdg::Output *> newInputStates;
213 std::unordered_map<rvsdg::Output *, size_t> stateIndexMap;
214 for (
size_t n = 1; n <
operands.size(); n++)
217 if (stateIndexMap.find(state) == stateIndexMap.end())
219 const size_t resultIndex = 1 + newInputStates.size();
220 newInputStates.push_back(state);
221 stateIndexMap[state] = resultIndex;
231 std::vector<rvsdg::Output *> results(
operands.size(),
nullptr);
232 results[0] = loadResults[0];
233 for (
size_t n = 1; n <
operands.size(); n++)
236 JLM_ASSERT(stateIndexMap.find(state) != stateIndexMap.end());
237 results[n] = loadResults[stateIndexMap[state]];
243 std::optional<std::vector<rvsdg::Output *>>
246 const std::vector<rvsdg::Output *> &
operands)
253 const auto loadAddressOperand =
operands[0];
257 auto [storeNode, storeOperation] =
258 rvsdg::TryGetSimpleNodeAndOptionalOp<StoreNonVolatileOperation>(*firstState);
266 if (loadAddressOperand != storeAddressOperand)
276 for (
size_t n = 1; n <
operands.size(); n++)
279 const auto node = rvsdg::TryGetOwnerNode<rvsdg::SimpleNode>(*state);
280 if (node != storeNode)
292 auto & storedValueType = *storeValueOperand->Type();
293 if (*loadedValueType != storedValueType)
300 std::vector results(1, storeValueOperand);
306 std::optional<std::vector<rvsdg::Output *>>
309 const std::vector<rvsdg::Output *> &
operands)
317 std::optional<std::vector<rvsdg::Output *>>
320 const std::vector<rvsdg::Output *> &
operands)
328 std::optional<std::vector<rvsdg::Output *>>
331 const std::vector<rvsdg::Output *> &
operands)
339 std::optional<std::vector<rvsdg::Output *>>
342 const std::vector<rvsdg::Output *> &
operands)
347 auto [ioBarrierNode, ioBarrierOperation] =
348 rvsdg::TryGetSimpleNodeAndOptionalOp<IOBarrierOperation>(*address);
349 if (!ioBarrierOperation)
354 if (!rvsdg::IsOwnerNodeOperation<AllocaOperation>(tracedAddress))
372 return operation && operation->
narguments() == narguments()
373 && operation->GetLoadedType() == GetLoadedType()
374 && operation->GetAlignment() == GetAlignment();
380 return "LoadVolatile";
383 std::unique_ptr<rvsdg::Operation>
386 return std::make_unique<LoadVolatileOperation>(*
this);
392 std::unique_ptr<LoadVolatileOperation> loadOperation,
393 const std::vector<rvsdg::Output *> &
operands)
static rvsdg::Input & BarredInput(const rvsdg::SimpleNode &node) noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeIOBarrierAllocaAddress(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the LoadNonVolatileOperation from an IOBarrierOperation when it can b...
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadStoreState(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
If the producer of a load's address is an alloca operation, then we can remove all state edges origin...
~LoadNonVolatileOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateStates(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *state, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadAlloca(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
If the producer of a load's address is an alloca operation, then we can remove all state edges origin...
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadStore(const LoadNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Forwards the value from a store operation.
size_t NumMemoryStates() const noexcept
std::shared_ptr< const rvsdg::Type > GetLoadedType() const noexcept
size_t GetAlignment() const noexcept
std::string debug_string() const override
~LoadVolatileOperation() noexcept override
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< LoadVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
Represent acyclic RVSDG subgraphs.
static SimpleNode & Create(Region ®ion, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
size_t narguments() const noexcept
std::size_t Size() const noexcept
Global memory state passed between functions.
static bool is_load_alloca_reducible(const std::vector< rvsdg::Output * > &operands)
static std::vector< rvsdg::Output * > perform_load_store_state_reduction(const LoadNonVolatileOperation &op, const std::vector< rvsdg::Output * > &operands)
rvsdg::Output & traceOutput(rvsdg::Output &output)
static bool is_load_store_state_reducible(const LoadNonVolatileOperation &op, const std::vector< rvsdg::Output * > &operands)
static std::vector< rvsdg::Output * > perform_multiple_origin_reduction(const LoadNonVolatileOperation &op, const std::vector< rvsdg::Output * > &operands)
static bool is_multiple_origin_reducible(const std::vector< rvsdg::Output * > &operands)
static bool is_reducible_state(const rvsdg::Output *state, const rvsdg::Node *loadalloca)
static std::vector< rvsdg::Output * > perform_load_alloca_reduction(const LoadNonVolatileOperation &op, const std::vector< rvsdg::Output * > &operands)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)