-
Notifications
You must be signed in to change notification settings - Fork 4.3k
GH-51245: [C++][Compute][Gandiva] Add support for LLVM 23.1 #51266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,4 +16,4 @@ | |
| # under the License. | ||
|
|
||
| clang | ||
| llvmdev<23 | ||
| llvmdev<24 | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -481,8 +481,8 @@ struct UnboxScalar<Decimal256Type> { | |
|
|
||
| template <typename T, typename VisitFunc, typename NullFunc> | ||
| requires std::is_void_v<std::invoke_result_t<VisitFunc, typename GetViewType<T>::T>> | ||
| static void VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, | ||
| NullFunc&& null_func) { | ||
| void VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LLVM 23 added
I don't think there's any harm in removing |
||
| NullFunc&& null_func) { | ||
| VisitArraySpanInline<T>( | ||
| arr, | ||
| [&](typename GetViewType<T>::PhysicalType v) { | ||
|
|
@@ -494,8 +494,8 @@ static void VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, | |
| template <typename T, typename VisitFunc, typename NullFunc> | ||
| requires std::is_same_v<std::invoke_result_t<VisitFunc, typename GetViewType<T>::T>, | ||
| Status> | ||
| static Status VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, | ||
| NullFunc&& null_func) { | ||
| Status VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_func, | ||
| NullFunc&& null_func) { | ||
| return VisitArraySpanInline<T>( | ||
| arr, | ||
| [&](typename GetViewType<T>::PhysicalType v) { | ||
|
|
@@ -507,8 +507,8 @@ static Status VisitArrayValuesInline(const ArraySpan& arr, VisitFunc&& valid_fun | |
| // Like VisitArrayValuesInline, but for binary functions. | ||
|
|
||
| template <typename Arg0Type, typename Arg1Type, typename VisitFunc, typename NullFunc> | ||
| static void VisitTwoArrayValuesInline(const ArraySpan& arr0, const ArraySpan& arr1, | ||
| VisitFunc&& valid_func, NullFunc&& null_func) { | ||
| void VisitTwoArrayValuesInline(const ArraySpan& arr0, const ArraySpan& arr1, | ||
| VisitFunc&& valid_func, NullFunc&& null_func) { | ||
| ArrayIterator<Arg0Type> arr0_it(arr0); | ||
| ArrayIterator<Arg1Type> arr1_it(arr1); | ||
|
|
||
|
|
@@ -584,7 +584,7 @@ namespace applicator { | |
| // static Status Call(KernelContext*, const Scalar& arg0, const ArraySpan& arg1, | ||
| // ExecResult* out) | ||
| template <typename Operator> | ||
| static Status SimpleBinary(KernelContext* ctx, const ExecSpan& batch, ExecResult* out) { | ||
| Status SimpleBinary(KernelContext* ctx, const ExecSpan& batch, ExecResult* out) { | ||
| if (batch.length == 0) return Status::OK(); | ||
|
|
||
| if (batch[0].is_array()) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1191,21 +1191,21 @@ constexpr int64_t kMillisecondsInDay = 86400000; | |
|
|
||
| // date to date | ||
| template <typename To> | ||
| enable_if_t<std::is_same<To, Date64Scalar>::value, Result<std::shared_ptr<Scalar>>> | ||
| enable_if_t<std::is_same<To, Date64Type>::value, Result<std::shared_ptr<Scalar>>> | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is another issue exposed by |
||
| CastImpl(const Date32Scalar& from, std::shared_ptr<DataType> to_type) { | ||
| return std::make_shared<Date64Scalar>(from.value * kMillisecondsInDay, | ||
| std::move(to_type)); | ||
| } | ||
| template <typename To> | ||
| enable_if_t<std::is_same<To, Date32Scalar>::value, Result<std::shared_ptr<Scalar>>> | ||
| enable_if_t<std::is_same<To, Date32Type>::value, Result<std::shared_ptr<Scalar>>> | ||
| CastImpl(const Date64Scalar& from, std::shared_ptr<DataType> to_type) { | ||
| return std::make_shared<Date32Scalar>( | ||
| static_cast<int32_t>(from.value / kMillisecondsInDay), std::move(to_type)); | ||
| } | ||
|
|
||
| // timestamp to date | ||
| template <typename To> | ||
| enable_if_t<std::is_same<To, Date64Scalar>::value, Result<std::shared_ptr<Scalar>>> | ||
| enable_if_t<std::is_same<To, Date64Type>::value, Result<std::shared_ptr<Scalar>>> | ||
| CastImpl(const TimestampScalar& from, std::shared_ptr<DataType> to_type) { | ||
| ARROW_ASSIGN_OR_RAISE( | ||
| auto millis, | ||
|
|
@@ -1214,7 +1214,7 @@ CastImpl(const TimestampScalar& from, std::shared_ptr<DataType> to_type) { | |
| std::move(to_type)); | ||
| } | ||
| template <typename To> | ||
| enable_if_t<std::is_same<To, Date32Scalar>::value, Result<std::shared_ptr<Scalar>>> | ||
| enable_if_t<std::is_same<To, Date32Type>::value, Result<std::shared_ptr<Scalar>>> | ||
| CastImpl(const TimestampScalar& from, std::shared_ptr<DataType> to_type) { | ||
| ARROW_ASSIGN_OR_RAISE( | ||
| auto millis, | ||
|
|
@@ -1225,7 +1225,7 @@ CastImpl(const TimestampScalar& from, std::shared_ptr<DataType> to_type) { | |
|
|
||
| // date to timestamp | ||
| template <typename To, typename From> | ||
| enable_if_timestamp<Result<std::shared_ptr<To>>> CastImpl( | ||
| enable_if_timestamp<To, Result<std::shared_ptr<Scalar>>> CastImpl( | ||
| const DateScalar<From>& from, std::shared_ptr<DataType> to_type) { | ||
| using ToScalar = typename TypeTraits<To>::ScalarType; | ||
| int64_t millis = from.value; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -131,6 +131,8 @@ template <typename T> | |
| arrow::Result<T> AsArrowResult(llvm::Expected<T>& expected, | ||
| const std::string& error_context) { | ||
| if (!expected) { | ||
| // NOTE: llvm::handleAllErrors() fails linking with RTTI-disabled LLVM builds | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment was supposed to be moved here from line 425 during a previous code refactoring, but it was overlooked. |
||
| // (ARROW-5148) | ||
| return Status::CodeGenError(error_context, llvm::toString(expected.takeError())); | ||
| } | ||
| return std::move(expected.get()); | ||
|
|
@@ -198,24 +200,34 @@ void AddProcessSymbol(llvm::orc::LLJIT& lljit) { | |
| } | ||
|
|
||
| #ifdef JIT_LINK_SUPPORTED | ||
| # if LLVM_VERSION_MAJOR < 23 | ||
| Result<std::unique_ptr<llvm::jitlink::InProcessMemoryManager>> CreateMemmoryManager() { | ||
| auto maybe_mem_manager = llvm::jitlink::InProcessMemoryManager::Create(); | ||
| return AsArrowResult(maybe_mem_manager, "Could not create memory manager: "); | ||
| } | ||
| # endif | ||
|
|
||
| Status UseJITLinkIfEnabled(llvm::orc::LLJITBuilder& jit_builder) { | ||
| static auto maybe_use_jit_link = ::arrow::internal::GetEnvVar("GANDIVA_USE_JIT_LINK"); | ||
| if (maybe_use_jit_link.ok()) { | ||
| # if LLVM_VERSION_MAJOR >= 23 | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. llvm/llvm-project#192214 added one more parameter. |
||
| jit_builder.setObjectLinkingLayerCreator( | ||
| [](llvm::orc::ExecutionSession& ES, | ||
| llvm::jitlink::JITLinkMemoryManager& memory_manager) { | ||
| return std::make_unique<llvm::orc::ObjectLinkingLayer>(ES, memory_manager); | ||
| }); | ||
| # else | ||
| ARROW_ASSIGN_OR_RAISE(static auto memory_manager, CreateMemmoryManager()); | ||
| # if LLVM_VERSION_MAJOR >= 21 | ||
| # if LLVM_VERSION_MAJOR >= 21 | ||
| jit_builder.setObjectLinkingLayerCreator([&](llvm::orc::ExecutionSession& ES) { | ||
| return std::make_unique<llvm::orc::ObjectLinkingLayer>(ES, *memory_manager); | ||
| }); | ||
| # else | ||
| # else | ||
| jit_builder.setObjectLinkingLayerCreator( | ||
| [&](llvm::orc::ExecutionSession& ES, const llvm::Triple& TT) { | ||
| return std::make_unique<llvm::orc::ObjectLinkingLayer>(ES, *memory_manager); | ||
| }); | ||
| # endif | ||
| # endif | ||
| } | ||
| return Status::OK(); | ||
|
|
@@ -261,13 +273,8 @@ Result<std::unique_ptr<llvm::orc::LLJIT>> BuildJIT( | |
| return jit; | ||
| } | ||
|
|
||
| arrow::Status VerifyAndLinkModule( | ||
| llvm::Module& dest_module, | ||
| llvm::Expected<std::unique_ptr<llvm::Module>> src_module_or_error) { | ||
| ARROW_ASSIGN_OR_RAISE( | ||
| auto src_ir_module, | ||
| AsArrowResult(src_module_or_error, "Failed to verify and link module: ")); | ||
|
|
||
| arrow::Status VerifyAndLinkModule(llvm::Module& dest_module, | ||
| std::unique_ptr<llvm::Module> src_ir_module) { | ||
| src_ir_module->setDataLayout(dest_module.getDataLayout()); | ||
|
|
||
| std::string error_info; | ||
|
|
@@ -282,6 +289,14 @@ arrow::Status VerifyAndLinkModule( | |
| return Status::OK(); | ||
| } | ||
|
|
||
| void RemoveBuildTargetAttributes(llvm::Module& module) { | ||
| for (auto& function : module.functions()) { | ||
| function.removeFnAttr("target-cpu"); | ||
| function.removeFnAttr("target-features"); | ||
| function.removeFnAttr("tune-cpu"); | ||
| } | ||
| } | ||
|
|
||
| } // namespace | ||
|
|
||
| Status Engine::SetLLVMObjectCache(GandivaObjectCache& object_cache) { | ||
|
|
@@ -422,10 +437,18 @@ Status Engine::LoadPreCompiledIR() { | |
| /// Parse the IR module. | ||
| llvm::Expected<std::unique_ptr<llvm::Module>> module_or_error = | ||
| llvm::getOwningLazyBitcodeModule(std::move(buffer), *context()); | ||
| // NOTE: llvm::handleAllErrors() fails linking with RTTI-disabled LLVM builds | ||
| // (ARROW-5148) | ||
| ARROW_RETURN_NOT_OK(VerifyAndLinkModule(*module_, std::move(module_or_error))); | ||
| return Status::OK(); | ||
| ARROW_ASSIGN_OR_RAISE( | ||
| auto src_ir_module, | ||
| AsArrowResult(module_or_error, "Failed to verify and link module: ")); | ||
|
|
||
| // Built-in bitcode is JIT-compiled on the runtime host. Do not retain the target | ||
| // selected by Clang when the bitcode was built. | ||
|
pitrou marked this conversation as resolved.
|
||
| // LLVM 23 checks target-feature compatibility even for alwaysinline functions and | ||
| // prevents inlining on a mismatch. See the LLVM 23 release notes: | ||
| // https://releases.llvm.org/23.1.0/docs/ReleaseNotes.html#changes-to-the-llvm-ir | ||
| RemoveBuildTargetAttributes(*src_ir_module); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The requirements for inlining have become stricter in LLVM 23.
|
||
|
|
||
| return VerifyAndLinkModule(*module_, std::move(src_ir_module)); | ||
| } | ||
|
|
||
| static llvm::MemoryBufferRef AsLLVMMemoryBuffer(const arrow::Buffer& arrow_buffer) { | ||
|
|
@@ -439,7 +462,10 @@ Status Engine::LoadExternalPreCompiledIR() { | |
| for (const auto& buffer : buffers) { | ||
| auto llvm_memory_buffer_ref = AsLLVMMemoryBuffer(*buffer); | ||
| auto module_or_error = llvm::parseBitcodeFile(llvm_memory_buffer_ref, *context()); | ||
| ARROW_RETURN_NOT_OK(VerifyAndLinkModule(*module_, std::move(module_or_error))); | ||
| ARROW_ASSIGN_OR_RAISE( | ||
| auto src_ir_module, | ||
| AsArrowResult(module_or_error, "Failed to verify and link module: ")); | ||
| ARROW_RETURN_NOT_OK(VerifyAndLinkModule(*module_, std::move(src_ir_module))); | ||
|
Comment on lines
463
to
+468
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment by Copilot is wrong, isn't it? Or should we actually force the precompiled bitcode's build target attributes to the same ones as the function registry? |
||
| } | ||
|
|
||
| return Status::OK(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a template function which doesn't have any callers.