Skip to content

Commit d7282a3

Browse files
authored
[BugFix][LLVM] Fix insertDeclare API mismatch for ROCm-bundled LLVM 20 (#19390)
## Problem Closes #18709. 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 guard `#if TVM_LLVM_VERSION >= 200` in `codegen_llvm.cc` broke ROCm users because their LLVM reports version 20 but lacks the new overload, causing a compile error like: ``` error: no matching function for call to 'llvm::DIBuilder::insertDeclare(..., llvm::BasicBlock::iterator)' note: candidate: insertDeclare(..., llvm::Instruction*) ``` ## Fix Replace the version-number guard with a CMake `check_cxx_source_compiles` feature probe in `cmake/utils/FindLLVM.cmake`. The probe compiles a small test program that calls `insertDeclare` with `BasicBlock::iterator`. The result is exposed as the preprocessor macro `TVM_LLVM_INSERTDECLARE_USES_ITERATOR`. `cmake_push_check_state`/`cmake_pop_check_state` is used to avoid leaking `CMAKE_REQUIRED_*` variables into the rest of the build. Three call sites in `src/target/llvm/codegen_llvm.cc` are updated to use `#if TVM_LLVM_INSERTDECLARE_USES_ITERATOR` instead of `#if TVM_LLVM_VERSION >= 200`. **Behavior by configuration:** | LLVM build | Probe result | Macro set | Code path | |---|---|---|---| | Upstream LLVM >= 20 with new overload | Compiles | Yes | `BasicBlock::iterator` | | ROCm LLVM 20 (old overload) | Fails | No | `Instruction*` | | Any LLVM < 20 | Probe skipped | No | `Instruction*` | ## Testing Tested locally with LLVM 20.1.8 (Ubuntu package): ``` tests/python/codegen/test_target_codegen_llvm.py 39 passed ```
1 parent 21993a5 commit d7282a3

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

cmake/utils/FindLLVM.cmake

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,42 @@ macro(find_llvm use_llvm)
237237
message(FATAL_ERROR "TVM requires LLVM 15.0 or higher.")
238238
endif()
239239
message(STATUS "Found TVM_LLVM_HAS_AARCH64_TARGET=" ${TVM_LLVM_HAS_AARCH64_TARGET})
240+
241+
# Detect whether DIBuilder insertion APIs (insertDeclare,
242+
# insertDbgValueIntrinsic) accept BasicBlock::iterator as the insertion point
243+
# (upstream LLVM 20+) vs Instruction* (pre-LLVM 20 and ROCm-bundled LLVM 20,
244+
# which reports version 200 but retains the legacy Instruction* overload).
245+
if (${TVM_LLVM_VERSION} GREATER_EQUAL 200)
246+
include(CheckCXXSourceCompiles)
247+
include(CMakePushCheckState)
248+
cmake_push_check_state(RESET)
249+
set(CMAKE_REQUIRED_INCLUDES ${LLVM_INCLUDE_DIRS})
250+
# Only force -std= when the outer project hasn't already selected a
251+
# standard; signature-only probe does not need -fno-rtti. Use the
252+
# compiler-appropriate form so the probe works under MSVC as well.
253+
if(NOT CMAKE_CXX_STANDARD)
254+
if(MSVC)
255+
set(CMAKE_REQUIRED_FLAGS "/std:c++17")
256+
else()
257+
set(CMAKE_REQUIRED_FLAGS "-std=c++17")
258+
endif()
259+
endif()
260+
check_cxx_source_compiles("
261+
#include <llvm/IR/DIBuilder.h>
262+
#include <llvm/IR/Instructions.h>
263+
void f(llvm::DIBuilder* b, llvm::Value* v, llvm::DILocalVariable* var,
264+
llvm::DIExpression* e, const llvm::DILocation* dl,
265+
llvm::Instruction* i) {
266+
b->insertDeclare(v, var, e, dl, llvm::BasicBlock::iterator(i));
267+
b->insertDbgValueIntrinsic(v, var, e, dl, llvm::BasicBlock::iterator(i));
268+
}
269+
" TVM_LLVM_DIBUILDER_USES_ITERATOR)
270+
cmake_pop_check_state()
271+
if(TVM_LLVM_DIBUILDER_USES_ITERATOR)
272+
add_definitions(-DTVM_LLVM_DIBUILDER_USES_ITERATOR=1)
273+
message(STATUS "LLVM DIBuilder insertion APIs use BasicBlock::iterator")
274+
else()
275+
message(STATUS "LLVM DIBuilder insertion APIs use Instruction* (ROCm or older LLVM 20)")
276+
endif()
277+
endif()
240278
endmacro(find_llvm)

src/target/llvm/codegen_llvm.cc

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,7 +2147,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Function* f_llvm,
21472147

21482148
auto* store = builder.CreateStore(iter_param, paramAlloca);
21492149
auto* di_loc = llvm::DILocation::get(*ctx, 0, 0, di_subprogram_);
2150-
#if TVM_LLVM_VERSION >= 200
2150+
#if TVM_LLVM_DIBUILDER_USES_ITERATOR
21512151
dbg_info_->di_builder_->insertDeclare(
21522152
paramAlloca, param, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc),
21532153
llvm::BasicBlock::iterator(store));
@@ -2193,9 +2193,10 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va
21932193
// the SSA value directly rather than a memory location.
21942194
if (!llvm_value->getType()->isPointerTy()) {
21952195
if (insert_before) {
2196-
// LLVM 20+ changed insertDbgValueIntrinsic to take BasicBlock::iterator
2197-
// instead of Instruction* for the insertion point.
2198-
#if TVM_LLVM_VERSION >= 200
2196+
// Upstream LLVM 20+ changed insertDbgValueIntrinsic to take
2197+
// BasicBlock::iterator; ROCm-bundled LLVM 20 retains Instruction*.
2198+
// TVM_LLVM_DIBUILDER_USES_ITERATOR is set by CMake feature detection.
2199+
#if TVM_LLVM_DIBUILDER_USES_ITERATOR
21992200
dbg_info_->di_builder_->insertDbgValueIntrinsic(
22002201
llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc),
22012202
llvm::BasicBlock::iterator(insert_before));
@@ -2213,7 +2214,7 @@ void CodeGenLLVM::AddDebugInformation(llvm::Value* llvm_value, const Var& tir_va
22132214
}
22142215

22152216
if (insert_before) {
2216-
#if TVM_LLVM_VERSION >= 200
2217+
#if TVM_LLVM_DIBUILDER_USES_ITERATOR
22172218
dbg_info_->di_builder_->insertDeclare(
22182219
llvm_value, local_var, dbg_info_->di_builder_->createExpression(), llvm::DebugLoc(di_loc),
22192220
llvm::BasicBlock::iterator(insert_before));

0 commit comments

Comments
 (0)