[AArch64][ShrinkWrap] LDARB has hasUnmodeledSideEffects set to true, preventing split restore
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Godbolt: https://godbolt.org/z/hvGdfobeM
In this example, bb.0 -> bb.3 is the fast path and does not require a stack frame. Only the initialization paths through bb.1 / bb.2 require one.
Current CFG:
bb0 -----------> bb3
|
v
bb1 -----------> bb3
|
v
bb2 -----------> bb3
After split restore, the dirty paths should go through a separate restore block, while the fast bb.0 -> bb.3 edge should remain unchanged:
bb0 ----------------------> bb3
|
v
bb1 -----> restore -------> bb3
| ^
v |
bb2 ----------+
However, bb.0 contains an LDARB used to read the static initialization guard. LDARB has hasUnmodeledSideEffects() == true, causing ShrinkWrap::useOrDefCSROrFI() to conservatively mark bb.0 as potentially using the stack (https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/ShrinkWrap.cpp#L328).
As a result, bb.0 is considered dirty, so postShrinkWrapping() does not identify bb.0 -> bb.3 as a clean predecessor and cannot perform the split restore.
The LDARB here only accesses the global guard variable, so hasUnmodeledSideEffects prevents an otherwise valid split restore.
Contributor guide
Research direction
Reproduce the AArch64 example from the Godbolt link, then inspect llvm/lib/CodeGen/ShrinkWrap.cpp around line 328 and the postShrinkWrapping() path that evaluates clean predecessors. Determine how the LDARB guard access affects useOrDefCSROrFI(); done means the bb.0 -> bb.3 fast edge remains unchanged while the dirty initialization paths use a separate restore block.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 52/100