From 70e8887ff2d156dac99e779845962380208d46aa Mon Sep 17 00:00:00 2001 From: Soowon Jeong Date: Sun, 12 Apr 2026 00:06:16 +0900 Subject: [PATCH 1/2] [BugFix][LLVM] Fix `insertDeclare` API mismatch for ROCm-bundled LLVM 20 ROCm ships its own LLVM 20 build that still uses the pre-LLVM-20 `Instruction*` overload of `DIBuilder::insertDeclare`, while upstream LLVM 20 switched to `BasicBlock::iterator`. The previous version-number guard `#if TVM_LLVM_VERSION >= 200` broke ROCm users on LLVM 20. Replace the version guard with a CMake `check_cxx_source_compiles` feature probe (`TVM_LLVM_INSERTDECLARE_USES_ITERATOR`) that compiles a small test program to detect which overload is actually available. Use `cmake_push_check_state`/`cmake_pop_check_state` to avoid leaking CMake check variables. Three call sites in `codegen_llvm.cc` are updated to use the new macro. Fixes #18709 --- cmake/utils/FindLLVM.cmake | 27 +++++++++++++++++++++++++++ src/target/llvm/codegen_llvm.cc | 11 ++++++----- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/cmake/utils/FindLLVM.cmake b/cmake/utils/FindLLVM.cmake index d35feef6877a..2be86d3b56a3 100644 --- a/cmake/utils/FindLLVM.cmake +++ b/cmake/utils/FindLLVM.cmake @@ -237,4 +237,31 @@ macro(find_llvm use_llvm) message(FATAL_ERROR "TVM requires LLVM 15.0 or higher.") endif() message(STATUS "Found TVM_LLVM_HAS_AARCH64_TARGET=" ${TVM_LLVM_HAS_AARCH64_TARGET}) + + # Detect whether DIBuilder::insertDeclare accepts BasicBlock::iterator + # as the insertion point (upstream LLVM 20+) vs Instruction* (pre-LLVM 20 + # and ROCm-bundled LLVM 20, which reports version 200 but lacks this overload). + if (${TVM_LLVM_VERSION} GREATER_EQUAL 200) + include(CheckCXXSourceCompiles) + include(CMakePushCheckState) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIRS}) + set(CMAKE_REQUIRED_FLAGS "-std=c++17 -fno-rtti") + check_cxx_source_compiles(" + #include + #include + void f(llvm::DIBuilder* b, llvm::Value* v, llvm::DILocalVariable* var, + llvm::DIExpression* e, const llvm::DILocation* dl, + llvm::Instruction* i) { + b->insertDeclare(v, var, e, dl, llvm::BasicBlock::iterator(i)); + } + " TVM_LLVM_INSERTDECLARE_USES_ITERATOR) + cmake_pop_check_state() + if(TVM_LLVM_INSERTDECLARE_USES_ITERATOR) + add_definitions(-DTVM_LLVM_INSERTDECLARE_USES_ITERATOR=1) + message(STATUS "LLVM DIBuilder::insertDeclare uses BasicBlock::iterator") + else() + message(STATUS "LLVM DIBuilder::insertDeclare uses Instruction* (ROCm or older LLVM 20)") + endif() + endif() endmacro(find_llvm) diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc index 3fcaaaf46d68..a1ee33d9cd0d 100644 --- a/src/target/llvm/codegen_llvm.cc +++ b/src/target/llvm/codegen_llvm.cc @@ -2147,7 +2147,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Function* f_llvm, auto* store = builder.CreateStore(iter_param, paramAlloca); auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, di_subprogram_); -#if TVM_LLVM_VERSION >= 200 +#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR dbg_info_->di_builder_->insertDeclare( paramAlloca, param, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(store)); @@ -2193,9 +2193,10 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va // the SSA value directly rather than a memory location. if (!llvm_value->getType()->isPointerTy()) { if (insert_before) { - // LLVM 20+ changed insertDbgValueIntrinsic to take BasicBlock::iterator - // instead of Instruction* for the insertion point. -#if TVM_LLVM_VERSION >= 200 + // Upstream LLVM 20+ changed insertDbgValueIntrinsic to take + // BasicBlock::iterator; ROCm-bundled LLVM 20 retains Instruction*. + // TVM_LLVM_INSERTDECLARE_USES_ITERATOR is set by CMake feature detection. +#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR dbg_info_->di_builder_->insertDbgValueIntrinsic( llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(insert_before)); @@ -2213,7 +2214,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va } if (insert_before) { -#if TVM_LLVM_VERSION >= 200 +#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR dbg_info_->di_builder_->insertDeclare( llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(insert_before)); From cf0311f90b1c4e56a2c2ad9cfbc1eaa4d246638c Mon Sep 17 00:00:00 2001 From: Soowon Jeong Date: Mon, 20 Apr 2026 12:43:43 +0900 Subject: [PATCH 2/2] [BugFix][LLVM] Broaden DIBuilder API probe for MSVC and insertDbgValueIntrinsic Address review feedback on #19390: - Rename the CMake feature flag to TVM_LLVM_DIBUILDER_USES_ITERATOR and extend the probe to also exercise insertDbgValueIntrinsic, so the macro accurately reflects every DIBuilder insertion site it gates. - Drop the unused -fno-rtti flag (probe is signature-only), skip the -std= flag when the outer project already sets CMAKE_CXX_STANDARD, and fall back to /std:c++17 under MSVC. Without this, MSVC builds against upstream LLVM 20 would silently take the Instruction* path and fail to compile. --- cmake/utils/FindLLVM.cmake | 29 ++++++++++++++++++++--------- src/target/llvm/codegen_llvm.cc | 8 ++++---- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/cmake/utils/FindLLVM.cmake b/cmake/utils/FindLLVM.cmake index 2be86d3b56a3..851e2acf54ee 100644 --- a/cmake/utils/FindLLVM.cmake +++ b/cmake/utils/FindLLVM.cmake @@ -238,15 +238,25 @@ macro(find_llvm use_llvm) endif() message(STATUS "Found TVM_LLVM_HAS_AARCH64_TARGET=" ${TVM_LLVM_HAS_AARCH64_TARGET}) - # Detect whether DIBuilder::insertDeclare accepts BasicBlock::iterator - # as the insertion point (upstream LLVM 20+) vs Instruction* (pre-LLVM 20 - # and ROCm-bundled LLVM 20, which reports version 200 but lacks this overload). + # Detect whether DIBuilder insertion APIs (insertDeclare, + # insertDbgValueIntrinsic) accept BasicBlock::iterator as the insertion point + # (upstream LLVM 20+) vs Instruction* (pre-LLVM 20 and ROCm-bundled LLVM 20, + # which reports version 200 but retains the legacy Instruction* overload). if (${TVM_LLVM_VERSION} GREATER_EQUAL 200) include(CheckCXXSourceCompiles) include(CMakePushCheckState) cmake_push_check_state(RESET) set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIRS}) - set(CMAKE_REQUIRED_FLAGS "-std=c++17 -fno-rtti") + # Only force -std= when the outer project hasn't already selected a + # standard; signature-only probe does not need -fno-rtti. Use the + # compiler-appropriate form so the probe works under MSVC as well. + if(NOT CMAKE_CXX_STANDARD) + if(MSVC) + set(CMAKE_REQUIRED_FLAGS "/std:c++17") + else() + set(CMAKE_REQUIRED_FLAGS "-std=c++17") + endif() + endif() check_cxx_source_compiles(" #include #include @@ -254,14 +264,15 @@ macro(find_llvm use_llvm) llvm::DIExpression* e, const llvm::DILocation* dl, llvm::Instruction* i) { b->insertDeclare(v, var, e, dl, llvm::BasicBlock::iterator(i)); + b->insertDbgValueIntrinsic(v, var, e, dl, llvm::BasicBlock::iterator(i)); } - " TVM_LLVM_INSERTDECLARE_USES_ITERATOR) + " TVM_LLVM_DIBUILDER_USES_ITERATOR) cmake_pop_check_state() - if(TVM_LLVM_INSERTDECLARE_USES_ITERATOR) - add_definitions(-DTVM_LLVM_INSERTDECLARE_USES_ITERATOR=1) - message(STATUS "LLVM DIBuilder::insertDeclare uses BasicBlock::iterator") + if(TVM_LLVM_DIBUILDER_USES_ITERATOR) + add_definitions(-DTVM_LLVM_DIBUILDER_USES_ITERATOR=1) + message(STATUS "LLVM DIBuilder insertion APIs use BasicBlock::iterator") else() - message(STATUS "LLVM DIBuilder::insertDeclare uses Instruction* (ROCm or older LLVM 20)") + message(STATUS "LLVM DIBuilder insertion APIs use Instruction* (ROCm or older LLVM 20)") endif() endif() endmacro(find_llvm) diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc index a1ee33d9cd0d..a78451a7415d 100644 --- a/src/target/llvm/codegen_llvm.cc +++ b/src/target/llvm/codegen_llvm.cc @@ -2147,7 +2147,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Function* f_llvm, auto* store = builder.CreateStore(iter_param, paramAlloca); auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, di_subprogram_); -#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR +#if TVM_LLVM_DIBUILDER_USES_ITERATOR dbg_info_->di_builder_->insertDeclare( paramAlloca, param, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(store)); @@ -2195,8 +2195,8 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va if (insert_before) { // Upstream LLVM 20+ changed insertDbgValueIntrinsic to take // BasicBlock::iterator; ROCm-bundled LLVM 20 retains Instruction*. - // TVM_LLVM_INSERTDECLARE_USES_ITERATOR is set by CMake feature detection. -#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR + // TVM_LLVM_DIBUILDER_USES_ITERATOR is set by CMake feature detection. +#if TVM_LLVM_DIBUILDER_USES_ITERATOR dbg_info_->di_builder_->insertDbgValueIntrinsic( llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(insert_before)); @@ -2214,7 +2214,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va } if (insert_before) { -#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR +#if TVM_LLVM_DIBUILDER_USES_ITERATOR dbg_info_->di_builder_->insertDeclare( llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc), llvm::BasicBlock::iterator(insert_before));