This is an archive of the discontinued LLVM Phabricator instance.

Require DominatorTree when requiring/preserving LoopInfo in the old pass manager
ClosedPublic

Authored by uabelho on May 14 2018, 5:25 AM.

Details

Summary

Require DominatorTree when requiring/preserving LoopInfo in the old pass manager

BreakCriticalEdges tries to keep LoopInfo and DominatorTree updated if they
exist. However, since commit r321653 and r321805, to update LoopInfo we
must have a DominatorTree, or we will hit an assert.

To fix this we now make a couple of passes that only required/preserved
LoopInfo also require DominatorTree.

This solves PR37334.

Diff Detail

Event Timeline

uabelho created this revision.May 14 2018, 5:25 AM

Like I said in the bug, I would rather fix BranchProbabilityInfoWrapperPass::getAnalysisUsage.

uabelho added a comment.EditedMay 14 2018, 10:19 PM

Like I said in the bug, I would rather fix BranchProbabilityInfoWrapperPass::getAnalysisUsage.

Alright, I'll do that then.

I can't say I really understand though.

What if we in some completely other situation, without running BranchProbabilityInfo, do BreakCriticalEdges and LI is available and DT isn't?
Then BreakCriticalEdges will (try to) update LI, but since there is no DT, the same assert will trigger again? Or what is it I'm missing?

Full stacktrace when it hits the assert:

opt: ../lib/Transforms/Utils/BasicBlockUtils.cpp:337: void UpdateAnalysisInformation(llvm::BasicBlock *, llvm::BasicBlock *, ArrayRef<llvm::BasicBlock *>, llvm::DominatorTree *, llvm::LoopInfo *, bool, bool &): Assertion `DT && "DT should be available to update LoopInfo!"' failed.
Stack dump:
0. Program arguments: build-all-Debug/bin/opt test/Transforms/Util/PR37334-break-crit-edges-require-dt.ll -o - -loop-sink -break-crit-edges -branch-prob -S -debug-pass=Executions

  1. Running pass 'Function Pass Manager' on module 'test/Transforms/Util/PR37334-break-crit-edges-require-dt.ll'.
  2. Running pass 'Break critical edges in CFG' on function '@f1'

#0 0x00000000035e086c llvm::sys::PrintStackTrace(llvm::raw_ostream&) /data/repo/llvm-patch/build-all-Debug/../lib/Support/Unix/Signals.inc:399:5
#1 0x00000000035e0a19 PrintStackTraceSignalHandler(void*) /data/repo/llvm-patch/build-all-Debug/../lib/Support/Unix/Signals.inc:463:1
#2 0x00000000035defc3 llvm::sys::RunSignalHandlers() /data/repo/llvm-patch/build-all-Debug/../lib/Support/Signals.cpp:50:5
#3 0x00000000035e105e SignalHandler(int) /data/repo/llvm-patch/build-all-Debug/../lib/Support/Unix/Signals.inc:253:1
#4 0x00007f291488e330 restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x10330)
#5 0x00007f291347dc37 gsignal /build/eglibc-ripdx6/eglibc-2.19/signal/../nptl/sysdeps/unix/sysv/linux/raise.c:56:0
#6 0x00007f2913481028 abort /build/eglibc-ripdx6/eglibc-2.19/stdlib/abort.c:91:0
#7 0x00007f2913476bf6
assert_fail_base /build/eglibc-ripdx6/eglibc-2.19/assert/assert.c:92:0
#8 0x00007f2913476ca2 (/lib/x86_64-linux-gnu/libc.so.6+0x2fca2)
#9 0x000000000360796a UpdateAnalysisInformation(llvm::BasicBlock*, llvm::BasicBlock*, llvm::ArrayRef<llvm::BasicBlock*>, llvm::DominatorTree*, llvm::LoopInfo*, bool, bool&) /data/repo/llvm-patch/build-all-Debug/../lib/Transforms/Utils/BasicBlockUtils.cpp:338:13
#10 0x0000000003606e1f llvm::SplitBlockPredecessors(llvm::BasicBlock*, llvm::ArrayRef<llvm::BasicBlock*>, char const*, llvm::DominatorTree*, llvm::LoopInfo*, bool) /data/repo/llvm-patch/build-all-Debug/../lib/Transforms/Utils/BasicBlockUtils.cpp:519:3
#11 0x000000000360ba51 llvm::SplitCriticalEdge(llvm::TerminatorInst*, unsigned int, llvm::CriticalEdgeSplittingOptions const&) /data/repo/llvm-patch/build-all-Debug/../lib/Transforms/Utils/BreakCriticalEdges.cpp:285:23
#12 0x00000000036068b1 llvm::SplitAllCriticalEdges(llvm::Function&, llvm::CriticalEdgeSplittingOptions const&) /data/repo/llvm-patch/build-all-Debug/../lib/Transforms/Utils/BasicBlockUtils.cpp:285:13
#13 0x000000000360cab7 (anonymous namespace)::BreakCriticalEdges::runOnFunction(llvm::Function&) /data/repo/llvm-patch/build-all-Debug/../lib/Transforms/Utils/BreakCriticalEdges.cpp:54:11
#14 0x0000000002cdc95d llvm::FPPassManager::runOnFunction(llvm::Function&) /data/repo/llvm-patch/build-all-Debug/../lib/IR/LegacyPassManager.cpp:1520:23
#15 0x0000000002cdcc95 llvm::FPPassManager::runOnModule(llvm::Module&) /data/repo/llvm-patch/build-all-Debug/../lib/IR/LegacyPassManager.cpp:1541:16
#16 0x0000000002cdd47e (anonymous namespace)::MPPassManager::runOnModule(llvm::Module&) /data/repo/llvm-patch/build-all-Debug/../lib/IR/LegacyPassManager.cpp:1597:23
#17 0x0000000002cdcf7b llvm::legacy::PassManagerImpl::run(llvm::Module&) /data/repo/llvm-patch/build-all-Debug/../lib/IR/LegacyPassManager.cpp:1700:16
#18 0x0000000002cdd9c1 llvm::legacy::PassManager::run(llvm::Module&) /data/repo/llvm-patch/build-all-Debug/../lib/IR/LegacyPassManager.cpp:1731:3
#19 0x0000000000c19c25 main /data/repo/llvm-patch/build-all-Debug/../tools/opt/opt.cpp:762:3
#20 0x00007f2913468f45 __libc_start_main /build/eglibc-ripdx6/eglibc-2.19/csu/libc-start.c:321:0
#21 0x0000000000bde519 _start (build-all-Debug/bin/opt+0xbde519)
Abort

Adding the require to BranchProbabilityInfoWrapperPass::getAnalysisUsage makes the crash go away too, but I don't understand
why/how that is the proper solution so I'd be happy if you could explain so I can at least write a proper commit message then :)

Thanks!

LoopInfo has a dependency on DominatorTree: when a pass requests the LoopInfo analysis, DominatorTree gets implicitly added to the pass pipeline. This is fine so far, but doesn't take into account what happens when a pass preserves LoopInfo or DominatorTree. When the CFG is mutated, we need to update LoopInfo, and at that point, we again need the DominatorTree. Normally it should be available: passes which require LoopInfo usually also require DomTree, and passes which preserve LoopInfo also usually preserve DomTree.

But BranchProbabilityInfo is weird: it requires LoopInfo, but not DomTree. In the simple case without any preserved analysis passes, this works because the pass manager implicitly adds the DomTree run anyway. But in the more complicated case, where there's some pass in between the LoopInfo run and the BranchProbabilityInfo run, it doesn't work. The DomTree gets computed, then dropped after LoopInfo, because no future pass in the pipeline requires it. But we actually need it to preserve LoopInfo.

One way to solve this problem is, like you're suggesting, to make any pass which uses a DomTree to update LoopInfo explicitly require a DomTree. This works, but adds unnecessary computation to the pass pipeline: we compute the domtree even if nothing actually needs it.

The other way to solve the issue is to always require/preserve domtree anywhere that requires/preseves LoopInfo. This way, we always have a domtree if we have loopinfo, and we only compute the domtree in cases where we actually need it.

uabelho updated this revision to Diff 146998.May 16 2018, 12:40 AM
uabelho retitled this revision from [BreakCriticalEdges] Require DominatorTree when using the old pass manager to Require DominatorTree when requiring/preserving LoopInfo in the old pass manager.
uabelho edited the summary of this revision. (Show Details)

Ok, added require of DT to BranchProbabilityInfo (and LazyBlockFrequencyInfo and LazyBranchProbabilityInfo since BreakCriticalEdges crashed the same way when running them) instead of to BreakCriticalEdges.

Thanks for the explanation!

I searched through the code and found two other passes that would also trigger the assertion, so I added the require to them too.
I wouldn't be surprised if there is some other pass that I missed but I haven't seen any other crash.

efriedma accepted this revision.May 16 2018, 3:21 PM

LGTM

lib/Analysis/BranchProbabilityInfo.cpp
1008

I don't think you need to specifically mention break-crit-edges here; just a brief explanation of the general problem is enough.

This revision is now accepted and ready to land.May 16 2018, 3:21 PM
uabelho updated this revision to Diff 147254.May 17 2018, 12:45 AM

Updated the comments in the code to not specifically mention -break-crit-edges.

LGTM

Thanks!

I'll push this in a little bit then.

This revision was automatically updated to reflect the committed changes.