This is an automated email from the ASF dual-hosted git repository.

tlopex pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm.git


The following commit(s) were added to refs/heads/main by this push:
     new b29b52fdf4 [Fix][LLVM] Preserve 64-bit AllocBuffer extents (#20141)
b29b52fdf4 is described below

commit b29b52fdf42e5dd792715e861dee80c6f26c731b
Author: Igor Stadnyk <[email protected]>
AuthorDate: Tue Sep 8 16:54:47 2026 +0100

    [Fix][LLVM] Preserve 64-bit AllocBuffer extents (#20141)
    
    Fixes #20125.
    
    ## What changed
    
    LLVM CPU code generation now keeps constant `AllocBuffer` extents as
    signed 64-bit values through stack allocation emission instead of
    narrowing them to `int32_t`. The temporary-allocation alignment helper
    accepts the same width and avoids multiplying when a large allocation
    cannot reduce the requested alignment, preventing overflow in that
    calculation.
    
    This change is intentionally limited to the CPU `CodeGenLLVM` path. The
    separate NVPTX and AMDGPU overrides described in the issue remain out of
    scope.
    
    ## Why
    
    An extent of `2**32 + 1` previously wrapped to one before
    `CreateAlloca`, producing a one-element stack allocation followed by an
    `i64 4294967296` element access in unoptimized TIR-X LLVM IR. The
    generated module could therefore contain an out-of-bounds access even
    though the original extent was valid as an `int64_t`.
    
    The regression test only compiles and inspects LLVM IR; it does not
    execute or materialize the very large allocation. It covers extents that
    previously wrapped to one and four elements.
    
    ## Validation
    
    - New regression on the unmodified base: 2 failures
    - New regression after the fix: 2 passed
    - `tests/python/codegen/test_target_codegen_llvm.py`: 380 passed
    - Rebuilt all 65 affected C++ units, including the NVPTX and AMDGPU
    callers of the alignment helper
    - Changed-file pre-commit hooks and `git diff --check`: passed
    - Compile-only boundary probes through `INT64_MAX - 3`: exact `i64`
    allocation counts, with no allocation executed
    
    ## AI assistance
    
    This PR was prepared with OpenAI Codex. The patch was derived from the
    repository and the issue's documented failure mode; no external
    third-party code was copied into the change.
    
    Generated-by: OpenAI Codex
    
    Co-authored-by: Igor Stadnyk <[email protected]>
---
 src/target/llvm/codegen_llvm.cc                  |  4 ++--
 src/tirx/transform/ir_utils.h                    | 13 +++++++++----
 tests/python/codegen/test_target_codegen_llvm.py | 23 +++++++++++++++++++++++
 3 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/target/llvm/codegen_llvm.cc b/src/target/llvm/codegen_llvm.cc
index 3ab326c559..2ced6e7847 100644
--- a/src/target/llvm/codegen_llvm.cc
+++ b/src/target/llvm/codegen_llvm.cc
@@ -2191,7 +2191,7 @@ void CodeGenLLVM::VisitStmt_(const AllocBufferNode* op) {
 
   const IntImmNode* dim_imm = op->buffer->shape[0].as<IntImmNode>();
   TVM_FFI_ICHECK(dim_imm) << "Can only handle constant size stack allocation";
-  int32_t constant_size = static_cast<int32_t>(dim_imm->value);
+  int64_t constant_size = dim_imm->value;
   TVM_FFI_ICHECK_GT(constant_size, 0) << "Can only handle constant size stack 
allocation";
 
   StorageInfo& info = alloc_storage_info_[op->buffer.get()];
@@ -2206,7 +2206,7 @@ void CodeGenLLVM::VisitStmt_(const AllocBufferNode* op) {
     info.alignment = 16;
   }
   llvm::AllocaInst* alloca = WithFunctionEntry([&]() {
-    return builder_->CreateAlloca(DTypeToLLVMType(op->buffer->dtype), 
ConstInt32(constant_size));
+    return builder_->CreateAlloca(DTypeToLLVMType(op->buffer->dtype), 
ConstInt64(constant_size));
   });
   auto alignment = static_cast<unsigned>(alloca->getAlign().value());
   if (alignment < static_cast<unsigned>(info.alignment)) {
diff --git a/src/tirx/transform/ir_utils.h b/src/tirx/transform/ir_utils.h
index 9dcd0431a4..9ad1099a91 100644
--- a/src/tirx/transform/ir_utils.h
+++ b/src/tirx/transform/ir_utils.h
@@ -181,12 +181,17 @@ inline PrimType APIType(const PrimType& t) {
  * \param const_size The constant size of the array.
  * \return the alignment
  */
-inline int GetTempAllocaAlignment(const PrimType& type, int32_t const_size) {
+inline int GetTempAllocaAlignment(const PrimType& type, int64_t const_size) {
   int align = runtime::kTempAllocaAlignment;
   if (const_size > 0) {
-    int64_t const_s = static_cast<int64_t>(const_size) * type.StorageBytes();
-    while (align > const_s) {
-      align = align / 2;
+    int64_t element_bytes = type.StorageBytes();
+    // Only compute the total size when it can reduce the alignment. This also 
avoids
+    // overflowing for very large allocations.
+    if (element_bytes > 0 && const_size <= (align - 1) / element_bytes) {
+      int64_t const_s = const_size * element_bytes;
+      while (align > const_s) {
+        align = align / 2;
+      }
     }
   }
   return align;
diff --git a/tests/python/codegen/test_target_codegen_llvm.py 
b/tests/python/codegen/test_target_codegen_llvm.py
index bdf617ff54..9e8c091310 100644
--- a/tests/python/codegen/test_target_codegen_llvm.py
+++ b/tests/python/codegen/test_target_codegen_llvm.py
@@ -957,6 +957,29 @@ def test_llvm_order_functions():
     assert matches == sorted(matches)
 
 
[email protected](not env.has_llvm(), reason="need llvm")
[email protected]("extent", [2**32 + 1, 2**32 + 4])
+def test_llvm_large_stack_allocation_uses_64bit_extent(extent):
+    @T.prim_func(s_tir=True)
+    def main(A: T.Buffer((1,), "float32")):
+        B = T.alloc_buffer(
+            (extent,),
+            "float32",
+            scope="global",
+            annotations={"disable_lower_builtin": True},
+        )
+        A[0] = B[extent - 1]
+
+    module = tvm.tirx.build(
+        main,
+        target={"kind": "llvm", "opt-level": 0},
+        pipeline="tirx",
+    )
+    llvm_ir = module.inspect_source("ll")
+
+    assert re.search(rf"alloca float, i64 {extent}(?:,|$)", llvm_ir)
+
+
 @pytest.mark.skipif(not env.has_llvm(), reason="need llvm")
 @tvm.testing.skip_if_32bit
 def test_llvm_import():

Reply via email to