Skip to content

Conversation

@kurisu6912
Copy link
Collaborator

@kurisu6912 kurisu6912 commented Dec 2, 2025

This pr integrates Z3 into the TVM arith analyzer.

  • Only support integer expressions. TVM lanes, vscales are not supported.
  • It uses the Z3 integer theorem to prove expressions in TVM

TODO

Added API

  • analyzer.get_smtlib2: Returns a SMTLIB2 format including all constraints, variables and debug informations
  • analyzer.get_smtlib2(expr): Based on get_smtlib2 and adding expr as the prove target
  • analyzer.set_z3_timeout_ms(t): Set z3 timeout in millseconds
  • analyzer.set_z3_max_step(step): Set z3 max step
  • analyzer.get_z3_stats(): Return z3 statistic information (in str)

Example

from tvm.tir.expr import Var, And
from tvm.arith import Analyzer
analyzer = Analyzer()
a = Var('a', 'int32')
b = Var('b', 'int32')
c = Var('c', 'int32')
with analyzer.constraint_scope(And(And(a > 0, b > 0), c > 0)):
    try_to_prove = (a - b) // c * c + b <= a
    print(analyzer.can_prove(try_to_prove))
    print(analyzer.get_smtlib2())
    print(analyzer.get_smtlib2(try_to_prove))
    print(analyzer.get_z3_stats())

This example gives the proving result True.

analyzer.get_smtlib2():

(set-option :timeout 5)
; Entering Scope
; Entering Scope
; constraint: a > 0 and b > 0 and c > 0
; 
(set-info :status unknown)
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(assert (<= (- 2147483648) a))
(assert (<= a 2147483647))
(assert (<= (- 2147483648) b))
(assert (<= b 2147483647))
(assert (<= (- 2147483648) c))
(assert (<= c 2147483647))
(assert
 (let (($x43 (> c 0)))
 (let (($x37 (> b 0)))
 (let (($x32 (> a 0)))
 (let (($x38 (and $x32 $x37)))
 (and $x38 $x43))))))
(check-sat)

analyzer.get_smtlib2(try_to_prove):

(set-option :timeout 5)
; Entering Scope
; Entering Scope
; constraint: a > 0 and b > 0 and c > 0
; Trying to prove: (a - b) // c * c + b <= a
; 
(set-info :status unknown)
(declare-fun a () Int)
(declare-fun b () Int)
(declare-fun c () Int)
(assert (<= (- 2147483648) a))
(assert (<= a 2147483647))
(assert (<= (- 2147483648) b))
(assert (<= b 2147483647))
(assert (<= (- 2147483648) c))
(assert (<= c 2147483647))
(assert
 (let (($x43 (> c 0)))
 (let (($x37 (> b 0)))
 (let (($x32 (> a 0)))
 (let (($x38 (and $x32 $x37)))
 (and $x38 $x43))))))
(assert
 (let ((?x53 (- a b)))
 (let ((?x54 (div ?x53 c)))
 (let ((?x55 (* ?x54 c)))
 (let ((?x56 (+ ?x55 b)))
 (let (($x57 (<= ?x56 a)))
 (not $x57)))))))
(check-sat)

analyzer.get_z3_stats():

(:added-eqs                      9
 :arith-eq-adapter               3
 :arith-bound-propagations-cheap 3
 :arith-conflicts                1
 :arith-fixed-eqs                3
 :arith-lower                    8
 :arith-make-feasible            3
 :arith-max-columns              20
 :arith-max-rows                 8
 :arith-propagations             3
 :arith-upper                    10
 :conflicts                      1
 :del-clause                     15
 :max-memory                     36.29
 :memory                         19.86
 :mk-bool-var                    28
 :mk-clause                      15
 :num-allocs                     8949891
 :num-checks                     1
 :propagations                   7
 :rlimit-count                   550)

Summary by CodeRabbit

  • Dependencies

    • Added Z3 solver (z3-solver>=4.13.0) and enabled Z3 integration in build/runtime.
  • Tests

    • Added extensive arithmetic analysis test suites: proofs, SMT-based checks, int-set/region-bound, iterator/affine-map, and simplification.
    • Converted GEMM tests to parameterized variants and consolidated CUDA GEMM SP tests.
    • Removed a deprecated/buggy test case.
  • Chores

    • Updated third-party submodule reference and adjusted build/runtime configuration for Z3 library discovery.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 2, 2025

