Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Canonicalize trunc of symbolic integer division by one#186194

Draft
jansel wants to merge 1 commit into
gh/jansel/1328/basefrom
gh/jansel/1328/head
Draft

Canonicalize trunc of symbolic integer division by one#186194
jansel wants to merge 1 commit into
gh/jansel/1328/basefrom
gh/jansel/1328/head

Conversation

@jansel
Copy link
Copy Markdown
Contributor

@jansel jansel commented Jun 4, 2026

Stack from ghstack (oldest at bottom):

Issue #138926 reported a torch.cond metadata mismatch where one branch
returned a tensor sized with TruncToInt(IntTrueDiv(s, 1)) while the other
returned the same tensor sized with s. The branches were semantically
compatible, but the symbolic expressions were not canonicalized before the
metadata check.

The root cause is that math.trunc(SymInt / 1) lowered to TruncToInt over an
IntTrueDiv expression instead of simplifying back to the original symbolic
integer. Canonicalize integer-valued TruncToInt inputs and the IntTrueDiv by
+/-1 cases in the SymPy helper layer so all downstream users see the same
shape expression. This fixes the cond branch metadata check without adding a
cond-specific workaround.

Fixes #138926
Generated by my agent

Test Plan:

  • python test/test_dynamic_shapes.py TestPySymInt.test_sym_trunc
  • python test/export/test_export.py TestExport.test_cond_dynamic_shape_trunc_div_one_output_metadata
  • original CUDA repro with torch._inductor.aot_compile
  • lintrunner -a

cc @jgong5 @mingfeima @XiaobingSuper @sanchitintel @ashokei @jingxu10 @aditew01

[ghstack-poisoned]
@pytorch-bot
Copy link
Copy Markdown

pytorch-bot Bot commented Jun 4, 2026

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/186194

Note: Links to docs will display an error until the docs builds have been completed.

✅ No Failures

As of commit e2a7273 with merge base 16de8e3 (image):
💚 Looks good so far! There are no failures yet. 💚

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@pytorch-bot pytorch-bot Bot added the module: cpu CPU specific problem (e.g., perf, algorithm) label Jun 4, 2026
@pytorch-bot
Copy link
Copy Markdown

pytorch-bot Bot commented Jun 4, 2026

This PR needs a release notes: label

If your changes are user facing and intended to be a part of release notes, please use a label starting with release notes:.

If not, please add the topic: not user facing label.

To add a label, you can comment to pytorchbot, for example
@pytorchbot label "topic: not user facing"

For more information, see
https://github.com/pytorch/pytorch/wiki/PyTorch-AutoLabel-Bot#why-categorize-for-release-notes-and-how-does-it-work.

@jansel
Copy link
Copy Markdown
Contributor Author

jansel commented Jun 4, 2026

@claude review these changes

@claude
Copy link
Copy Markdown

claude Bot commented Jun 4, 2026

Claude finished @jansel's task in 1m 32s —— View job


Review of PR #186194: Canonicalize trunc of symbolic integer division by one

  • Read the diff and changed files
  • Review torch/utils/_sympy/functions.py changes
  • Review test/test_dynamic_shapes.py changes
  • Review test/export/test_export.py changes
  • Post review feedback

Overall: This looks good. The fix is well-scoped and placed at the right layer.

torch/utils/_sympy/functions.py (lines 1268–1275)

The two simplification rules are correct:

  1. number.is_integer is True → number — Truncating an integer is a no-op. Using is True correctly excludes the None (unknown) case from SymPy's three-valued logic.

  2. IntTrueDiv(base, ±1) pattern match — Since IntTrueDiv has is_real = True (not is_integer), SymPy won't infer that IntTrueDiv(s, 1) is integer-valued, so this explicit pattern match is necessary and won't be subsumed by the is_integer check above it.

The placement is correct: handling this in TruncToInt rather than in IntTrueDiv.eval preserves the type semantics — IntTrueDiv models float-returning division, while TruncToInt is the float→int conversion boundary where the composition TruncToInt(IntTrueDiv(s, 1)) can safely collapse to s.

Minor observation (not blocking)

CeilToInt and FloorToInt lack the number.is_integer is True early-return that TruncToInt now has (and that FloorToInt partially covers with isinstance(number, sympy.Integer)). If similar ceil(x/1) or floor(x/1) patterns ever arise, they'd hit the same issue. But that's a separate concern — this PR correctly fixes the reported problem without scope creep.

Tests

Both tests are well-structured:

No issues found. LGTM.

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

Labels

module: cpu CPU specific problem (e.g., perf, algorithm)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant