Limit non-local call dependency walks in MemoryDependenceAnalysis - #8997
Closed
Damyan Pepper (damyanp) wants to merge 2 commits into
Closed
Damyan Pepper (damyanp) wants to merge 2 commits into
Damyan Pepper (damyanp) wants to merge 2 commits into
Conversation
GVN queries non-local dependencies for read-only calls (e.g. dx.op.createHandleForLib). When clobbers sit on conditional paths the walk visits every block back to the function entry, making GVN quadratic on large shaders. Once a non-Def dependency is found the result is unusable by GVN, so stop scanning after 100 blocks and mark the rest Unknown. Output is unchanged; on a Dawn-generated repro total compile time drops from ~46s to ~8s. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
GVN can take a very long time on large shaders with many resource accesses. One Tint/Dawn-generated compute shader took about 45s to compile at
-O3, and about 84% of that was spent in the two GVN runs (about 15s each).Root cause
Profiling shows all of the GVN time is spent in this path:
GVN::processInstruction→ValueTable::lookup_or_add_call→MemoryDependenceAnalysis::getNonLocalCallDependency→getCallSiteDependencyFromThe queries are for read-only calls, mostly
dx.op.createHandleForLibon RW buffers. TherawBufferStorecalls that clobber them are inside conditional blocks, so there is always a path around them. As a result, each query walks every block back to the function entry. With N inlined call sites, the total cost is O(N × function size), which is quadratic.Upstream LLVM limits the number of blocks visited for non-local pointer dependencies, but has no such limit for call dependencies.
Fix
In
getNonLocalCallDependency, once the walk has found a dependency that is not a Def (a clobber or unknown) and has visited more than 100 blocks, stop scanning. The remaining blocks are markedUnknown.GVN only uses a non-local call dependency when it is a single Def whose block dominates the query. A result that already contains a clobber or unknown entry can never be used, so this cutoff does not change GVN output. The only other user of this API is
MemDepPrinter.Results
On the repro,
-T cs_6_0 -O3 -HV 2018:Testing
tools/clang/test/DXC/Passes/GVN/nonlocal-call-dep-limit.ll. It checks two cases:check-allpasses with no failures (3025 passed, 7 expected failures).Assisted by GitHub Copilot.