Dataflow Region Pitfalls¶
Pitfalls met when building @df.region() designs on the fork, with the
dated corrections they received. Originally titled “Pitfalls: @df.region()
with Multi-Kernel Arg Mapping”.
Bug: top-func arg order reordered when scalar n appears before array in kernel args¶
Root cause: _build_top in allo/dataflow.py populated input_types in
kernel-appearance order (first kernel’s args first). If a scalar int32[1] arg
appeared in an earlier kernel’s args=[arr_in, n] list than a large array that
only appeared in a later kernel (args=[arr_out]), the top-level MLIR function
ended up with (arr_in, n, arr_out) instead of the declared (arr_in, arr_out, n).
Python callers invoking mod(inp, out, n) would silently corrupt args.
Fix: _build_top now pre-seeds used_args and input_types from
s.func_args[s.top_func_name] (the region’s canonical declaration order) before
iterating kernels. Kernel args resolve to canonical positions via dtensor.top_name
(set by allo/ir/infer.py from args=[...] annotation).
File changed: allo/dataflow.py — _build_top() function, argument mapping
section (~line 481).
Scalar region args: bare int32 is rejected; use int32[1] → m_axi¶
Corrected 2026-09-17. An earlier version of this section claimed that a bare
int32 (no brackets) @df.region() argument yields a true AXI-Lite scalar port
(s_axilite). That held only on the short-lived
feature/region-bare-scalar-axilite branch, which was reverted (a7ae144f,
reverting dbc60b43) after upstream PR #577 settled on rejecting scalars in
args=[...].
On main today:
args=[...]takes array types only.int32[N]for any N (including N=1) maps to an AXI-MM pointer (m_axi); there is no scalar port path.s_axiliteappears nowhere inallo/backend/vitis.py(only inallo/backend/pynq.py), andtests/dataflow/test_df_unit.py::test_region_bare_scalar_argno longer exists.The auto-capture →
s_axiliteredesign is still open. It is item 4 of the hierarchical-region design record (dev/records/hierarchical_regions.rst) and is tracked in fork issue #7.
Observation: OMP segfault at Python GC exit¶
When running simulator with OMP threads and the module is not freed before
interpreter exit, Python GC (dict_traverse / func_traverse) can segfault due to
OMP thread-local storage teardown racing with the GC. Workaround: set
OMP_NUM_THREADS=N explicitly and run each region in its own process. This
is a Python/OpenMP interaction issue, not an Allo bug.
Observation: LLVM_BUILD_DIR must be set BY YOU – corrected 2026-09-18¶
This section used to say the conda allo env “already sets LLVM_BUILD_DIR” to
/work/shared/common/llvm-project-main/build-rhel8 and must not be overridden.
That is false on this host and contradicted CLAUDE.md, which is right
(its environment notes now live in dev/toolchains.rst).
Checked directly:
$ conda activate allo && echo "${LLVM_BUILD_DIR:-<unset>}"
<unset>
Neither conda activate allo nor conda run sets it, and the simulator asserts
LLVM_BUILD_DIR is not set without it. Export it yourself:
export LLVM_BUILD_DIR=/home/sk3463/llvm-allo-6b09f739/build
What survives of the original warning is the reason it was written: which build you point at matters. A build made against a newer glibc than the host’s fails at simulator init with a GLIBC_2.33 error, which is why an RHEL8-compatible build was named here in the first place. The path above is the build every result in this repo was produced with.
Inspecting MLIR: one process per dump¶
(Extracted from the retired ALLO_LESSONS.md on 2026-09-17; still true. That
file was deleted 2026-09-18 once this was the only part of it left standing –
git show f1c3aad1^:notes/ALLO_LESSONS.md.)
The MLIR context cannot be re-initialized in the same Python process — a second
customize() in one interpreter aborts with
LLVM ERROR: Option 'fast' already exists!. Use one process per module dump:
conda run -n allo python -c "...customize and print str(s.module)..."
and pipe through head / sed -n for line ranges; generated MLIR carries no
source attribution, so match by function name (func.func @decoder_0), never by
line number.
These errors are library bugs, not user-code bugs — the right move is a minimal reproducer and a compiler fix, not a rewrite of the kernel to dodge them:
cannot be converted to LLVM IR: missing LLVMTranslationDialectInterfaceAssertion 'value' failedFailure while creating the ExecutionEngineAttributeError: 'ASTContext' object has no attribute 'global_op_cache'LLVM ERROR: Option 'fast' already exists!