6#ifndef JLM_LLVM_IR_OPERATORS_STORE_HPP
7#define JLM_LLVM_IR_OPERATORS_STORE_HPP
29 const std::vector<std::shared_ptr<const rvsdg::Type>> & operandTypes,
30 const std::vector<std::shared_ptr<const rvsdg::Type>> & resultTypes,
39 auto & addressType = *operandTypes[0];
42 auto & storedType = *operandTypes[1];
45 JLM_ASSERT(operandTypes.size() == resultTypes.size() + 2);
46 for (
size_t n = 0; n < resultTypes.size(); n++)
48 auto & operandType = *operandTypes[n + 2];
49 auto & resultType = *resultTypes[n];
82 [[nodiscard]]
static size_t
85 const auto storeOperation = util::assertedCast<const StoreOperation>(&node.GetOperation());
86 return storeOperation->NumMemoryStates_;
93 auto & input = *node.input(0);
102 auto & input = *node.input(1);
110 const auto storeOperation = util::assertedCast<const StoreOperation>(&node.GetOperation());
111 if (storeOperation->NumMemoryStates_ == 0)
116 const auto firstMemoryStateOutput =
117 node.output(storeOperation->nresults() - storeOperation->NumMemoryStates_);
118 JLM_ASSERT(is<MemoryStateType>(firstMemoryStateOutput->Type()));
133 const auto storeOperation = util::assertedCast<const StoreOperation>(&node.GetOperation());
134 if (storeOperation->NumMemoryStates_ == 0)
139 const auto firstMemoryStateInput =
140 node.input(storeOperation->narguments() - storeOperation->NumMemoryStates_);
141 JLM_ASSERT(is<MemoryStateType>(firstMemoryStateInput->Type()));
153 [[nodiscard]]
static std::vector<rvsdg::Output *>
156 std::vector<rvsdg::Output *> operands;
158 operands.push_back(input.origin());
172 JLM_ASSERT(storeNode->ninputs() - 2 == storeNode->noutputs());
173 const auto input = storeNode->input(output.
index() + 2);
174 JLM_ASSERT(is<MemoryStateType>(input->Type()));
194 std::shared_ptr<const rvsdg::Type> storedType,
196 const
size_t alignment)
205 operator==(
const Operation & other)
const noexcept override;
207 [[nodiscard]] std::string
210 [[nodiscard]] std::unique_ptr<Operation>
211 copy()
const override;
231 static std::optional<std::vector<rvsdg::Output *>>
233 const StoreNonVolatileOperation & operation,
234 const std::vector<rvsdg::Output *> & operands);
250 static std::optional<std::vector<rvsdg::Output *>>
252 const StoreNonVolatileOperation & store2Op,
253 const std::vector<rvsdg::Output *> & operands);
273 static std::optional<std::vector<rvsdg::Output *>>
275 const StoreNonVolatileOperation & operation,
276 const std::vector<rvsdg::Output *> & operands);
291 static std::optional<std::vector<rvsdg::Output *>>
293 const StoreNonVolatileOperation & operation,
294 const std::vector<rvsdg::Output *> & operands);
318 static std::optional<std::vector<rvsdg::Output *>>
320 const StoreNonVolatileOperation & storeOperation,
321 const std::vector<rvsdg::Output *> & operands);
335 static std::optional<std::vector<rvsdg::Output *>>
337 const StoreNonVolatileOperation & operation,
338 const std::vector<rvsdg::Output *> & operands);
340 static std::unique_ptr<llvm::ThreeAddressCode>
345 auto op = std::make_unique<StoreNonVolatileOperation>(storedType, 1, alignment);
349 static std::vector<rvsdg::Output *>
353 const std::vector<rvsdg::Output *> & memoryStates,
356 return outputs(&
CreateNode(*address, *value, memoryStates, alignment));
363 const std::vector<rvsdg::Output *> & memoryStates,
368 std::vector operands({ &address, &value });
369 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
371 auto operation = std::make_unique<StoreNonVolatileOperation>(
372 std::move(storedType),
378 static std::vector<rvsdg::Output *>
381 std::unique_ptr<StoreNonVolatileOperation> storeOperation,
382 const std::vector<rvsdg::Output *> & operands)
384 return outputs(&
CreateNode(region, std::move(storeOperation), operands));
390 std::unique_ptr<StoreNonVolatileOperation> storeOperation,
391 const std::vector<rvsdg::Output *> & operands)
397 static const std::shared_ptr<const jlm::rvsdg::Type>
408 static std::vector<std::shared_ptr<const rvsdg::Type>>
411 std::vector<std::shared_ptr<const rvsdg::Type>> types(
413 std::vector<std::shared_ptr<const rvsdg::Type>> states(
416 types.insert(types.end(), states.begin(), states.end());
438 std::shared_ptr<const rvsdg::Type> storedType,
440 const
size_t alignment)
449 operator==(
const Operation & other)
const noexcept override;
451 [[nodiscard]] std::string
454 [[nodiscard]] std::unique_ptr<Operation>
455 copy()
const override;
461 auto & input = *node.input(2);
470 auto & output = *node.output(0);
475 static std::unique_ptr<llvm::ThreeAddressCode>
485 auto op = std::make_unique<StoreVolatileOperation>(storedType, 1, alignment);
492 std::unique_ptr<StoreVolatileOperation> storeOperation,
493 const std::vector<rvsdg::Output *> & operands)
503 const std::vector<rvsdg::Output *> & memoryStates,
508 std::vector<rvsdg::Output *> operands({ &address, &value, &ioState });
509 operands.insert(operands.end(), memoryStates.begin(), memoryStates.end());
512 std::make_unique<StoreVolatileOperation>(storedType, memoryStates.size(), alignment);
516 static std::vector<rvsdg::Output *>
519 std::unique_ptr<StoreVolatileOperation> storeOperation,
520 const std::vector<rvsdg::Output *> & operands)
526 static std::shared_ptr<const rvsdg::Type>
535 static std::vector<std::shared_ptr<const rvsdg::Type>>
538 std::vector<std::shared_ptr<const rvsdg::Type>> types(
540 std::vector<std::shared_ptr<const rvsdg::Type>> states(
543 types.insert(types.end(), states.begin(), states.end());
547 static std::vector<std::shared_ptr<const rvsdg::Type>>
551 std::vector<std::shared_ptr<const rvsdg::Type>> memoryStates(
554 types.insert(types.end(), memoryStates.begin(), memoryStates.end());
static std::shared_ptr< const IOStateType > Create()
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
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 rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< StoreNonVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
static const std::shared_ptr< const jlm::rvsdg::Type > CheckAndExtractStoredType(const std::shared_ptr< const rvsdg::Type > &type)
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
bool operator==(const Operation &other) const noexcept 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.
static std::optional< std::vector< rvsdg::Output * > > normalizeMemoryHoistBarrierAddress(const StoreNonVolatileOperation &storeOperation, const std::vector< rvsdg::Output * > &operands)
Redirect the address operand of the StoreNonVolatileOperation node from an MemoryHoistBarrierOperatio...
~StoreNonVolatileOperation() noexcept override
static std::vector< rvsdg::Output * > Create(rvsdg::Output *address, rvsdg::Output *value, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(std::shared_ptr< const rvsdg::Type > storedType, size_t numMemoryStates)
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::vector< rvsdg::Output * > Create(rvsdg::Region ®ion, std::unique_ptr< StoreNonVolatileOperation > storeOperation, 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 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 std::vector< rvsdg::Output * > getMemoryStateOperands(const rvsdg::Node &node) noexcept
static rvsdg::Input & StoredValueInput(const rvsdg::Node &node) noexcept
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
size_t GetAlignment() const noexcept
static size_t numMemoryStates(const rvsdg::SimpleNode &node) noexcept
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
StoreOperation(const std::vector< std::shared_ptr< const rvsdg::Type > > &operandTypes, const std::vector< std::shared_ptr< const rvsdg::Type > > &resultTypes, size_t numMemoryStates, size_t alignment)
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
static rvsdg::Node::InputIteratorRange getMemoryStateInputs(const rvsdg::Node &node) noexcept
const rvsdg::Type & GetStoredType() const noexcept
size_t NumMemoryStates() const noexcept
bool operator==(const Operation &other) const noexcept override
std::string debug_string() const override
~StoreVolatileOperation() noexcept override
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node) noexcept
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(size_t numMemoryStates)
std::unique_ptr< Operation > copy() const override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(std::shared_ptr< const rvsdg::Type > storedType, size_t numMemoryStates)
static std::vector< rvsdg::Output * > Create(rvsdg::Region ®ion, std::unique_ptr< StoreVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *value, const Variable *ioState, const Variable *memoryState, size_t alignment)
static std::shared_ptr< const rvsdg::Type > CheckAndExtractStoredType(const std::shared_ptr< const rvsdg::Type > &type)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &value, rvsdg::Output &ioState, const std::vector< rvsdg::Output * > &memoryStates, size_t alignment)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< StoreVolatileOperation > storeOperation, const std::vector< rvsdg::Output * > &operands)
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
const std::shared_ptr< const jlm::rvsdg::Type > Type() const noexcept
rvsdg::Region * region() const noexcept
size_t index() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
Represent acyclic RVSDG subgraphs.
static SimpleNode & Create(Region ®ion, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
const std::shared_ptr< const rvsdg::Type > & argument(size_t index) const noexcept
SimpleOperation(std::vector< std::shared_ptr< const jlm::rvsdg::Type > > operands, std::vector< std::shared_ptr< const jlm::rvsdg::Type > > results)
Global memory state passed between functions.
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)
@ State
Designate a state type.
@ Value
Designate a value type.
NodeType * TryGetOwnerNode(const rvsdg::Input &input) noexcept
Checks if this is an input to a node of specified type.