Skip to content

[Bug] Unsigned conditions crash block access-region analysis with an internally generated negative constant #20343

Description

@sepcnt

Expected behavior

Block access-region analysis should handle valid uint32/uint64 conditions without crashing. If an unsigned predicate cannot be solved, conservatively including both branches is sufficient.

Actual behavior

Analyzing if_then_else(mask != 0, data[0], data[3]) with an unsigned mask raises:

tvm.error.InternalError: cannot make uint from negative value -1

There is no negative constant in the input program, and all buffer accesses are in bounds. Both uint32 and uint64 reproduce; the int32 control passes. An explicit mask == 0 condition also reproduces.

The failure occurs when analyzing the implicit else condition, mask == 0. ConditionalBoundsContext::TrySolveCondition accepts unsigned variables and passes the condition to SolveInequalitiesToRange / SolveLinearInequalities. The solver constructs signed mathematical coefficients using the program variable's unsigned type, for example:

PrimExpr c_pos = MakeConst(v_ty, neg.first / first_gcd);

This attempts to represent an internally generated -1 as an unsigned constant. The issue is a mismatch between conditional-analysis eligibility and the inequality solver's supported arithmetic domain, not an invalid user literal.

Environment

  • Apache TVM main, commit cc0f9f07c17c8118a781fdca55f7fe45f7de916a (0.26.dev0).
  • Windows, Python 3.12.13, locally built TVM compiler/runtime DLLs.
  • Reproduced directly in Apache TVM, without TileLang. No GPU execution or LLVM code generation is required.

Steps to reproduce

Run this script against the above revision:

from tvm import s_tir, tirx

mask_buffer = tirx.decl_buffer((1,), "uint32", name="mask_buffer")
data = tirx.decl_buffer((4,), "int32", name="data")
output = tirx.decl_buffer((1,), "int32", name="output")
mask = tirx.Var("mask", "uint32")

body = tirx.SeqStmt([
    tirx.Bind(mask, mask_buffer[0]),
    tirx.BufferStore(
        output, tirx.if_then_else(mask != 0, data[0], data[3]), [0]
    ),
])
block = tirx.SBlock([], [], [], "conditional_read", body)
buffers = {buf: buf for buf in (mask_buffer, data, output)}

print(s_tir.analysis.get_sblock_access_region(block, buffers))

Replace both uint32 occurrences with uint64 to reproduce the same error, or with int32 for the passing control. The expected conservative read region for data is [0:4].

Triage

  • needs-triage
  • type: bug

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triagePRs or issues that need to be investigated by maintainers to find the right assignees to address ittype: bug

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions