diff --git a/jlm/llvm/Makefile.sub b/jlm/llvm/Makefile.sub index 7fc105124..8d9dc6c08 100644 --- a/jlm/llvm/Makefile.sub +++ b/jlm/llvm/Makefile.sub @@ -27,6 +27,7 @@ libllvm_SOURCES = \ jlm/llvm/ir/operators/alloca.cpp \ jlm/llvm/ir/operators/call.cpp \ jlm/llvm/ir/operators/delta.cpp \ + jlm/llvm/ir/operators/FunctionPointer.cpp \ jlm/llvm/ir/operators/GetElementPtr.cpp \ jlm/llvm/ir/operators/lambda.cpp \ jlm/llvm/ir/operators/Load.cpp \ @@ -123,6 +124,7 @@ libllvm_HEADERS = \ jlm/llvm/ir/operators/Load.hpp \ jlm/llvm/ir/operators/MemCpy.hpp \ jlm/llvm/ir/operators/MemoryStateOperations.hpp \ + jlm/llvm/ir/operators/FunctionPointer.hpp \ jlm/llvm/ir/operators/GetElementPtr.hpp \ jlm/llvm/ir/operators/delta.hpp \ jlm/llvm/ir/operators/Store.hpp \ diff --git a/jlm/llvm/backend/jlm2llvm/instruction.cpp b/jlm/llvm/backend/jlm2llvm/instruction.cpp index 5272ccc73..c5aeff41e 100644 --- a/jlm/llvm/backend/jlm2llvm/instruction.cpp +++ b/jlm/llvm/backend/jlm2llvm/instruction.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -1001,6 +1002,26 @@ convert( return nullptr; } +static ::llvm::Value * +convert( + const PointerToFunctionOperation &, + const std::vector & operands, + ::llvm::IRBuilder<> &, + context & ctx) +{ + return ctx.value(operands[0]); +} + +static ::llvm::Value * +convert( + const FunctionToPointerOperation &, + const std::vector & operands, + ::llvm::IRBuilder<> &, + context & ctx) +{ + return ctx.value(operands[0]); +} + template static ::llvm::Value * convert( @@ -1094,7 +1115,9 @@ convert_operation( { typeid(CallEntryMemoryStateMergeOperation), convert }, { typeid(CallExitMemoryStateSplitOperation), - convert } }); + convert }, + { typeid(PointerToFunctionOperation), convert }, + { typeid(FunctionToPointerOperation), convert } }); /* FIXME: AddrSpaceCast instruction is not supported */ JLM_ASSERT(map.find(std::type_index(typeid(op))) != map.end()); diff --git a/jlm/llvm/ir/operators/FunctionPointer.cpp b/jlm/llvm/ir/operators/FunctionPointer.cpp new file mode 100644 index 000000000..35040dff9 --- /dev/null +++ b/jlm/llvm/ir/operators/FunctionPointer.cpp @@ -0,0 +1,158 @@ +/* + * Copyright 2024 Helge Bahmann + * See COPYING for terms of redistribution. + */ + +#include +#include + +namespace jlm::llvm +{ + +FunctionToPointerOperation::~FunctionToPointerOperation() noexcept +{} + +FunctionToPointerOperation::FunctionToPointerOperation(std::shared_ptr fn) + : unary_op(fn, llvm::PointerType::Create()), + FunctionType_(std::move(fn)) +{} + +bool +FunctionToPointerOperation::operator==(const Operation & other) const noexcept +{ + if (auto o = dynamic_cast(&other)) + { + return *FunctionType() == *o->FunctionType(); + } + else + { + return false; + } +} + +[[nodiscard]] std::string +FunctionToPointerOperation::debug_string() const +{ + return "FunPtr(" + FunctionType()->debug_string() + ")"; +} + +[[nodiscard]] std::unique_ptr +FunctionToPointerOperation::copy() const +{ + return Create(FunctionType()); +} + +rvsdg::unop_reduction_path_t +FunctionToPointerOperation::can_reduce_operand(const jlm::rvsdg::output * arg) const noexcept +{ + if (auto node = rvsdg::TryGetOwnerNode(*arg)) + { + if (auto op = dynamic_cast(&node->GetOperation())) + { + if (*op->FunctionType() == *FunctionType()) + { + return rvsdg::unop_reduction_inverse; + } + } + } + return rvsdg::unop_reduction_none; +} + +jlm::rvsdg::output * +FunctionToPointerOperation::reduce_operand( + rvsdg::unop_reduction_path_t path, + jlm::rvsdg::output * arg) const +{ + if (auto node = rvsdg::TryGetOwnerNode(*arg)) + { + if (auto op = dynamic_cast(&node->GetOperation())) + { + if (*op->FunctionType() == *FunctionType()) + { + return node->input(0)->origin(); + } + } + } + return arg; +} + +std::unique_ptr +FunctionToPointerOperation::Create(std::shared_ptr fn) +{ + return std::make_unique(std::move(fn)); +} + +PointerToFunctionOperation::~PointerToFunctionOperation() noexcept +{} + +PointerToFunctionOperation::PointerToFunctionOperation(std::shared_ptr fn) + : unary_op(llvm::PointerType::Create(), fn), + FunctionType_(std::move(fn)) +{} + +bool +PointerToFunctionOperation::operator==(const Operation & other) const noexcept +{ + if (auto o = dynamic_cast(&other)) + { + return *FunctionType() == *o->FunctionType(); + } + else + { + return false; + } +} + +[[nodiscard]] std::string +PointerToFunctionOperation::debug_string() const +{ + return "PtrFun(" + FunctionType()->debug_string() + ")"; +} + +[[nodiscard]] std::unique_ptr +PointerToFunctionOperation::copy() const +{ + return Create(FunctionType()); +} + +rvsdg::unop_reduction_path_t +PointerToFunctionOperation::can_reduce_operand(const jlm::rvsdg::output * arg) const noexcept +{ + if (auto node = rvsdg::TryGetOwnerNode(*arg)) + { + if (auto op = dynamic_cast(&node->GetOperation())) + { + if (*op->FunctionType() == *FunctionType()) + { + return rvsdg::unop_reduction_inverse; + } + } + } + return rvsdg::unop_reduction_none; +} + +jlm::rvsdg::output * +PointerToFunctionOperation::reduce_operand( + rvsdg::unop_reduction_path_t path, + jlm::rvsdg::output * arg) const +{ + if (auto node = rvsdg::TryGetOwnerNode(*arg)) + { + if (auto op = dynamic_cast(&node->GetOperation())) + { + if (*op->FunctionType() == *FunctionType()) + { + return node->input(0)->origin(); + } + } + } + return arg; +} + +std::unique_ptr +PointerToFunctionOperation::Create(std::shared_ptr fn) +{ + return std::make_unique(std::move(fn)); +} + +} diff --git a/jlm/llvm/ir/operators/FunctionPointer.hpp b/jlm/llvm/ir/operators/FunctionPointer.hpp new file mode 100644 index 000000000..b7b0d4743 --- /dev/null +++ b/jlm/llvm/ir/operators/FunctionPointer.hpp @@ -0,0 +1,95 @@ +/* + * Copyright 2024 Helge Bahmann + * See COPYING for terms of redistribution. + */ + +#ifndef JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP +#define JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP + +#include +#include +#include +#include + +namespace jlm::llvm +{ + +/** + \brief Get address of compiled function object. + */ +class FunctionToPointerOperation final : public rvsdg::unary_op +{ +public: + ~FunctionToPointerOperation() noexcept override; + + FunctionToPointerOperation(std::shared_ptr fn); + + bool + operator==(const Operation & other) const noexcept override; + + [[nodiscard]] std::string + debug_string() const override; + + [[nodiscard]] std::unique_ptr + copy() const override; + + rvsdg::unop_reduction_path_t + can_reduce_operand(const jlm::rvsdg::output * arg) const noexcept override; + + jlm::rvsdg::output * + reduce_operand(rvsdg::unop_reduction_path_t path, jlm::rvsdg::output * arg) const override; + + static std::unique_ptr + Create(std::shared_ptr fn); + + inline const std::shared_ptr & + FunctionType() const noexcept + { + return FunctionType_; + } + +private: + std::shared_ptr FunctionType_; +}; + +/** + \brief Interpret pointer as callable function. + */ +class PointerToFunctionOperation final : public rvsdg::unary_op +{ +public: + ~PointerToFunctionOperation() noexcept override; + + PointerToFunctionOperation(std::shared_ptr fn); + + bool + operator==(const Operation & other) const noexcept override; + + [[nodiscard]] std::string + debug_string() const override; + + [[nodiscard]] std::unique_ptr + copy() const override; + + rvsdg::unop_reduction_path_t + can_reduce_operand(const jlm::rvsdg::output * arg) const noexcept override; + + jlm::rvsdg::output * + reduce_operand(rvsdg::unop_reduction_path_t path, jlm::rvsdg::output * arg) const override; + + static std::unique_ptr + Create(std::shared_ptr fn); + + inline const std::shared_ptr & + FunctionType() const noexcept + { + return FunctionType_; + } + +private: + std::shared_ptr FunctionType_; +}; + +} + +#endif // JLM_LLVM_IR_OPERATORS_FUNCTIONPOINTER_HPP diff --git a/jlm/llvm/opt/InvariantValueRedirection.cpp b/jlm/llvm/opt/InvariantValueRedirection.cpp index 8b842532f..c6253d83a 100644 --- a/jlm/llvm/opt/InvariantValueRedirection.cpp +++ b/jlm/llvm/opt/InvariantValueRedirection.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include #include @@ -84,6 +85,12 @@ InvariantValueRedirection::RedirectInRootRegion(rvsdg::Graph & rvsdg) // Nothing needs to be done. // Delta nodes are irrelevant for invariant value redirection. } + else if ( + is(node->GetOperation()) + || is(node->GetOperation())) + { + // Nothing needs to be done. + } else { JLM_UNREACHABLE("Unhandled node type."); diff --git a/jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.cpp b/jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.cpp index 62fa0fba5..48728abba 100644 --- a/jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.cpp +++ b/jlm/llvm/opt/alias-analyses/RegionAwareMemoryNodeProvider.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -874,6 +875,14 @@ RegionAwareMemoryNodeProvider::Propagate(const RvsdgModule & rvsdgModule) // Nothing needs to be done for delta nodes. continue; } + else if ( + is(node->GetOperation()) + || is(node->GetOperation())) + { + // Few operators may appear as top-level constructs and simply must + // be ignored. + continue; + } else { JLM_UNREACHABLE("Unhandled node type!"); diff --git a/jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.cpp b/jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.cpp index d0f4313ea..eede0c420 100644 --- a/jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.cpp +++ b/jlm/llvm/opt/alias-analyses/TopDownMemoryNodeEliminator.cpp @@ -3,6 +3,7 @@ * See COPYING for terms of redistribution. */ +#include #include #include #include @@ -492,6 +493,12 @@ TopDownMemoryNodeEliminator::EliminateTopDownRootRegion(rvsdg::Region & region) { // Nothing needs to be done. } + else if ( + is(node->GetOperation()) + || is(node->GetOperation())) + { + // Nothing needs to be done. + } else { JLM_UNREACHABLE("Unhandled node type!");