6#ifndef JLM_LLVM_IR_OPERATORS_MEMORYSTATEOPERATIONS_HPP
7#define JLM_LLVM_IR_OPERATORS_MEMORYSTATEOPERATIONS_HPP
47 throw util::Error(
"Insufficient number of operands.");
51 operator==(
const Operation & other)
const noexcept override;
53 [[nodiscard]] std::string
56 [[nodiscard]] std::unique_ptr<Operation>
57 copy()
const override;
67 static std::optional<std::vector<rvsdg::Output *>>
70 const std::vector<rvsdg::Output *> & operands);
78 static std::optional<std::vector<rvsdg::Output *>>
81 const std::vector<rvsdg::Output *> & operands);
90 static std::optional<std::vector<rvsdg::Output *>>
93 const std::vector<rvsdg::Output *> & operands);
102 static std::optional<std::vector<rvsdg::Output *>>
105 const std::vector<rvsdg::Output *> & operands);
114 Create(
const std::vector<rvsdg::Output *> & operands)
119 static std::unique_ptr<ThreeAddressCode>
120 Create(
const std::vector<const Variable *> & operands)
122 if (operands.empty())
123 throw util::Error(
"Insufficient number of operands.");
125 auto operation = std::make_unique<MemoryStateMergeOperation>(operands.size());
144 if (numOperands == 0)
145 throw std::logic_error(
"Insufficient number of operands.");
149 operator==(
const Operation & other)
const noexcept override;
151 [[nodiscard]] std::string
154 [[nodiscard]] std::unique_ptr<Operation>
155 copy()
const override;
165 static std::optional<std::vector<rvsdg::Output *>>
168 const std::vector<rvsdg::Output *> & operands);
176 static std::optional<std::vector<rvsdg::Output *>>
179 const std::vector<rvsdg::Output *> & operands);
188 static std::optional<std::vector<rvsdg::Output *>>
191 const std::vector<rvsdg::Output *> & operands);
215 throw util::Error(
"Insufficient number of results.");
219 operator==(
const Operation & other)
const noexcept override;
221 [[nodiscard]] std::string
224 [[nodiscard]] std::unique_ptr<Operation>
225 copy()
const override;
235 static std::optional<std::vector<rvsdg::Output *>>
238 const std::vector<rvsdg::Output *> & operands);
247 static std::optional<std::vector<rvsdg::Output *>>
250 const std::vector<rvsdg::Output *> & operands);
260 static std::optional<std::vector<rvsdg::Output *>>
263 const std::vector<rvsdg::Output *> & operands);
271 static std::vector<rvsdg::Output *>
274 return outputs(&
CreateNode(operand, numResults));
296 operator==(const Operation & other) const noexcept override;
298 [[nodiscard]] std::
string
301 [[nodiscard]] std::unique_ptr<Operation>
302 copy() const override;
310 std::vector<MemoryNodeId> memoryNodeIds(
nresults());
314 memoryNodeIds[index] = memoryNodeId;
317 return memoryNodeIds;
348 std::move(memoryNodeIds));
373 operator==(const Operation & other) const noexcept override;
375 [[nodiscard]] std::
string
378 [[nodiscard]] std::unique_ptr<Operation>
379 copy() const override;
387 std::vector<MemoryNodeId> memoryNodeIds(
narguments());
391 memoryNodeIds[index] = memoryNodeId;
394 return memoryNodeIds;
431 static std::optional<std::vector<rvsdg::Output *>>
434 const std::vector<rvsdg::Output *> & operands);
447 static std::optional<std::vector<rvsdg::Output *>>
450 const std::vector<rvsdg::Output *> & operands);
462 static std::optional<std::vector<rvsdg::Output *>>
465 const std::vector<rvsdg::Output *> & operands);
470 const std::vector<rvsdg::Output *> & operands,
471 const std::vector<MemoryNodeId> & memoryNodeIds)
473 return operands.empty()
500 operator==(const Operation & other) const noexcept override;
502 [[nodiscard]] std::
string
505 [[nodiscard]] std::unique_ptr<Operation>
506 copy() const override;
514 std::vector<MemoryNodeId> memoryNodeIds(
narguments());
518 memoryNodeIds[index] = memoryNodeId;
521 return memoryNodeIds;
538 const std::vector<rvsdg::Output *> & operands,
539 std::vector<MemoryNodeId> memoryNodeIds)
543 std::move(memoryNodeIds))
546 std::move(memoryNodeIds));
571 operator==(const Operation & other) const noexcept override;
573 [[nodiscard]] std::
string
576 [[nodiscard]] std::unique_ptr<Operation>
577 copy() const override;
585 std::vector<MemoryNodeId> memoryNodeIds(
nresults());
589 memoryNodeIds[index] = memoryNodeId;
592 return memoryNodeIds;
623 std::move(memoryNodeIds));
std::string debug_string() const override
util::BijectiveMap< MemoryNodeId, size_t > MemoryNodeIdToIndex_
std::unique_ptr< Operation > copy() const override
std::vector< MemoryNodeId > getMemoryNodeIds() const noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, const std::vector< rvsdg::Output * > &operands, std::vector< MemoryNodeId > memoryNodeIds)
~CallEntryMemoryStateMergeOperation() noexcept override
static rvsdg::Input * tryMapMemoryNodeIdToInput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
~CallExitMemoryStateSplitOperation() noexcept override
static MemoryNodeId mapOutputToMemoryNodeId(const rvsdg::Output &output)
util::BijectiveMap< MemoryNodeId, size_t > memoryNodeIdToIndexMap_
std::unique_ptr< Operation > copy() const override
static rvsdg::Output * tryMapMemoryNodeIdToOutput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
std::string debug_string() const override
std::vector< MemoryNodeId > getMemoryNodeIds() const noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, std::vector< MemoryNodeId > memoryNodeIds)
util::BijectiveMap< MemoryNodeId, size_t > memoryNodeIdToIndexMap_
static rvsdg::Output * tryMapMemoryNodeIdToOutput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
~LambdaEntryMemoryStateSplitOperation() noexcept override
std::unique_ptr< Operation > copy() const override
std::vector< MemoryNodeId > getMemoryNodeIds() const noexcept
static MemoryNodeId mapOutputToMemoryNodeId(const rvsdg::Output &output)
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeLoadFromAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeStoreToAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
util::BijectiveMap< MemoryNodeId, size_t > MemoryNodeIdToIndex_
std::vector< MemoryNodeId > getMemoryNodeIds() const noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, const std::vector< rvsdg::Output * > &operands, const std::vector< MemoryNodeId > &memoryNodeIds)
static rvsdg::Input * tryMapMemoryNodeIdToInput(const rvsdg::SimpleNode &node, MemoryNodeId memoryNodeId)
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeAlloca(const LambdaExitMemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
~LambdaExitMemoryStateMergeOperation() noexcept override
static MemoryNodeId mapInputToMemoryNodeId(const rvsdg::Input &input)
std::string debug_string() const override
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateOperands(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes duplicated operands from the MemoryStateJoinOperation.
static std::optional< std::vector< rvsdg::Output * > > NormalizeNestedJoins(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested MemoryStateJoinOperation nodes into a single node.
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleOperand(const MemoryStateJoinOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateJoinOperation as it has only a single operand, i.e., no joining is performed.
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
~MemoryStateJoinOperation() noexcept override
static rvsdg::SimpleNode & CreateNode(const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeNestedMerges(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested merges into a single merge.
static rvsdg::SimpleNode & CreateNode(const std::vector< rvsdg::Output * > &operands)
bool operator==(const Operation &other) const noexcept override
~MemoryStateMergeOperation() noexcept override
std::unique_ptr< Operation > copy() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeMergeSplit(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested splits into a single merge.
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleOperand(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateMergeOperation as it has only a single operand, i.e., no merging is performed.
static rvsdg::Output * Create(const std::vector< rvsdg::Output * > &operands)
static std::optional< std::vector< rvsdg::Output * > > NormalizeDuplicateOperands(const MemoryStateMergeOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes duplicated operands from the MemoryStateMergeOperation.
static std::unique_ptr< ThreeAddressCode > Create(const std::vector< const Variable * > &operands)
std::string debug_string() const override
MemoryStateOperation(size_t numOperands, size_t numResults)
static std::optional< std::vector< rvsdg::Output * > > NormalizeNestedSplits(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Fuses nested splits into a single split.
~MemoryStateSplitOperation() noexcept override
bool operator==(const Operation &other) const noexcept override
static std::optional< std::vector< rvsdg::Output * > > NormalizeSingleResult(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes the MemoryStateSplitOperation as it has only a single result, i.e., no splitting is performed...
static std::vector< rvsdg::Output * > Create(rvsdg::Output &operand, const size_t numResults)
std::unique_ptr< Operation > copy() const override
std::string debug_string() const override
static std::optional< std::vector< rvsdg::Output * > > NormalizeSplitMerge(const MemoryStateSplitOperation &operation, const std::vector< rvsdg::Output * > &operands)
Removes an idempotent split-merge pair.
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &operand, const size_t numResults)
static std::shared_ptr< const MemoryStateType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
Represent acyclic RVSDG subgraphs.
NodeOutput * output(size_t index) const noexcept
size_t nresults() const noexcept
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > results)
size_t narguments() const noexcept
Global memory state passed between functions.
bool hasMemoryState(const rvsdg::Node &node)
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.