[llvm-bugs] [Bug 50973] New: [SimpleLoopUnswitch] Assertion `!NodePtr->isKnownSentinel()' failed when catchswitch BB is cloned

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Jul 3 17:34:43 PDT 2021


https://bugs.llvm.org/show_bug.cgi?id=50973

            Bug ID: 50973
           Summary: [SimpleLoopUnswitch] Assertion
                    `!NodePtr->isKnownSentinel()' failed when catchswitch
                    BB is cloned
           Product: libraries
           Version: trunk
          Hardware: All
                OS: All
            Status: NEW
          Severity: release blocker
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: aheejin at gmail.com
                CC: chandlerc at gmail.com, llvm-bugs at lists.llvm.org,
                    rnk at google.com

Running

$ opt -simple-loop-unswitch -enable-nontrivial-unswitch test.ll

When test.ll is

```
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
target triple = "wasm32-unknown-emscripten"

declare i32 @__gxx_wasm_personality_v0(...)

declare void @foo()

define void @test(i1 %arg) personality i8* bitcast (i32 (...)*
@__gxx_wasm_personality_v0 to i8*) {
entry:
  br label %while.body

while.body:                                       ; preds = %cleanup, %entry
  br i1 %arg, label %if.end, label %if.then

if.then:                                          ; preds = %while.body
  br label %if.end

if.end:                                           ; preds = %if.then,
%while.body
  invoke void @foo()
          to label %cleanup unwind label %catch.dispatch

catch.dispatch:                                   ; preds = %invoke.cont,
%if.end
  %0 = catchswitch within none [label %catch] unwind to caller

catch:                                            ; preds = %catch.dispatch
  %1 = catchpad within %0 [i8* null]
  unreachable

cleanup:                                          ; preds = %invoke.cont
  br label %while.body
}
```

crashes with the error message
```
opt:
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/ADT/ilist_iterator.h:138:
llvm::ilist_iterator::reference
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true,
false, void>, false, false>::operator*() const [OptionsT =
llvm::ilist_detail::node_options<llvm::Instruction, true, false, void>,
IsReverse = false, IsConst = false]: Assertion `!NodePtr->isKnownSentinel()'
failed.
PLEASE submit a bug report to https://bugs.llvm.org/ and include the crash
backtrace.
Stack dump:
0.      Program arguments:
/usr/local/google/home/aheejin/llvm-git/install.debug/bin/opt
-simple-loop-unswitch -enable-nontrivial-unswitch reduced.ll
 #0 0x00007f81093eecaa llvm::sys::PrintStackTrace(llvm::raw_ostream&, int)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Support/Unix/Signals.inc:565:11
 #1 0x00007f81093eee5b PrintStackTraceSignalHandler(void*)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Support/Unix/Signals.inc:632:1
 #2 0x00007f81093ed673 llvm::sys::RunSignalHandlers()
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Support/Signals.cpp:76:5
 #3 0x00007f81093ef495 SignalHandler(int)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Support/Unix/Signals.inc:407:1
 #4 0x00007f810dea6140 __restore_rt
(/lib/x86_64-linux-gnu/libpthread.so.0+0x14140)
 #5 0x00007f8108c3fce1 raise ./signal/../sysdeps/unix/sysv/linux/raise.c:51:1
 #6 0x00007f8108c29537 abort ./stdlib/abort.c:81:7
 #7 0x00007f8108c2940f get_sysdep_segment_value ./intl/loadmsgcat.c:509:8
 #8 0x00007f8108c2940f _nl_load_domain ./intl/loadmsgcat.c:970:34
 #9 0x00007f8108c38662 (/lib/x86_64-linux-gnu/libc.so.6+0x34662)
