Skip to content

compiler: Preserve compilation invariants under symbol renaming - #3084

Open
FabioLuporini wants to merge 19 commits into
mainfrom
kernel-local-names
Open

FabioLuporini wants to merge 19 commits into
mainfrom
kernel-local-names

Conversation

@FabioLuporini

Copy link
Copy Markdown
Contributor

Generated temporary names can affect CSE scheduling, while symbolic substitutions can reorder lowered arithmetic or leave stale references in auxiliary metadata. Application identifiers such as r0 can also collide with compiler-generated temporaries.

This PR addresses these issues and provides a final IET customization point for backend naming passes:

  • Schedule ready CSE temporaries in expression order, independently of their names.
  • Preserve lowered Add/Mul operand order and grouping during substitution, retaining numeric folding and handling nested negations correctly.
  • Substitute dereference offsets and flattened-array stride metadata while preserving scoped C member names.
  • Distinguish flattened-array macros by their stride bindings.
  • Reserve application and generated identifiers through SymbolRegistry.reserve.
  • Abstract equal symbol instances once, preserving equivalent helper reuse.
  • Add _finalize_iet after dtype lowering and symbol minimization, before macro extraction and signature finalization.

@codecov

codecov Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.56140% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 84.46%. Comparing base (6d2ad82) to head (89a123f).
⚠️ Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
devito/operator/operator.py 75.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3084      +/-   ##
==========================================
+ Coverage   84.28%   84.46%   +0.17%     
==========================================
  Files         258      260       +2     
  Lines       57469    58349     +880     
  Branches     4914     4956      +42     
==========================================
+ Hits        48439    49282     +843     
- Misses       8206     8245      +39     
+ Partials      824      822       -2     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX 68.47% <74.39%> (-0.03%) ⬇️
pytest-gpu-gcc- 79.17% <99.56%> (+0.24%) ⬆️
pytest-gpu-icx- 79.12% <99.56%> (+0.27%) ⬆️
pytest-gpu-nvc-nvidiaX 69.17% <74.39%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mloubout mloubout 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.

Looks sane

@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

Comment thread devito/ir/support/symregistry.py Outdated
self.reserved.update(i.name for e in exprs for i in e.free_symbols)

# Before indexification, a Function's free symbols omit its own name
self.reserved.update(i.name for i in retrieve_functions(exprs))

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.

mode='unique'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

OK

Comment thread devito/passes/clusters/cse.py
Comment thread devito/symbolics/manipulation.py Outdated
Comment thread tests/test_operator.py Outdated
Retrieve Functions uniquely when reserving names, share the default
uxreplace traversal through an explicit helper, and remove the unneeded
Operator name from the input-name collision test.

Keep the CSE position map to avoid repeated linear scans of exprs. In a
comparison of the actual topological sort with 128 independent CTemps,
including map construction, cached lookup took 39 ms versus 1255 ms for
list.index. Add a comment explaining the cached lookup.

Validation: focused C/OpenMP regressions (64 passed, 1 xfailed) and
C++/OpenMP regressions (62 passed, 1 xfailed). The full CPU audit found
separate numerical failures already present before the rebase.
Comment thread devito/ir/cgen/printer.py Outdated

def __init__(self, settings=None):
super().__init__(settings)
self._order = self.order

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.

?

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.

Seconded

Stably place numeric offsets last in commutative integer sums. This emits
bx_size - 1 without sorting symbolic operands by name or changing
floating-point summation order. Preserve opaque noncommutative expressions.

Cover positive and negative offsets with 32- and 64-bit integers and mixed
floating-point addends. Refresh two stale floating-point code-display lines
in the MPI overview, keeping notebook source and comparison rules unchanged.

Validation: both MPI notebooks pass all 35 cell checks on a private four-rank
cluster; affected C/OpenMP compiler tests pass 554 cases, and C++/OpenMP
symbolic/IET tests pass 192 cases.
Comment thread devito/ir/cgen/printer.py Outdated

def __init__(self, settings=None):
super().__init__(settings)
self._order = self.order

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.

Seconded



@_uxreplace_dispatch.register(dict)
@_uxreplace_dispatch.register(frozendict)

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.

This dispatcher currently turns a frozendict into a dict. You need to add a cast at the end to make sure it's the correct type.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

fixing

Comment on lines +220 to +221
@_uxreplace_handle.register(UnevalAdd)
@_uxreplace_handle.register(UnevalMul)

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.

Why not register UnevalMixin instead of having multiple registrations here?

Choose emitted Add/Mul order at the existing freezing boundary, using
capture-avoiding definition-order comparison symbols for local Temps.
Preserve original operands and groups through replacement, serialization
and printing. Remove the per-node printer setting mutation and integer
result-type formatting workaround.

Keep frozen sums grouped and preserve factor order during negative
coefficient extraction. Retain ordinary symbolic display, refresh generated
notebook output, and avoid fixed operand positions in the visitor regression.

Preserve immutable mapping types during symbolic reconstruction, and explain
why the concrete frozen Add/Mul dispatch registrations are required by MRO.
Restore recursive unevaluation without comparison symbols or operand sorting.
Keep ordinary Add/Mul printing and avoid new parentheses around nested sums.
Preserve the earlier scoped substitution and reconstruction fixes.

Extract numeric factor signs locally in the Devito printer, including signs
outside the leading factor and products containing only minus-one factors.
Cover pure freezing, equal operand instances and canonical emitted code; bring
tutorial snapshots back to ordinary printing.

Validate CPU/C++ symbolic and numerical cases, 91 strict notebook checks,
CUDA naming/pickling and the reported CUDA/OpenACC compilation failures.
The existing min-storage and bitcomp precision failures remain unchanged in
scope; no numerical tolerances are relaxed.
Document that SymPy calls the standalone _keep_coeff helper, so UnevalMul
cannot override its reconstruction. Explain why Devito extracts signs before
delegating instead of patching SymPy or copying its multiplication printer.

Comment only; Python syntax trees are identical. Ruff and diff checks pass.

This branch has not been deployed

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants