27 return operation && operation->
narguments() == narguments()
28 && operation->GetStoredType() == GetStoredType()
29 && operation->GetAlignment() == GetAlignment();
38std::unique_ptr<rvsdg::Operation>
41 return std::make_unique<StoreNonVolatileOperation>(*
this);
50 if (!is<MemoryStateMergeOperation>(memStateMergeNode))
53 for (
size_t n = 2; n < operands.size(); n++)
65 if (operands.size() == 3)
69 if (!is<AllocaOperation>(allocaNode))
72 std::unordered_set states(std::next(std::next(operands.begin())), operands.end());
73 if (states.find(allocaNode->output(1)) == states.end())
76 if (allocaNode->output(1)->nusers() != 1)
86 return states.
Size() != operands.size() - 2;
89static std::vector<jlm::rvsdg::Output *>
92 const std::vector<jlm::rvsdg::Output *> & operands)
100 memStateMergeOperands,
105static std::vector<jlm::rvsdg::Output *>
108 const std::vector<jlm::rvsdg::Output *> & operands)
110 auto value = operands[1];
111 auto address = operands[0];
113 std::unordered_set<jlm::rvsdg::Output *> states(
114 std::next(std::next(operands.begin())),
119 states.erase(alloca_state);
120 states.insert(outputs[0]);
121 return { states.begin(), states.end() };
124static std::vector<jlm::rvsdg::Output *>
127 const std::vector<jlm::rvsdg::Output *> & operands)
132 const auto address = operands[0];
133 const auto value = operands[1];
135 std::vector<rvsdg::Output *> newInputStates;
136 std::unordered_map<rvsdg::Output *, size_t> stateIndexMap;
137 for (
size_t n = 2; n < operands.size(); n++)
139 auto state = operands[n];
140 if (stateIndexMap.find(state) == stateIndexMap.end())
142 const size_t resultIndex = newInputStates.size();
143 newInputStates.push_back(state);
144 stateIndexMap[state] = resultIndex;
148 const auto storeResults =
151 std::vector<rvsdg::Output *> results(operation.
nresults(),
nullptr);
152 for (
size_t n = 2; n < operands.size(); n++)
154 auto state = operands[n];
155 JLM_ASSERT(stateIndexMap.find(state) != stateIndexMap.end());
156 results[n - 2] = storeResults[stateIndexMap[state]];
162std::optional<std::vector<rvsdg::Output *>>
165 const std::vector<rvsdg::Output *> & operands)
173std::optional<std::vector<rvsdg::Output *>>
176 const std::vector<rvsdg::Output *> & operands)
186 auto & store2Address = *operands[0];
187 auto & store2Value = *operands[1];
188 const auto & store2FirstMemoryState = *operands[2];
191 const auto [store1Node, store1Op] =
202 std::vector<rvsdg::Output *> newMemoryStates;
203 for (
size_t n = 2; n < operands.size(); n++)
205 auto & memoryState = *operands[n];
206 JLM_ASSERT(is<MemoryStateType>(memoryState.Type()));
209 && memoryState.nusers() == 1)
212 newMemoryStates.push_back(memoryStateInput.origin());
221 const auto & store1Type = store1Op->GetStoredType();
226 return Create(&store2Address, &store2Value, newMemoryStates, store2Op.
GetAlignment());
229std::optional<std::vector<rvsdg::Output *>>
232 const std::vector<rvsdg::Output *> & operands)
240std::optional<std::vector<rvsdg::Output *>>
243 const std::vector<rvsdg::Output *> & operands)
253static std::optional<size_t>
256 auto [allocaNode, allocaOperation] =
265 const auto deltaOperation =
266 util::assertedCast<const LlvmDeltaOperation>(&deltaNode->GetOperation());
270 if (
const auto llvmImport =
dynamic_cast<const LlvmGraphImport *
>(&output))
278std::optional<std::vector<rvsdg::Output *>>
281 const std::vector<rvsdg::Output *> & operands)
284 const auto address = operands[0];
285 const auto value = operands[1];
287 auto [ioBarrierNode, ioBarrierOperation] =
289 if (!ioBarrierOperation)
295 if (!allocationSizeInBytes.has_value())
298 size_t offsetInBytes = 0;
299 if (
const auto offsetInBytesOpt = pointerOrigin.getOffsetInBytes(); offsetInBytesOpt.has_value())
301 offsetInBytes = offsetInBytesOpt.value();
307 > allocationSizeInBytes.value())
313 { std::next(operands.begin(), 2), operands.end() },
316 return { outputs(&storeNode) };
319std::optional<std::vector<rvsdg::Output *>>
322 const std::vector<rvsdg::Output *> & operands)
325 const auto & address = *operands[0];
333 if (address.nusers() != 1)
336 std::vector newMemoryStateResults(operands.begin() + 2, operands.end());
339 return newMemoryStateResults;
349 && operation->GetStoredType() == GetStoredType()
350 && operation->GetAlignment() == GetAlignment();
356 return "StoreVolatile";
359std::unique_ptr<rvsdg::Operation>
362 return std::make_unique<StoreVolatileOperation>(*
this);
static rvsdg::Input & BarredInput(const rvsdg::Node &node) noexcept
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > normalizeStoreStore(const StoreNonVolatileOperation &store2Op, const std::vector< rvsdg::Output * > &operands)
Removes a duplicated store to the same address.
static std::optional< std::vector< rvsdg::Output * > > normalizeIOBarrierAddress(const StoreNonVolatileOperation &storeOperation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the StoreNonVolatileOperation node from an IOBarrierOperation node wh...
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *state, size_t alignment)
std::string debug_string() const override
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.
~StoreNonVolatileOperation() noexcept override
static std::optional< std::vector< rvsdg::Output * > > normalizeStoreAllocaSingleUser(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
std::unique_ptr< Operation > copy() const override
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 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 * > > NormalizeDuplicateStates(const StoreNonVolatileOperation &operation, const std::vector< rvsdg::Output * > &operands)
Remove duplicated state operands.
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
size_t GetAlignment() const noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
const rvsdg::Type & GetStoredType() const noexcept
size_t NumMemoryStates() const noexcept
std::string debug_string() const override
~StoreVolatileOperation() noexcept override
std::unique_ptr< Operation > copy() const override
size_t nresults() const noexcept
size_t narguments() const noexcept
std::size_t Size() const noexcept
Global memory state passed between functions.
size_t GetTypeAllocSize(const rvsdg::Type &type)
static std::vector< jlm::rvsdg::Output * > perform_store_mux_reduction(const StoreNonVolatileOperation &op, const std::vector< jlm::rvsdg::Output * > &operands)
rvsdg::Output & traceOutput(rvsdg::Output &output, const rvsdg::Region *withinRegion)
static std::vector< jlm::rvsdg::Output * > perform_store_alloca_reduction(const StoreNonVolatileOperation &op, const std::vector< jlm::rvsdg::Output * > &operands)
TracedPointerOrigin TracePointerOriginPrecise(const rvsdg::Output &p)
static bool is_store_mux_reducible(const std::vector< jlm::rvsdg::Output * > &operands)
size_t GetTypeStoreSize(const rvsdg::Type &type)
static std::optional< size_t > getAllocationSizeInBytes(const rvsdg::Output &output)
static bool is_multiple_origin_reducible(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_store_alloca_reducible(const std::vector< jlm::rvsdg::Output * > &operands)
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.