Skip to content
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
[Refactor] Report an out-of-range fill region as a validation error
The three checks in this block validate a region that comes from the TileLang
program under compilation, so a region that does not fit is a frontend
validation failure rather than an internal invariant. `support/check.h` is
already included and `src/op/reduce.cc` uses `CHECK(..., ValueError)` for the
same kind of condition.

A slice that runs past the end of its buffer now fails as

    ValueError: Check failed: (min_imm->value + extent_imm->value <= ...

instead of an InternalError, which is what the style guide asks for:

    Use user-facing validation errors where the problem can be caused by a
    TileLang program rather than an internal invariant.
  • Loading branch information
173787247 committed Sep 30, 2026
commit e046a5ca5ccc4426d34ec828ca10c564ba5be403
11 changes: 7 additions & 4 deletions src/op/fill.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,25 +109,28 @@ Fill::Fill(Array<PrimExpr> args, Map<String, ObjectRef> annotations) {
<< "region size = " << node->region.size()
<< " != " << node->dst->shape.size();
for (int i = 0; i < node->region.size(); i++) {
// bound check if region is static
// bound check if region is static. The region comes from the TileLang
// program under compilation, so a region that does not fit is a frontend
// validation failure rather than an internal invariant.
if (const auto *min_imm = node->region[i]->min.as<IntImmNode>()) {
int64_t min = min_imm->value;
ICHECK_GE(min, 0) << "region[" << i << "] = " << min << " < 0";
CHECK(min >= 0, ValueError) << "region[" << i << "] = " << min << " < 0";
}
if (const auto *extent_imm = node->region[i]->extent.as<IntImmNode>()) {
// Only perform the upper-bound check when the destination shape
// extent is also statically known. If the shape is symbolic (e.g., Var),
// skip this static check to avoid invalid downcasts.
if (const auto *shape_imm = node->dst->shape[i].as<IntImmNode>()) {
ICHECK_LE(extent_imm->value, shape_imm->value)
CHECK(extent_imm->value <= shape_imm->value, ValueError)
<< "region[" << i << "] = " << extent_imm->value << " > "
<< node->dst->shape[i];
// `extent <= shape` only bounds a region anchored at the start of the
// buffer. A sliced region may start further in, so its end is what has
// to fit: `As[6:12]` into a shape-8 buffer has a legal extent and still
// writes four elements past the end.
if (const auto *min_imm = node->region[i]->min.as<IntImmNode>()) {
ICHECK_LE(min_imm->value + extent_imm->value, shape_imm->value)
CHECK(min_imm->value + extent_imm->value <= shape_imm->value,
ValueError)
<< "region[" << i << "] = [" << min_imm->value << ", "
<< min_imm->value + extent_imm->value << ") exceeds "
<< node->dst->shape[i];
Expand Down