6 #ifndef JLM_LLVM_IR_OPERATORS_LOAD_HPP
7 #define JLM_LLVM_IR_OPERATORS_LOAD_HPP
29 const std::vector<std::shared_ptr<const rvsdg::Type>> & operandTypes,
30 const std::vector<std::shared_ptr<const rvsdg::Type>> & resultTypes,
32 const size_t alignment)
37 JLM_ASSERT(!operandTypes.empty() && !resultTypes.empty());
39 auto & addressType = *operandTypes[0];
42 auto & loadedType = *resultTypes[0];
45 JLM_ASSERT(operandTypes.size() == resultTypes.size());
46 for (
size_t n = 1; n < operandTypes.size(); n++)
48 auto & operandType = *operandTypes[n];
49 auto & resultType = *resultTypes[n];
62 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
78 const auto input = node.input(0);
87 const auto output = node.
output(0);
100 [[nodiscard]]
static size_t
103 const auto loadOperation = util::assertedCast<const LoadOperation>(&node.GetOperation());
104 return loadOperation->NumMemoryStates_;
118 const auto loadOperation = util::assertedCast<const LoadOperation>(&node.GetOperation());
119 if (loadOperation->NumMemoryStates_ == 0)
124 const auto firstMemoryStateOutput =
125 node.output(loadOperation->nresults() - loadOperation->NumMemoryStates_);
126 JLM_ASSERT(is<MemoryStateType>(firstMemoryStateOutput->Type()));
141 const auto loadOperation = util::assertedCast<const LoadOperation>(&node.GetOperation());
142 if (loadOperation->NumMemoryStates_ == 0)
147 const auto firstMemoryStateOutput =
148 node.input(loadOperation->narguments() - loadOperation->NumMemoryStates_);
149 JLM_ASSERT(is<MemoryStateType>(firstMemoryStateOutput->Type()));
160 auto [loadNode, loadOperation] = rvsdg::TryGetSimpleNodeAndOptionalOp<LoadOperation>(output);
162 JLM_ASSERT(loadNode->ninputs() == loadNode->noutputs());
163 const auto input = loadNode->input(output.
index());
164 JLM_ASSERT(is<MemoryStateType>(input->Type()));
175 auto [loadNode, loadOperation] = rvsdg::TryGetSimpleNodeAndOptionalOp<LoadOperation>(input);
177 JLM_ASSERT(loadNode->ninputs() == loadNode->noutputs());
178 const auto output = loadNode->output(input.
index());
179 JLM_ASSERT(is<MemoryStateType>(output->Type()));
205 std::shared_ptr<const rvsdg::Type> loadedType,
216 operator==(
const Operation & other)
const noexcept
override;
218 [[nodiscard]] std::string
221 [[nodiscard]] std::unique_ptr<Operation>
222 copy()
const override;
228 const auto input = node.input(1);
237 const auto output = node.
output(1);
242 static std::unique_ptr<llvm::ThreeAddressCode>
247 std::shared_ptr<const rvsdg::Type> loadedType,
250 auto operation = std::make_unique<LoadVolatileOperation>(std::move(loadedType), 1, alignment);
257 std::unique_ptr<LoadVolatileOperation> loadOperation,
258 const std::vector<rvsdg::Output *> &
operands);
264 const std::vector<rvsdg::Output *> & memoryStates,
265 std::shared_ptr<const rvsdg::Type> loadedType,
268 std::vector
operands({ &address, &iOState });
271 auto operation = std::make_unique<LoadVolatileOperation>(
272 std::move(loadedType),
279 static std::vector<std::shared_ptr<const rvsdg::Type>>
282 std::vector<std::shared_ptr<const rvsdg::Type>> types(
284 std::vector<std::shared_ptr<const rvsdg::Type>> states(
287 types.insert(types.end(), states.begin(), states.end());
291 static std::vector<std::shared_ptr<const rvsdg::Type>>
294 std::vector<std::shared_ptr<const rvsdg::Type>> types(
296 std::vector<std::shared_ptr<const rvsdg::Type>> states(
299 types.insert(types.end(), states.begin(), states.end());
315 std::shared_ptr<const rvsdg::Type> loadedType,
326 operator==(
const Operation & other)
const noexcept
override;
328 [[nodiscard]] std::string
331 [[nodiscard]] std::unique_ptr<Operation>
332 copy()
const override;
352 static std::optional<std::vector<rvsdg::Output *>>
355 const std::vector<rvsdg::Output *> &
operands);
373 static std::optional<std::vector<rvsdg::Output *>>
376 const std::vector<rvsdg::Output *> &
operands);
397 static std::optional<std::vector<rvsdg::Output *>>
400 const std::vector<rvsdg::Output *> &
operands);
415 static std::optional<std::vector<rvsdg::Output *>>
418 const std::vector<rvsdg::Output *> &
operands);
438 static std::optional<std::vector<rvsdg::Output *>>
441 const std::vector<rvsdg::Output *> &
operands);
443 static std::unique_ptr<llvm::ThreeAddressCode>
447 std::shared_ptr<const rvsdg::Type> loadedType,
451 std::make_unique<LoadNonVolatileOperation>(std::move(loadedType), 1, alignment);
455 static std::vector<rvsdg::Output *>
458 const std::vector<rvsdg::Output *> & memoryStates,
459 std::shared_ptr<const rvsdg::Type> loadedType,
460 const size_t alignment)
468 std::unique_ptr<LoadNonVolatileOperation> loadOperation,
469 const std::vector<rvsdg::Output *> &
operands)
474 static std::vector<rvsdg::Output *>
477 std::unique_ptr<LoadNonVolatileOperation> loadOperation,
478 const std::vector<rvsdg::Output *> &
operands)
486 const std::vector<rvsdg::Output *> & memoryStates,
487 std::shared_ptr<const rvsdg::Type> loadedType,
493 auto operation = std::make_unique<LoadNonVolatileOperation>(
494 std::move(loadedType),
501 static std::vector<std::shared_ptr<const rvsdg::Type>>
505 std::vector<std::shared_ptr<const rvsdg::Type>> states(
508 types.insert(types.end(), states.begin(), states.end());
512 static std::vector<std::shared_ptr<const rvsdg::Type>>
515 std::vector<std::shared_ptr<const rvsdg::Type>> types(1, std::move(loadedType));
516 std::vector<std::shared_ptr<const rvsdg::Type>> states(
519 types.insert(types.end(), states.begin(), states.end());
static std::shared_ptr< const IOStateType > Create()
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(size_t numMemoryStates)
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...
static std::vector< rvsdg::Output * > Create(rvsdg::Output *address, const std::vector< rvsdg::Output * > &memoryStates, std::shared_ptr< const rvsdg::Type > loadedType, const size_t alignment)
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, const std::vector< rvsdg::Output * > &memoryStates, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
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::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(std::shared_ptr< const rvsdg::Type > loadedType, size_t numMemoryStates)
static std::vector< rvsdg::Output * > Create(rvsdg::Region ®ion, std::unique_ptr< LoadNonVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &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
bool operator==(const Operation &other) const noexcept 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
static rvsdg::Input & AddressInput(const rvsdg::Node &node) noexcept
static rvsdg::Output & LoadedValueOutput(const rvsdg::Node &node)
LoadOperation(const std::vector< std::shared_ptr< const rvsdg::Type >> &operandTypes, const std::vector< std::shared_ptr< const rvsdg::Type >> &resultTypes, const size_t numMemoryStates, const size_t alignment)
static size_t numMemoryStates(const rvsdg::SimpleNode &node) noexcept
static rvsdg::Node::OutputIteratorRange MemoryStateOutputs(const rvsdg::Node &node) noexcept
static rvsdg::Output & mapMemoryStateInputToOutput(const rvsdg::Input &input)
static rvsdg::Node::InputIteratorRange MemoryStateInputs(const rvsdg::Node &node) noexcept
size_t GetAlignment() const noexcept
static rvsdg::Input & MapMemoryStateOutputToInput(const rvsdg::Output &output)
std::string debug_string() const override
~LoadVolatileOperation() noexcept override
static rvsdg::Input & IOStateInput(const rvsdg::Node &node) noexcept
static rvsdg::SimpleNode & CreateNode(rvsdg::Output &address, rvsdg::Output &iOState, const std::vector< rvsdg::Output * > &memoryStates, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
bool operator==(const Operation &other) const noexcept override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateResultTypes(std::shared_ptr< const rvsdg::Type > loadedType, size_t numMemoryStates)
static rvsdg::SimpleNode & CreateNode(rvsdg::Region ®ion, std::unique_ptr< LoadVolatileOperation > loadOperation, const std::vector< rvsdg::Output * > &operands)
static std::unique_ptr< llvm::ThreeAddressCode > Create(const Variable *address, const Variable *iOState, const Variable *memoryState, std::shared_ptr< const rvsdg::Type > loadedType, size_t alignment)
std::unique_ptr< Operation > copy() const override
static std::vector< std::shared_ptr< const rvsdg::Type > > CreateOperandTypes(size_t numMemoryStates)
static rvsdg::Output & IOStateOutput(const rvsdg::Node &node)
static std::shared_ptr< const MemoryStateType > Create()
static std::shared_ptr< const PointerType > Create()
static std::unique_ptr< llvm::ThreeAddressCode > create(std::unique_ptr< rvsdg::SimpleOperation > operation, const std::vector< const Variable * > &operands)
NodeOutput * output(size_t index) const noexcept
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
size_t index() 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 > & result(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.
@ State
Designate a state type.
@ Value
Designate a value type.
static std::vector< jlm::rvsdg::Output * > operands(const Node *node)
static std::vector< jlm::rvsdg::Output * > outputs(const Node *node)