6#ifndef JLM_LLVM_IR_OPERATORS_GETELEMENTPTR_HPP
7#define JLM_LLVM_IR_OPERATORS_GETELEMENTPTR_HPP
31 const std::shared_ptr<const rvsdg::Type> & baseAddressType,
32 const std::vector<std::shared_ptr<const rvsdg::Type>> & indexTypes,
33 std::shared_ptr<const rvsdg::Type> gepType,
34 std::shared_ptr<const rvsdg::Type> resultType)
45 operator==(
const Operation & other)
const noexcept override;
47 [[nodiscard]] std::string
50 [[nodiscard]] std::unique_ptr<Operation>
51 copy()
const override;
53 [[nodiscard]] std::shared_ptr<const rvsdg::Type>
81 [[nodiscard]]
static std::optional<Constant>
97 const auto firstIndex = node.input(1);
98 JLM_ASSERT(is<rvsdg::BitType>(firstIndex->Type()));
108 [[nodiscard]]
static size_t
111 JLM_ASSERT(is<GetElementPtrOperation>(node.GetOperation()));
112 return node.ninputs() - 1;
127 const auto baseAddress = node.
input(0);
128 JLM_ASSERT(is<PointerType>(baseAddress->Type()));
144 const auto baseAddress = node.
input(0);
145 JLM_ASSERT(is<PointerType>(baseAddress->Type()));
158 static std::unique_ptr<ThreeAddressCode>
161 const std::vector<const Variable *> & offsets,
162 std::shared_ptr<const rvsdg::Type> gepType)
164 auto indexTypes = extractIndexTypes<const Variable>(offsets);
167 std::vector operands(1, baseAddress);
168 operands.insert(operands.end(), offsets.begin(), offsets.end());
174 static std::unique_ptr<GetElementPtrOperation>
176 const std::shared_ptr<const rvsdg::Type> & baseAddressType,
177 const std::vector<std::shared_ptr<const rvsdg::Type>> & indexTypes,
178 const std::shared_ptr<const rvsdg::Type> & gepType)
188 auto resultType =
getResultType(baseAddressType, indexTypes);
190 return std::unique_ptr<GetElementPtrOperation>(
206 const std::vector<rvsdg::Output *> &
indices,
207 const std::shared_ptr<const rvsdg::Type> & gepType)
209 std::vector operands({ &baseAddress });
233 const std::vector<rvsdg::Output *> &
indices,
234 std::shared_ptr<const rvsdg::Type> gepType)
249 static std::optional<std::vector<rvsdg::Output *>>
252 const std::vector<rvsdg::Output *> & operands);
255 static std::shared_ptr<const rvsdg::Type>
257 const std::shared_ptr<const rvsdg::Type> & gepType,
258 const std::vector<rvsdg::Output *> &
indices);
262 const std::shared_ptr<const rvsdg::Type> & gepType,
263 const std::vector<rvsdg::Output *> &
indices)
266 if (indexedType ==
nullptr)
268 throw std::logic_error(
"Invalid GetElementPtrOperation indices for type!");
275 const auto isPointerType = is<PointerType>(type);
276 const auto vectorType =
dynamic_cast<const VectorType *
>(&type);
277 const auto isVectorOfPointerType = vectorType && is<PointerType>(vectorType->Type());
279 if (!isPointerType && !isVectorOfPointerType)
281 throw std::logic_error(
"Expected pointer type.");
288 for (
auto & indexType : indexTypes)
290 if (!is<rvsdg::BitType>(indexType) && !isVectorOf<rvsdg::BitType>(*indexType))
292 throw std::logic_error(
"Expected bitstring type.");
297 static std::shared_ptr<const rvsdg::Type>
299 const std::shared_ptr<const rvsdg::Type> & baseAddressType,
300 const std::vector<std::shared_ptr<const rvsdg::Type>> & indexTypes)
306 if (
const auto fixedVectorType =
307 std::dynamic_pointer_cast<const FixedVectorType>(baseAddressType))
311 if (
const auto scalableVectorType =
312 std::dynamic_pointer_cast<const ScalableVectorType>(baseAddressType))
317 for (
auto & indexType : indexTypes)
319 if (
const auto fixedVectorType = std::dynamic_pointer_cast<const FixedVectorType>(indexType))
323 if (
const auto scalableVectorType =
324 std::dynamic_pointer_cast<const ScalableVectorType>(indexType))
334 static std::vector<std::shared_ptr<const rvsdg::Type>>
337 std::vector<std::shared_ptr<const rvsdg::Type>> indexTypes;
338 for (
const auto & index :
indices)
340 indexTypes.emplace_back(std::move(index->Type()));
346 static std::vector<std::shared_ptr<const rvsdg::Type>>
348 std::shared_ptr<const rvsdg::Type> baseAddressType,
349 const std::vector<std::shared_ptr<const rvsdg::Type>> & indexTypes)
351 std::vector types({ std::move(baseAddressType) });
352 types.insert(types.end(), indexTypes.begin(), indexTypes.end());
static std::shared_ptr< const FixedVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
static rvsdg::Input & getBaseAddressInput(rvsdg::Node &node)
std::string debug_string() const override
static std::shared_ptr< const rvsdg::Type > getResultType(const std::shared_ptr< const rvsdg::Type > &baseAddressType, const std::vector< std::shared_ptr< const rvsdg::Type > > &indexTypes)
GetElementPtrOperation(GetElementPtrOperation &&other) noexcept=default
static std::shared_ptr< const rvsdg::Type > getIndexedType(const std::shared_ptr< const rvsdg::Type > &gepType, const std::vector< rvsdg::Output * > &indices)
static size_t numIndices(const rvsdg::Node &node) noexcept
static std::vector< std::shared_ptr< const rvsdg::Type > > createOperandTypes(std::shared_ptr< const rvsdg::Type > baseAddressType, const std::vector< std::shared_ptr< const rvsdg::Type > > &indexTypes)
static std::unique_ptr< GetElementPtrOperation > createOperation(const std::shared_ptr< const rvsdg::Type > &baseAddressType, const std::vector< std::shared_ptr< const rvsdg::Type > > &indexTypes, const std::shared_ptr< const rvsdg::Type > &gepType)
static void checkBaseAddressType(const rvsdg::Type &type)
static rvsdg::Output * create(rvsdg::Output *baseAddress, const std::vector< rvsdg::Output * > &indices, std::shared_ptr< const rvsdg::Type > gepType)
std::shared_ptr< const rvsdg::Type > gepType_
GetElementPtrOperation(const GetElementPtrOperation &other)=default
static void checkIndexedType(const std::shared_ptr< const rvsdg::Type > &gepType, const std::vector< rvsdg::Output * > &indices)
static std::vector< std::shared_ptr< const rvsdg::Type > > extractIndexTypes(const std::vector< T * > &indices)
std::shared_ptr< const rvsdg::Type > getPointeeType() const noexcept
static const rvsdg::Input & getBaseAddressInput(const rvsdg::Node &node)
bool operator==(const Operation &other) const noexcept override
static rvsdg::Node::InputConstIteratorRange indices(const rvsdg::Node &node) noexcept
static std::optional< Constant > tryGetAsConstant(const rvsdg::SimpleNode &gepNode)
~GetElementPtrOperation() noexcept override
static rvsdg::SimpleNode & createNode(rvsdg::Output &baseAddress, const std::vector< rvsdg::Output * > &indices, const std::shared_ptr< const rvsdg::Type > &gepType)
static void checkIndexTypes(const std::vector< std::shared_ptr< const rvsdg::Type > > &indexTypes)
static std::optional< std::vector< rvsdg::Output * > > normalizeIdempotent(const GetElementPtrOperation &operation, const std::vector< rvsdg::Output * > &operands)
static std::unique_ptr< ThreeAddressCode > createTAC(const Variable *baseAddress, const std::vector< const Variable * > &offsets, std::shared_ptr< const rvsdg::Type > gepType)
std::unique_ptr< Operation > copy() const override
static std::shared_ptr< const PointerType > Create()
static std::shared_ptr< const ScalableVectorType > Create(std::shared_ptr< const rvsdg::Type > type, size_t size)
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
NodeInput * input(size_t index) const noexcept
virtual const Operation & GetOperation() const noexcept=0
rvsdg::Region * region() const noexcept
const std::shared_ptr< const rvsdg::Type > & Type() const noexcept
static SimpleNode & Create(Region ®ion, std::unique_ptr< Operation > operation, const std::vector< rvsdg::Output * > &operands)
NodeOutput * output(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.
int64_t getOffsetInBytes() const noexcept
std::vector< uint64_t > indices
std::shared_ptr< const rvsdg::Type > pointeeType