#10 0x00007f810ae1350f
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true,
false, void>, false, false>::operator*() const
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/ADT/ilist_iterator.h:0:5
#11 0x00007f810ae630c5
llvm::simplify_type<llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,
true, false, void>, false, false>
>::getSimplifiedValue(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,
true, false, void>, false, false> const&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/ADT/ilist_iterator.h:189:64
#12 0x00007f810ae677e5 llvm::isa_impl_wrap<llvm::PHINode,
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true,
false, void>, false, false> const,
llvm::Instruction*>::doit(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,
true, false, void>, false, false> const&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/Support/Casting.h:123:27
#13 0x00007f810ae56405 bool llvm::isa<llvm::PHINode,
llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction, true,
false, void>, false, false>
>(llvm::ilist_iterator<llvm::ilist_detail::node_options<llvm::Instruction,
true, false, void>, false, false> const&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/Support/Casting.h:142:3
#14 0x00007f810ae509d4 SplitBlockImpl(llvm::BasicBlock*, llvm::Instruction*,
llvm::DomTreeUpdater*, llvm::DominatorTree*, llvm::LoopInfo*,
llvm::MemorySSAUpdater*, llvm::Twine const&, bool)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp:769:10
#15 0x00007f810ae501c7 llvm::SplitBlock(llvm::BasicBlock*, llvm::Instruction*,
llvm::DominatorTree*, llvm::LoopInfo*, llvm::MemorySSAUpdater*, llvm::Twine
const&, bool)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Utils/BasicBlockUtils.cpp:816:3
#16 0x00007f810c0146ca buildClonedLoopBlocks(llvm::Loop&, llvm::BasicBlock*,
llvm::BasicBlock*, llvm::ArrayRef<llvm::BasicBlock*>, llvm::BasicBlock*,
llvm::BasicBlock*, llvm::BasicBlock*, llvm::SmallDenseMap<llvm::BasicBlock*,
llvm::BasicBlock*, 16u, llvm::DenseMapInfo<llvm::BasicBlock*>,
llvm::detail::DenseMapPair<llvm::BasicBlock*, llvm::BasicBlock*> > const&,
llvm::ValueMap<llvm::Value const*, llvm::WeakTrackingVH,
llvm::ValueMapConfig<llvm::Value const*, llvm::sys::SmartMutex<false> > >&,
llvm::SmallVectorImpl<llvm::cfg::Update<llvm::BasicBlock*> >&,
llvm::AssumptionCache&, llvm::DominatorTree&, llvm::LoopInfo&,
llvm::MemorySSAUpdater*)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1120:11
#17 0x00007f810c012292 unswitchNontrivialInvariants(llvm::Loop&,
llvm::Instruction&, llvm::ArrayRef<llvm::Value*>,
llvm::SmallVectorImpl<llvm::BasicBlock*>&, llvm::IVConditionInfo&,
llvm::DominatorTree&, llvm::LoopInfo&, llvm::AssumptionCache&,
llvm::function_ref<void (bool, bool, llvm::ArrayRef<llvm::Loop*>)>,
llvm::ScalarEvolution*, llvm::MemorySSAUpdater*)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2154:25
#18 0x00007f810c00caa9 unswitchBestCondition(llvm::Loop&, llvm::DominatorTree&,
llvm::LoopInfo&, llvm::AssumptionCache&, llvm::AAResults&,
llvm::TargetTransformInfo&, llvm::function_ref<void (bool, bool,
llvm::ArrayRef<llvm::Loop*>)>, llvm::ScalarEvolution*, llvm::MemorySSAUpdater*)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:2961:3
#19 0x00007f810c00ab8c unswitchLoop(llvm::Loop&, llvm::DominatorTree&,
llvm::LoopInfo&, llvm::AssumptionCache&, llvm::AAResults&,
llvm::TargetTransformInfo&, bool, llvm::function_ref<void (bool, bool,
llvm::ArrayRef<llvm::Loop*>)>, llvm::ScalarEvolution*, llvm::MemorySSAUpdater*)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:3037:7
#20 0x00007f810c00a84a llvm::SimpleLoopUnswitchPass::run(llvm::Loop&,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:3090:7
#21 0x00007f810e153297 llvm::detail::PassModel<llvm::Loop,
llvm::SimpleLoopUnswitchPass, llvm::PreservedAnalyses,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManagerInternal.h:85:17
#22 0x00007f810be16032 llvm::Optional<llvm::PreservedAnalyses>
llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop,
llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&,
llvm::LPMUpdater&>::runSinglePass<llvm::Loop,
std::__1::unique_ptr<llvm::detail::PassConcept<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>,
std::__1::default_delete<llvm::detail::PassConcept<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&> > > >(llvm::Loop&,
std::__1::unique_ptr<llvm::detail::PassConcept<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>,
std::__1::default_delete<llvm::detail::PassConcept<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&> > >&,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&,
llvm::PassInstrumentation&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/Transforms/Scalar/LoopPassManager.h:378:8
#23 0x00007f810be14cfa llvm::PassManager<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&,
llvm::LPMUpdater&>::runWithoutLoopNestPasses(llvm::Loop&,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/LoopPassManager.cpp:143:10
#24 0x00007f810be14771 llvm::PassManager<llvm::Loop,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&,
llvm::AnalysisManager<llvm::Loop, llvm::LoopStandardAnalysisResults&>&,
llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/LoopPassManager.cpp:0:32
#25 0x00007f810e0d7207 llvm::detail::PassModel<llvm::Loop,
llvm::PassManager<llvm::Loop, llvm::AnalysisManager<llvm::Loop,
llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&,
llvm::LPMUpdater&>, llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Loop,
llvm::LoopStandardAnalysisResults&>, llvm::LoopStandardAnalysisResults&,
llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager<llvm::Loop,
llvm::LoopStandardAnalysisResults&>&, llvm::LoopStandardAnalysisResults&,
llvm::LPMUpdater&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManagerInternal.h:85:17
#26 0x00007f810be153bd llvm::FunctionToLoopPassAdaptor::run(llvm::Function&,
llvm::AnalysisManager<llvm::Function>&)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/Transforms/Scalar/LoopPassManager.cpp:279:14
#27 0x00007f810e156747 llvm::detail::PassModel<llvm::Function,
llvm::FunctionToLoopPassAdaptor, llvm::PreservedAnalyses,
llvm::AnalysisManager<llvm::Function> >::run(llvm::Function&,
llvm::AnalysisManager<llvm::Function>&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManagerInternal.h:85:17
#28 0x00007f8109c2be2d llvm::PassManager<llvm::Function,
llvm::AnalysisManager<llvm::Function> >::run(llvm::Function&,
llvm::AnalysisManager<llvm::Function>&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManager.h:509:16
#29 0x00007f810e14a887 llvm::detail::PassModel<llvm::Function,
llvm::PassManager<llvm::Function, llvm::AnalysisManager<llvm::Function> >,
llvm::PreservedAnalyses, llvm::AnalysisManager<llvm::Function>
>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManagerInternal.h:85:17
#30 0x00007f8109c2ab03 llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&,
llvm::AnalysisManager<llvm::Module>&)
/usr/local/google/home/aheejin/llvm-git/llvm/lib/IR/PassManager.cpp:117:14
#31 0x00000000002b7547 llvm::detail::PassModel<llvm::Module,
llvm::ModuleToFunctionPassAdaptor, llvm::PreservedAnalyses,
llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&,
llvm::AnalysisManager<llvm::Module>&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManagerInternal.h:85:17
#32 0x00007f8109c2af7d llvm::PassManager<llvm::Module,
llvm::AnalysisManager<llvm::Module> >::run(llvm::Module&,
llvm::AnalysisManager<llvm::Module>&)
/usr/local/google/home/aheejin/llvm-git/llvm/include/llvm/IR/PassManager.h:509:16
#33 0x00000000002813f7 llvm::runPassPipeline(llvm::StringRef, llvm::Module&,
llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*,
llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef,
llvm::ArrayRef<llvm::StringRef>, llvm::opt_tool::OutputKind,
llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool)
/usr/local/google/home/aheejin/llvm-git/llvm/tools/opt/NewPMDriver.cpp:457:3
#34 0x00000000002cb10e main
/usr/local/google/home/aheejin/llvm-git/llvm/tools/opt/opt.cpp:830:12
#35 0x00007f8108c2ad0a __libc_start_main ./csu/../csu/libc-start.c:308:16
#36 0x000000000027a77a _start
(/usr/local/google/home/aheejin/llvm-git/install.debug/bin/opt+0x27a77a)
Aborted
```

The reason this crash is while we are cloning loop exit blocks, we try to clone
a 'catchswitch' BB here:
https://github.com/llvm/llvm-project/blob/89c1c64cc3170a05a881bb9954feafc3edca6704/llvm/lib/Transforms/Scalar/SimpleLoopUnswitch.cpp#L1115-L1120

But 'catchswitch' BB cannot be cloned and its predecessors cannot be split,
because tokens can't be phi'd. The old LoopUnswitch pass avoids this by bailing
out if BasicBlock::canSplitPredecessors
(https://github.com/llvm/llvm-project/blob/89c1c64cc3170a05a881bb9954feafc3edca6704/llvm/lib/IR/BasicBlock.cpp#L350-L360)
returns true:
https://github.com/llvm/llvm-project/blob/89c1c64cc3170a05a881bb9954feafc3edca6704/llvm/lib/Transforms/Scalar/LoopUnswitch.cpp#L706-L707

1. By the way, I am not familiar with SimpleLoopUnswitch pass.. Why do we need
to clone loop exit blocks? Would only cloning the loop blocks and let the
cloned loops merge in (non-cloned) loop exit blocks not work?

2. I tried to insert BasicBlock::canSplitPredecessors check to
SimpleLoopUnswitch too, but it was hard to find the right place. Checking it
right before splitting the exit blocks wouldn't work because we have already
cleaned all loop blocks by then. The old LoopUnswitch pass checks it before
doing any transformation and does not optimize any loop with 'catchswitch' exit
blocks. Should we do a similar thing too?

3. It looks this bug existed from the beginning of SimpleLoopUnswitch pass, so
I am rather surprised this hasn't been hit by WinEH users. Reid, is this code
pass not being used by WinEH users? Or the way WinEH code is generated makes it
not vulnerable to this or something?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20210704/71464cc8/attachment-0001.html>


More information about the llvm-bugs mailing list