[Relax] Fix FuseOpsByPattern dropping bound constants on duplicate-structure functions#19801
Conversation
…ructure functions BlockBuilder::AddFunction deduplicates context functions through a map whose hash (StructuralHashIgnoreNDarray) intentionally ignores tensor content for speed. Its equality, however, was the default ffi::StructuralEqual, whose operator() also skips tensor content. As a result two grouped functions that differ only in their bound constants -- e.g. two conv layers with different weights produced by FuseOpsByPattern(bind_constants=True) -- compared equal and were merged, silently dropping all but the first constant and miscompiling the result. A hash may be approximate, but the dedup equality must be exact. Add a value-aware equality functor (skip_tensor_content=false) and use it as the map's KeyEqual, keeping the fast content-ignoring hash. Functions with identical constants still dedup; functions with differing constants no longer do. This affects any BYOC backend relying on bind_constants=True (TensorRT, CUTLASS, cuDNN, ...).
There was a problem hiding this comment.
Code Review
This pull request introduces StructuralEqualConsiderNDarray, a custom structural equality comparator that compares tensor (constant) data content. It updates ctx_func_dedup_map_ to use this new comparator instead of ffi::StructuralEqual. This ensures that functions differing only in their bound constants are not incorrectly treated as duplicates and merged. There are no review comments, so no feedback is provided.
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.
BlockBuilder::AddFunction deduplicates context functions through a map whose hash (StructuralHashIgnoreNDarray) intentionally ignores tensor content for speed. Its equality, however, was the default ffi::StructuralEqual, whose operator() also skips tensor content. As a result two grouped functions that differ only in their bound constants -- e.g. two conv layers with different weights produced by FuseOpsByPattern(bind_constants=True) -- compared equal and were merged, silently dropping all but the first constant and miscompiling the result.
A hash may be approximate, but the dedup equality must be exact. This pr adds a value-aware equality functor (skip_tensor_content=false) and use it as the map's KeyEqual, keeping the fast content-ignoring hash. Functions with identical constants still dedup; functions with differing constants no longer do.