Walkthrough

Updates the TVM submodule pointer, integrates Z3 (build/runtime and Python dependency), adds TileLang arith sources to CMake, extends RPATH handling for z3, introduces many new arithmetic and parameterized GEMM tests, removes one obsolete test helper, and makes a small utility cleanup.

Changes

Cohort / File(s) Summary
Submodule
3rdparty/tvm
Updated tracked commit reference from 3a32b76... to 877f20c... (submodule pointer only).
Build & CMake
CMakeLists.txt
Added src/arith/*.cc to TileLang sources, introduced USE_Z3 = "pypi", and extended Apple/UNIX RPATH handling to include z3 library paths alongside the TVM runtime.
Python build & runtime deps
pyproject.toml, requirements.txt
Added z3-solver>=4.13.0 to runtime requirements; added z3-solver==4.13.0 to [build-system].requires; adjusted cibuildwheel repair-wheel exclusion for libz3.so.
Arithmetic tests — proofs & Z3
testing/python/arith/test_arith_hard.py
New tests exercising Analyzer proof queries, SMT-LIB2 emission, Z3 satisfiability checks, and bound-binding workflows (implies, test_hard_prove, test_smtlib2, test_bind).
Arithmetic tests — int-set analysis
testing/python/arith/test_arith_intset.py
New comprehensive int-set and region-bound tests with IntSetChecker and many scenarios covering intervals, vector/scalable vectors, arithmetic ops, region bounds, and modular behavior.
Arithmetic tests — iter/affine maps
testing/python/arith/test_arith_iter_affine_map.py
New tests for iter-map detection, fusion/splitting, affine inversion, normalization, predicates, padding, and complex nested iterator patterns (many helpers and cases).
Arithmetic tests — simplification/regressions
testing/python/arith/test_arith_simplify.py
New simplification and can_prove regression tests across int/float dtypes, symbolic comparisons, floor_mod rewrites, and recursion-regression cases.
GEMM tests (parameterized)
testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py, testing/python/tilelibrary/test_tilelang_tilelibrary_gemm_sp.py
Converted many hard-coded GEMM invocations into pytest-parameterized tests; added trans_A/trans_B parameters and forwarded them into run helpers; added CUDA/SM-specific parameterization for SP tests.
Test removal / cleanup
testing/python/transform/test_tilelang_transform_legalize_safe_memory_access.py
Removed issue_1013_buggy_kernel and disabled its wrapper test.
Minor cleanup
tilelang/utils/sparse.py
Removed an extraneous comment in an exception handler; no behavioral change.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Pay extra attention to:
    • CMake RPATH and USE_Z3 integration (platform-specific linker/runtime paths).
    • pyproject build-system ordering and cibuildwheel auditwheel exclusion for libz3.
    • New tests that invoke Z3 — check flakiness, solver invocation, and test isolation.
    • GEMM parameter forwarding to ensure transposition and CUDA-specific params are passed correctly.

Suggested reviewers

  • LeiWang1999

Poem

🐇 I hopped through CMake, wheels, and tests,

Z3 whispers proofs while I take rests.
GEMM now dances, params in a line,
Int-sets and maps all look fine.
A tidy burrow — build and tests align.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.68% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[Feat] Integrate Z3 in TVM Arith Analyzer' accurately and clearly describes the main change: integrating the Z3 SMT solver into TVM's arithmetic Analyzer. It is concise, specific, and directly reflects the primary objective of the pull request.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c831d9 and cde17e6.

📒 Files selected for processing (1)
  • pyproject.toml (3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Test for Python 3.12 with Metal (on macos-latest)
  • GitHub Check: Build wheels for Python 3.9 on ubuntu-24.04-arm with CUDA-12.8
  • GitHub Check: Build wheels for Python 3.9 on macos-latest with Metal
  • GitHub Check: Build wheels for Python 3.9 on ubuntu-latest with CUDA-12.1
  • GitHub Check: Build SDist
🔇 Additional comments (2)
pyproject.toml (2)

43-43: Verify z3-solver version compatibility strategy.

The build-system requires z3-solver==4.13.0 (exact), while runtime dependencies allow >=4.13.0. This asymmetry is intentional to work around SONAME issues (as discussed in PR comments), but could lead to ABI mismatches if a user has a newer z3-solver at runtime.

Since line 253 excludes libz3.so from wheels (relying on the runtime dependency to provide it), ensure that:

  • z3-solver 4.13.0 libz3.so is compatible with wheels built against earlier versions
  • The documentation or CI/CD clarifies the supported z3-solver versions at runtime
  • Test coverage validates the 4.13.0 build against multiple z3-solver versions if feasible

Also applies to: 54-54


252-255: Libz3.so exclusion approach looks sound.

The exclusion of libz3.so from wheel repair aligns with the strategy to rely on the z3-solver package dependency (line 43) to provide it at runtime. This avoids embedding a versioned SONAME and the ABI incompatibility issues discussed in the PR comments.

Ensure that:

  • Installation docs clarify that z3-solver is required at runtime (beyond the [project.dependencies] declaration)
  • CI/CD validates that libz3.so from z3-solver >= 4.13.0 is correctly resolved at import/runtime

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link

github-actions bot commented Dec 2, 2025

👋 Hi! Thank you for contributing to the TileLang project.

Please remember to run pre-commit run --all-files in the root directory of the project to ensure your changes are properly linted and formatted. This will help ensure your contribution passes the format check.

We appreciate you taking this step! Our team will review your contribution, and we look forward to your awesome work! 🚀

@LeiWang1999 LeiWang1999 self-requested a review December 2, 2025 15:41
@SiriusNEO SiriusNEO self-requested a review December 4, 2025 18:48
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please double-check the modification on the build system

The other modification on the build system can be found in 3rdparty/tvm/CMakeLists.txt.

Copy link
Contributor

@oraluben oraluben Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build system changes LGTM (including 3rdparty/tvm/CMakeLists.txt).

BTW now tvm add python and z3 libs as a non-optional build time dependency, is that what we want?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, Z3 is an optional dependency of TVM (but I don't test building TVM without Tilelang). And Tilelang depends on Z3 by setting set(USE_Z3 "pypi")


# Collect source files
file(GLOB TILE_LANG_SRCS
src/arith/*.cc
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be removed

Copy link
Contributor

@oraluben oraluben Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build system changes LGTM (including 3rdparty/tvm/CMakeLists.txt).

BTW now tvm add python and z3 libs as a non-optional build time dependency, is that what we want?

pyproject.toml Outdated
"torch>=2.7; platform_system == 'Darwin'",
"tqdm>=4.62.3",
"typing-extensions>=4.10.0",
"z3-solver>=4.13.0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

trivial update: add comma after each line

Suggested change
"z3-solver>=4.13.0"
"z3-solver>=4.13.0",

@tile-ai tile-ai deleted a comment from KEKE046 Dec 8, 2025
@kurisu6912 kurisu6912 marked this pull request as ready for review December 8, 2025 07:23
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
CMakeLists.txt (1)

136-136: Clarify or address the past review comment.

There's an existing comment from kurisu6912 stating "This should be removed" on this line. If the src/arith/*.cc sources are intentionally needed for Z3 integration, please resolve or dismiss that comment. If it was meant for a different change, the comment should be clarified.

🧹 Nitpick comments (8)
testing/python/transform/test_tilelang_transform_legalize_safe_memory_access.py (2)

41-69: Consider deleting or updating this code rather than commenting it out.

The comment from the previous review indicates that "After integrating Z3, this access can be proved safe." If this is the case, consider one of the following approaches:

  1. Delete the commented code entirely if the test is no longer needed
  2. Update the test to verify that Z3 can now prove the access is safe (remove the boundary check from the expected output)

Leaving commented-out code adds noise and maintenance burden.


148-152: Same concern: prefer deletion over commenting out test code.

This test invocation should either be deleted along with the helper function, or updated to test the improved Z3 behavior.

testing/python/arith/test_arith_iter_affine_map.py (2)

733-735: Remove commented-out dead code.

The commented variable z is unused and should be removed.

     x = tvm.tir.Var("x", "int32")
     y = tvm.tir.Var("y", "int32")
-    # z = tvm.tir.Var("z", "int32")

1145-1150: Confusing variable naming: a and b reuse names "x" and "y".

The variables a and b are constructed with names "x" and "y" respectively, which matches the names of the earlier x and y variables. While this may be intentional for the test case (testing overlapped iterations with same-named variables), it could cause confusion during debugging.

Consider using distinct names:

-    a = tvm.tir.Var("x", "int32")
-    b = tvm.tir.Var("y", "int32")
+    a = tvm.tir.Var("a", "int32")
+    b = tvm.tir.Var("b", "int32")
testing/python/arith/test_arith_simplify.py (2)

18-21: Missing explicit import tvm.testing.

Line 39 uses tvm.testing.parameter(...), but tvm.testing is not explicitly imported. While this may work if tilelang.tvm re-exports the testing module, it differs from test_arith_intset.py which explicitly imports import tvm.testing. For consistency and clarity, add the explicit import.

 from tilelang import tvm
 import tilelang.testing
 from tvm import tir
 import tvm.ir
+import tvm.testing

39-51: Float dtypes included in parameterized tests.

The PR description states Z3 integration targets integer expressions only. Including float dtypes (float16, float32, float64) is fine for general analyzer coverage, but these cases will not exercise the Z3 backend. Consider adding a comment clarifying this distinction, or if Z3-specific testing is intended, use a separate integer-only parameter set.

testing/python/arith/test_arith_intset.py (2)

177-179: Minor: prefer generator expression over list comprehension in all().

Using a generator expression is slightly more efficient as it short-circuits without building the full list.

     if result is None:
-        assert all([_ is None for _ in expect])
+        assert all(e is None for e in expect)
         return

372-378: Consider explicit variable assignment for clarity.

The pattern i, j = var_dom unpacks dict keys (the Var objects) relying on insertion order. While correct in Python 3.7+, explicit assignment would be clearer and less surprising to readers.

 def test_region_lower_bound_unfusable():
+    i = tvm.tir.Var("i", "int32")
+    j = tvm.tir.Var("j", "int32")
     var_dom = {
-        tvm.tir.Var("i", "int32"): tvm.ir.Range(8),
-        tvm.tir.Var("j", "int32"): tvm.ir.Range(4),
+        i: tvm.ir.Range(8),
+        j: tvm.ir.Range(4),
     }
-    i, j = var_dom
     check_region_bound({(i + j) // 2: (0, 6)}, var_dom, mode="lowerbound")
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d933d65 and d2cdeee.

📒 Files selected for processing (11)
  • 3rdparty/tvm (1 hunks)
  • CMakeLists.txt (3 hunks)
  • pyproject.toml (2 hunks)
  • testing/python/arith/test_arith_hard.py (1 hunks)
  • testing/python/arith/test_arith_intset.py (1 hunks)
  • testing/python/arith/test_arith_iter_affine_map.py (1 hunks)
  • testing/python/arith/test_arith_simplify.py (1 hunks)
  • testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py (4 hunks)
  • testing/python/tilelibrary/test_tilelang_tilelibrary_gemm_sp.py (5 hunks)
  • testing/python/transform/test_tilelang_transform_legalize_safe_memory_access.py (2 hunks)
  • tilelang/utils/sparse.py (0 hunks)
💤 Files with no reviewable changes (1)
  • tilelang/utils/sparse.py
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-14T07:56:11.098Z
Learnt from: lucifer1004
Repo: tile-ai/tilelang PR: 1256
File: testing/python/jit/test_tilelang_jit_gemm_nvrtc.py:55-115
Timestamp: 2025-11-14T07:56:11.098Z
Learning: In `testing/python/jit/test_tilelang_jit_gemm_nvrtc.py`, the global function `tilelang_callback_cuda_postproc` registered via `tvm.register_global_func(..., override=True)` is intentionally not restored after the test completes, as the persistent behavior is expected.

Applied to files:

  • testing/python/transform/test_tilelang_transform_legalize_safe_memory_access.py
  • testing/python/tilelibrary/test_tilelang_tilelibrary_gemm_sp.py
🧬 Code graph analysis (4)
testing/python/arith/test_arith_hard.py (1)
tilelang/tools/Analyzer.py (1)
  • Analyzer (33-218)
testing/python/arith/test_arith_simplify.py (2)
tilelang/tools/Analyzer.py (1)
  • Analyzer (33-218)
tilelang/language/ast/ir.py (1)
  • Range (1716-1728)
testing/python/tilelibrary/test_tilelang_tilelibrary_gemm_sp.py (3)
tilelang/testing/__init__.py (3)
  • requires_cuda_compute_version (38-102)
  • requires_cuda_compute_version_ge (105-106)
  • requires_cuda_compute_version_le (121-122)
tilelang/tileop/gemm/__init__.py (2)
  • trans_A (103-104)
  • trans_B (107-108)
tilelang/tileop/gemm_sp/gemm_sp_base.py (2)
  • trans_A (45-46)
  • trans_B (49-50)
testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py (2)
maint/gemm_v2/correctness_evaluation.py (3)
  • run_gemm_rs (181-213)
  • run_gemm_sr (267-300)
  • run_gemm_rr (357-390)
testing/python/amd/test_tilelang_test_amd.py (1)
  • run_gemm_rs (179-223)
🪛 Ruff (0.14.7)
testing/python/arith/test_arith_hard.py

23-23: Avoid specifying long messages outside the exception class

(TRY003)


95-95: Use raise without specifying exception name

Remove exception name

(TRY201)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: Quick Lint
  • GitHub Check: Build SDist
  • GitHub Check: Build wheels for Python 3.9 on ubuntu-24.04-arm with CUDA-12.8
  • GitHub Check: Build wheels for Python 3.9 on macos-latest with Metal
  • GitHub Check: Build wheels for Python 3.9 on ubuntu-latest with CUDA-12.1
🔇 Additional comments (30)
testing/python/tilelibrary/test_tilelang_tilelibrary_gemm_sp.py (3)

1-1: LGTM!

The pytest import is correctly added to support the parameterized test decorators.


235-294: Excellent parameterization for SM90 tests.

The test cases comprehensively cover multiple data types (float16, float8_e4m3, int8), block configurations, staging options, and transposition combinations. The trans_A and trans_B parameters are correctly integrated into both the kernel construction and execution.


297-299: Manual verification needed for decorator combination behavior.

The combination of requires_cuda_compute_version_ge(8, 0) and requires_cuda_compute_version_le(8, 9) is intended to create a version range [8.0, 8.9] for SM80 tests. However, the implementation of these decorators in the tilelang.testing module could not be inspected to confirm that pytest combines multiple decorators using AND logic (test runs only if both conditions are true) rather than OR logic. This pattern should be verified manually by reviewing the decorator source code in tilelang.testing and confirming how pytest chains them together.

testing/python/tilelibrary/test_tilelang_tilelibrary_gemm.py (4)

110-159: Well-structured parameterization for skipped SS tests.

The test is properly parameterized and will be easy to re-enable once the GEMM SS issues mentioned in the skip reason are resolved. The parameter coverage includes multiple data types and all transposition combinations.


270-319: Well-structured parameterization for skipped RS tests.

Similar to test_gemm_ss, this test is properly parameterized and documented with a skip marker. The test will be straightforward to re-enable once GEMM RS issues are resolved.


430-479: Active SR tests with documented coverage gap.

The parameterization is correct, and the TODO comment at line 443 appropriately documents the known float32 coverage issue. This test is active (unlike SS and RS), which indicates SR functionality is working.


594-644: Comprehensive parameterization for RR tests.

This test has the most extensive coverage, including bfloat16 in addition to the other data types. The 16 test cases systematically cover various configurations, block sizes, and transposition combinations. The active status (no skip marker) indicates this functionality is stable.

3rdparty/tvm (1)

1-1: Verify the submodule commit reference and z3 branch merge completion.

The commit 68f5e91e2c46223ea8b1270711a143fa6799cbc5 should be verified to confirm:

  1. It exists in the TVM repository and is reachable from tilelang_main
  2. It represents the successful completion of the z3 branch merge
  3. No breaking API changes affect TileLang consumers

Regarding the z3-solver>=4.13.0 dependency in pyproject.toml: no widely documented TVM-specific incompatibilities exist with recent z3-solver versions, though general installation and platform-specific issues can occur. Verify this specific version pairing has been tested in your build environment.

Please confirm the status of outstanding work items before merging:

  • Vectorization bug fix for the AtomicAdd op (referenced as #1366)
  • Full verification that build configuration changes in CMakeLists.txt and pyproject.toml are complete and compatible
CMakeLists.txt (2)

225-226: LGTM: Z3 integration enabled via PyPI.

Setting USE_Z3 to "pypi" aligns with the z3-solver dependency added to pyproject.toml and enables the TVM Z3 integration for arithmetic proving.


291-299: LGTM: RPATH updated for Z3 library discovery.

The RPATH additions for both Apple (@loader_path/../../z3/lib) and UNIX ($ORIGIN/../../z3/lib) platforms ensure the z3 shared libraries can be found at runtime alongside the existing tvm_ffi paths.

pyproject.toml (2)

54-54: LGTM: z3-solver build-time dependency added.

Adding z3-solver>=4.13.0 to build requirements ensures Z3 is available during the build process for TVM's Z3 integration.


43-43: LGTM: z3-solver runtime dependency added.

The z3-solver>=4.13.0 dependency enables the new Z3-based arithmetic proving capabilities at runtime. The version constraint is appropriate, allowing flexibility to use versions up to the latest (4.15.4.0).

testing/python/arith/test_arith_hard.py (4)

1-5: LGTM: Imports are appropriate for Z3 arithmetic testing.

The imports from tvm.arith, tvm.ir.expr, and tvm.tir.expr are correct for testing the new Z3-based arithmetic analyzer.


8-9: LGTM: Logical implication helper.

The implies(x, y) helper correctly implements logical implication as ¬x ∨ y.


12-54: LGTM: Comprehensive arithmetic proof tests.

The test_hard_prove function tests complex arithmetic implications including:

  • Integer division/modulo properties
  • Comparison transitivity (with caveats for d)
  • Bit manipulation patterns

The check_expr helper provides useful debugging output via SMT-LIB2 on failure.


78-95: LGTM: Range binding test.

The test_bind function correctly tests the analyzer's ability to prove expressions with bound variables. The exception handling provides useful SMT-LIB2 debugging output.

testing/python/arith/test_arith_iter_affine_map.py (4)

1-20: LGTM: License header and imports.

The Apache 2.0 license header is appropriate for TVM-derived test code, and the imports correctly reference the tilelang and TVM modules needed for iter-map testing.


23-48: LGTM: Well-documented helper functions.

The utility functions ifuse, isplit, var_dom, and convert_iter_expr are clearly documented and provide a clean API for constructing test cases.


51-117: LGTM: Comprehensive assertion helpers.

The assert_iter_sum_pattern, assert_iter_map_simplify, and assert_iter_sum_failure functions provide thorough validation of iter-map detection results with support for various check levels and options.


120-1422: LGTM: Comprehensive iter-map test coverage.

The test suite provides thorough coverage of TVM's arithmetic iter-map analysis including:

  • Trivial cases, fusion, and splitting
  • Compound patterns and predicates
  • Subspace division
  • Normalization and inverse affine mappings
  • Padding scenarios
  • Symbolic cases and edge conditions

This is valuable test coverage for the TVM arithmetic integration.

testing/python/arith/test_arith_simplify.py (4)

86-94: LGTM - regression test pattern is appropriate.

The test intentionally has no assertion since it verifies that rewrite_simplify completes without infinite recursion. The test passes by not hanging, which is the correct approach for this type of regression test.


121-122: Inconsistent test runner with sibling test file.

This file uses tilelang.testing.main() while test_arith_intset.py uses tvm.testing.main(). For consistency across test files in the same directory, consider aligning the test runner usage.


24-36: LGTM - well-structured index simplification test.

The test correctly verifies that the analyzer simplifies a flattened index expression back to its original form, validating the reshape pattern simplification logic.


68-83: LGTM - comprehensive symbolic bound proof tests.

Good coverage of symbolic comparison proofs with ProofStrength.SYMBOLIC_BOUND, testing various inequality forms and boundary conditions.

testing/python/arith/test_arith_intset.py (6)

17-21: LGTM - imports are well-organized.

Imports are complete and consistent. The explicit import tvm.testing aligns with the tvm.testing.main() usage at the end of the file.


24-36: LGTM - clean helper class design.

The IntSetChecker class provides a reusable pattern for int set verification with informative error messages for debugging test failures.


58-63: LGTM - appropriate vscale handling test.

This test validates that scalable vectors with vscale() correctly produce pos_inf() for the max value, which is the expected behavior since vscale is runtime-determined. This aligns with the PR noting that vscales are not supported in Z3 integration.


92-122: LGTM - thorough modulo operation testing.

Good coverage of both truncmod and floormod operations with various interval ranges. The use of separate IntSetChecker instances (ck vs ck1) correctly isolates different binding contexts.


381-392: LGTM - good edge case coverage for union bounds.

The test correctly validates union behavior with infinite bounds, including the edge case where an empty interval (pos_inf to neg_inf) is included in the union.


205-240: LGTM - comprehensive dependent region bound tests.

Good coverage of scenarios where region bounds cannot be computed (dependent indices) for lowerbound mode, with corresponding upperbound fallbacks.

Comment on lines +73 to +75
solver = z3.Solver()
solver.from_string(smtlib2)
assert solver.check()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Potential issue: solver.check() returns CheckSatResult, not a boolean.

In Z3, solver.check() returns z3.sat, z3.unsat, or z3.unknown, not a boolean. While z3.sat is truthy, z3.unknown is also truthy and would pass this assertion unexpectedly.

Consider being explicit about the expected result:

-    assert solver.check()
+    assert solver.check() == z3.sat, f"Expected sat, got {solver.check()}"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
solver = z3.Solver()
solver.from_string(smtlib2)
assert solver.check()
solver = z3.Solver()
solver.from_string(smtlib2)
assert solver.check() == z3.sat, f"Expected sat, got {solver.check()}"
🤖 Prompt for AI Agents
In testing/python/arith/test_arith_hard.py around lines 73 to 75, the code
asserts solver.check() directly but Z3 returns a CheckSatResult (z3.sat /
z3.unsat / z3.unknown), so unknown would incorrectly pass; change the assertion
to explicitly compare the result to z3.sat (e.g. result = solver.check(); assert
result == z3.sat) and only call solver.model() or use the model when result is
z3.sat.

@kurisu6912
Copy link
Collaborator Author

Sad, Z3 has a hard-encoded SONAME libz3.so.x.xx. The linker will make TVM dependent on only 1 version of Z3. We have to choose:

  1. Link Z3 statically: causing binary size 10~20% larger
  2. Force only 1 version of Z3: may cause conflict with other libraries using Z3
  3. Manually hack Z3 to make it portable: large engineering effort

I think the best choice may be 1, @LeiWang1999

@kurisu6912 kurisu6912 marked this pull request as draft December 9, 2025 05:08
@oraluben
Copy link
Contributor

oraluben commented Dec 9, 2025

Sad, Z3 has a hard-encoded SONAME libz3.so.x.xx. The linker will make TVM dependent on only 1 version of Z3. We have to choose:

libz3.so in z3-solver==4.13.0 has a SONAME "libz3.so", 4.14 and 4.15 have version number in their SONAMEs. We could build tvm with the specific version and then use a looser z3 in runtime.

Also we could use patchelf --replace-needed to modify the DL_NEEDED part of libtvm (libz3.so.x.xx -> libz3.so). This is rather common in python packaging. I could help if needed.

@kurisu6912
Copy link
Collaborator Author

Sad, Z3 has a hard-encoded SONAME libz3.so.x.xx. The linker will make TVM dependent on only 1 version of Z3. We have to choose:

libz3.so in z3-solver==4.13.0 has a SONAME "libz3.so", 4.14 and 4.15 have version number in their SONAMEs. We could build tvm with the specific version and then use a looser z3 in runtime.

Also we could use patchelf --replace-needed to modify the DL_NEEDED part of libtvm (libz3.so.x.xx -> libz3.so). This is rather common in python packaging. I could help if needed.

Oh, that's soo cool!

I will check z3-solver==4.13.0 in the build environment, and call you if needed!

Thanks very much!

@kurisu6912 kurisu6912 marked this pull request as ready for review December 10, 2025 09:52
@oraluben
Copy link
Contributor

Also we could use patchelf --replace-needed to modify the DL_NEEDED part of libtvm (libz3.so.x.xx -> libz3.so). This is rather common in python packaging. I could help if needed.

Actually this looks more robust. Building against specific version of library does not make much sense, especially when you look at the arm & mac failure:

The z3-solver==4.13.0 on arm claims to be manylinux2014, but the libz3.so rely on glibc 2.29, causing the failure.
I didn't dig into the mac failure but it sounds like a similar issue.

For linux arm issue, we may have to embed libz3.so into the wheel if its future version stay buggy.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants