-
Notifications
You must be signed in to change notification settings - Fork 15k
Description
Bugzilla Link | 51035 |
Version | trunk |
OS | Linux |
Attachments | loop-fusion-candidate-problem.ll |
CC | @aeubanks,@fhahn,@mikaelholmen,@sidbav |
Extended Description
When doing some tests with fuzzy pass pipelines in opt we hit some assertions in the loop-fusion pass
Running
opt -passes='function(loop-fusion)' -S -o - loop-fusion-candidate-problem.ll
results in an assertion in FusionCandidate::reportInvalidCandidate:
opt: ../lib/Transforms/Scalar/LoopFuse.cpp:374: bool {anonymous}::FusionCandidate::reportInvalidCandidate(llvm::Statistic&) const: Assertion `L && Preheader && "Fusion candidate not initialized properly!"' failed.
PLEASE submit a bug report to ... and include the crash backtrace.
Stack dump:
0. Program arguments: /bin/opt -passes=function(loop-fusion) -S -o - loop-fusion-candidate-problem.ll
#0 0x00000000030e09a8 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/bin/opt+0x30e09a8)
#1 0x00000000030de47e SignalHandler(int) Signals.cpp:0:0
#2 0x00007f4bcdf87630 __restore_rt sigaction.c:0:0
#3 0x00007f4bcb8e4387 raise (/lib64/libc.so.6+0x36387)
#4 0x00007f4bcb8e5a78 abort (/lib64/libc.so.6+0x37a78)
#5 0x00007f4bcb8dd1a6 __assert_fail_base (/lib64/libc.so.6+0x2f1a6)
#6 0x00007f4bcb8dd252 (/lib64/libc.so.6+0x2f252)
#7 0x0000000002fb7e0c (/bin/opt+0x2fb7e0c)
#8 0x0000000002fba9b5 (anonymous namespace)::LoopFuser::collectFusionCandidates(llvm::SmallVector<llvm::Loop*, 4u> const&) LoopFuse.cpp:0:0
#9 0x0000000002fc41fb (anonymous namespace)::LoopFuser::fuseLoops(llvm::Function&) LoopFuse.cpp:0:0
#10 0x0000000002fc5353 llvm::LoopFusePass::run(llvm::Function&, llvm::AnalysisManagerllvm::Function&) (/bin/opt+0x2fc5353)
#11 0x00000000033bda1e llvm::detail::PassModel<llvm::Function, llvm::LoopFusePass, llvm::PreservedAnalyses, llvm::AnalysisManagerllvm::Function >::run(llvm::Function&, llvm::AnalysisManagerllvm::Function&) (//bin/opt+0x33bda1e)
#12 0x00000000027ef715 llvm::PassManager<llvm::Function, llvm::AnalysisManagerllvm::Function >::run(llvm::Function&, llvm::AnalysisManagerllvm::Function&) (/bin/opt+0x27ef715)
#13 0x0000000000cfdb0e llvm::detail::PassModel<llvm::Function, llvm::PassManager<llvm::Function, llvm::AnalysisManagerllvm::Function >, llvm::PreservedAnalyses, llvm::AnalysisManagerllvm::Function >::run(llvm::Function&, llvm::AnalysisManagerllvm::Function&) (//bin/opt+0xcfdb0e)
#14 0x00000000027ee24e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (/bin/opt+0x27ee24e)
#15 0x0000000000779a6e llvm::detail::PassModel<llvm::Module, llvm::ModuleToFunctionPassAdaptor, llvm::PreservedAnalyses, llvm::AnalysisManagerllvm::Module >::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (/bin/opt+0x779a6e)
#16 0x00000000027ebb18 llvm::PassManager<llvm::Module, llvm::AnalysisManagerllvm::Module >::run(llvm::Module&, llvm::AnalysisManagerllvm::Module&) (/bin/opt+0x27ebb18)
#17 0x000000000078538b llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRefllvm::StringRef, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool) (/bin/opt+0x78538b)
#18 0x00000000006b4865 main (/bin/opt+0x6b4865)
The same thing happens with
opt -enable-new-pm=1 -loop-fusion -S -o - loop-fusion-candidate-problem.ll
but not with
opt -enable-new-pm=0 -loop-fusion -S -o - loop-fusion-candidate-problem.ll
Looking at LoopFuse.cpp it looks like with the legacy PM the pass requires LoopSimplify to be run before the pass. So the pass implementation in some sense expects the loops to be in loop simplify form (at least that is what has been tested in the past with legacy PM). But with the new pass manager there is no such requirement.
It is perhaps also a bit silly that the FusionCandidate c'tor is calling reportInvalidCandidate without first verifying that the CFG requirements are valid. Normally when constructing FusionCandidate objects, the new object is validated post construction by using one of the isEligibleForFusion/verify member functions. But the c'tor itself is doing similar verification, but without checking the CFG requirement before calling reportInvalidCandidate.
A possible fix/workaround would be to also add such checks in the c'tor like this:
diff --git a/llvm/lib/Transforms/Scalar/LoopFuse.cpp b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
index 889358bade31..e411861e2b09 100644
--- a/llvm/lib/Transforms/Scalar/LoopFuse.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFuse.cpp
@@ -192,6 +192,12 @@ struct FusionCandidate {
GuardBranch(L->getLoopGuardBranch()), PP(PP), AbleToPeel(canPeel(L)),
Peeled(false), DT(DT), PDT(PDT), ORE(ORE) {
- if (!isValid()) {
-
LLVM_DEBUG(dbgs() << "FC has invalid CFG requirements!\n");
-
invalidate();
-
return;
- }
- // Walk over all blocks in the loop and check for conditions that may
// prevent fusion. For each block, walk over all instructions and collect
// the memory reads and writes If any instructions that prevent fusion are
But maybe there are other problems hiding here as well. Unless the loop simplify form is forced somehow. One difference between the pass managers would be that the pass either would perform loop-fusion (including loop-simplify) on the given example, or just failing to identify any valid candidates and skip transformation altogether.