Skip to content

[Arith] Restrict floormod coefficient reduction to keep DetectIterMapstable#19832

Merged
tlopex merged 2 commits into
apache:mainfrom
tlopex:fix-arith-floormod-itermap-19825
Jun 18, 2026
Merged

[Arith] Restrict floormod coefficient reduction to keep DetectIterMapstable#19832
tlopex merged 2 commits into
apache:mainfrom
tlopex:fix-arith-floormod-itermap-19825

Conversation

@tlopex

@tlopex tlopex commented Jun 18, 2026

Copy link
Copy Markdown
Member

This PR fixes #19825, which restricts the rewrites

floormod(x * c1 + y, c2) -> floormod(x * floormod(c1, c2) + y, c2)

and

floormod(x + y * c1, c2) -> floormod(x + y * floormod(c1, c2), c2).

While algebraically valid in isolation, these transformations rewrite only the floormod side of a matching floordiv/floormod pair. As a result, the two expressions no longer share a visible fused index expression, causing DetectIterMap to reject otherwise bijective splits such as:

lane = flat % 128
reg  = flat // 128

where both expressions originate from the same fused index.

Context

Per the suggestion in #19825, the two rewrites are guarded with c1 % c2 == 0 rather than dropped outright. The multiplied term is still eliminated when it is a multiple of the divisor (e.g. (x*10 + y) % 2 -> y % 2), which is safe for DetectIterMap; only the coefficient-shrinking case (c1 not a multiple of c2) is disabled. Both operand orderings are covered, and the PR adds a rewrite-simplify regression plus an end-to-end DetectIterMap regression test.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request restricts certain floormod rewrite rules in RewriteSimplifier to only apply when c1 % c2 == 0, and updates the corresponding tests. The reviewer suggests further simplifying the target expressions in both modified rules directly to floormod(y, c2) and floormod(x, c2) respectively, as floormod(c1, c2) always evaluates to 0 under the new conditions, which avoids unnecessary recursive simplification overhead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 1251 to +1252
TVM_TRY_REWRITE_IF(floormod(x * c1 + y, c2), floormod(x * floormod(c1, c2) + y, c2),
c2.Eval()->value > 0);
c2.Eval()->value > 0 && c1.Eval()->value % c2.Eval()->value == 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Since the rewrite is now restricted to cases where c1 % c2 == 0, floormod(c1, c2) will always evaluate to 0. Therefore, floormod(x * floormod(c1, c2) + y, c2) simplifies directly to floormod(y, c2). We can simplify the target expression directly to floormod(y, c2) to avoid unnecessary recursive simplification steps (such as multiplying by zero and adding zero).

    TVM_TRY_REWRITE_IF(floormod(x * c1 + y, c2), floormod(y, c2),
                       c2.Eval()->value > 0 && c1.Eval()->value % c2.Eval()->value == 0);

Comment on lines 1259 to +1260
TVM_TRY_REWRITE_IF(floormod(x + y * c1, c2), floormod(x + y * floormod(c1, c2), c2),
c2.Eval()->value > 0);
c2.Eval()->value > 0 && c1.Eval()->value % c2.Eval()->value == 0);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

Similarly, since c1 % c2 == 0 implies floormod(c1, c2) == 0, the expression floormod(x + y * floormod(c1, c2), c2) simplifies directly to floormod(x, c2). Rewriting directly to floormod(x, c2) avoids intermediate simplification overhead.

    TVM_TRY_REWRITE_IF(floormod(x + y * c1, c2), floormod(x, c2),
                       c2.Eval()->value > 0 && c1.Eval()->value % c2.Eval()->value == 0);

@tlopex

tlopex commented Jun 18, 2026

Copy link
Copy Markdown
Member Author

cc @LeiWang1999

@tqchen

tqchen commented Jun 18, 2026

Copy link
Copy Markdown
Member

would be good to add short comment about context

@tlopex tlopex force-pushed the fix-arith-floormod-itermap-19825 branch from 6e19711 to c926502 Compare June 18, 2026 19:47
tlopex added 2 commits June 18, 2026 15:52
… stable

The rewrites floormod(x * c1 + y, c2) -> floormod(x * floormod(c1, c2) + y, c2)
and its mirror floormod(x + y * c1, c2) reduce the multiplier modulo the
divisor. This is algebraically valid in isolation, but when the modulo is
paired with the matching floordiv of the same fused index it rewrites only the
modulo's source, so the two halves no longer share a visible fused expression
and DetectIterMap rejects an otherwise bijective split (e.g. a layout that
splits a flat index into lane = flat % 128 and reg = flat // 128).

Guard both rewrites with c1 % c2 == 0 so the multiplied term is only dropped
when it is a multiple of the divisor, which is iter-map-safe, as suggested in
issue apache#19825. Add a rewrite-simplify regression for both operand orderings and
an end-to-end DetectIterMap regression.
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@tlopex tlopex force-pushed the fix-arith-floormod-itermap-19825 branch from c926502 to b14a680 Compare June 18, 2026 19:52
@tlopex tlopex merged commit 7bd73e5 into apache:main Jun 18, 2026
9 checks passed
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.

[Arith] floormod(x * c1 + y, c2) rewrite breaks DetectIterMap on fused div/mod maps

2 participants