llvm / llvm/llvm-project

opt crash in ScalarEvolution::getBackedgeTakenInfo

Open
#195,176 3 comments 0 reactions 0 assignees View on GitHub
confirmed crash-on-valid llvm:SCEV
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

The following valid IR (reduced from compiling dav1d with UBSan) crashes at trunk with `opt -O3` (https://godbolt.org/z/qo3hnjdK5):

```llvm
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
target triple = "x86_64-grtev4-linux-gnu"

@qm_tbl_8x4 = external global [15 x [2 x [32 x i8]]]

; Function Attrs: optsize
define i32 @dav1d_init_qm_tables(i1 %0, ptr %qm_tbl_32x32) #0 {
br label %2

2: ; preds = %5, %1
%.11 = phi i64 [ 0, %1 ], [ 1, %5 ]
br i1 %0, label %4, label %3

3: ; preds = %2
ret i32 0

split: ; preds = %4
call void @llvm.ubsantrap(i8 0)
unreachable

4: ; preds = %2
%.not = icmp ult i64 %.11, ptrtoint (ptr @qm_tbl_8x4 to i64)
br i1 %.not, label %split, label %5

5: ; preds = %4
call void @untriangle(ptr %qm_tbl_32x32, i32 32)
br label %2
}

; Function Attrs: cold noreturn nounwind memory(inaccessiblemem: write)
declare void @llvm.ubsantrap(i8 immarg) #1

define void @untriangle(ptr %0, i32 %1) {
br label %3

3: ; preds = %21, %2
%.016 = phi ptr [ null, %2 ], [ %22, %21 ]
%.015 = phi i32 [ 0, %2 ], [ %17, %21 ]
%.014 = phi ptr [ %0, %2 ], [ null, %21 ]
%4 = icmp slt i32 %.015, %1
br i1 %4, label %7, label %5

5: ; preds = %3
ret void

6: ; preds = %16, %9
call void @llvm.ubsantrap(i8 0)
unreachable

7: ; preds = %12, %3
%.0.in = phi i32 [ %.0, %12 ], [ %.015, %3 ]
%8 = icmp slt i32 %.0.in, %1
br i1 %8, label %12, label %9

9: ; preds = %7
%10 = ptrtoint ptr %.014 to i64
%11 = sext i32 %1 to i64
%.not = icmp ult i64 %10, %11
br i1 %.not, label %6, label %16

12: ; preds = %7
%.0 = add i32 %.0.in, 1
%13 = load i8, ptr %0, align 1
%14 = sext i32 %.0.in to i64
%15 = getelementptr i8, ptr %.014, i64 %14
store i8 %13, ptr %15, align 1
br label %7

16: ; preds = %9
%17 = add i32 %.015, 1
%18 = ptrtoint ptr %.016 to i64
%19 = xor i64 %18, -1
%20 = sext i32 %17 to i64
%.not1 = icmp ult i64 %19, %20
br i1 %.not1, label %6, label %21

21: ; preds = %16
%22 = getelementptr nusw i8, ptr %.016, i64 %20
br label %3
}

attributes #0 = { optsize }
attributes #1 = { cold noreturn nounwind memory(inaccessiblemem: write) }
```

Output:
```
opt: /root/llvm-project/llvm/include/llvm/ADT/DenseMap.h:1223: llvm::DenseMapIterator::value_type& llvm::DenseMapIterator::operator*() const [with KeyT = const llvm::Loop*; ValueT = llvm::ScalarEvolution::BackedgeTakenInfo; KeyInfoT = llvm::DenseMapInfo; Bucket = llvm::detail::DenseMapPair; bool IsConst = false; llvm::DenseMapIterator::reference = llvm::detail::DenseMapPair&; llvm::DenseMapIterator::value_type = llvm::detail::DenseMapPair]: Assertion `Ptr != End && "dereferencing end() iterator"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace and instructions to reproduce the bug.
Stack dump:
0. Program arguments: /opt/compiler-explorer/clang-assertions-trunk/bin/opt -o /app/output.s -S -S -O3
1. Running pass "require,function(invalidate),require,cgscc(devirt<4>(inline,function-attrs,argpromotion,openmp-opt-cgscc,function(sroa,early-cse,speculative-execution,jump-threading,correlated-propagation,simplifycfg,instcombine,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm,loop-rotate,licm,simple-loop-unswitch),simplifycfg,instcombine,loop(loop-idiom,indvars,extra-simple-loop-unswitch-passes,loop-deletion,loop-unroll-full),sroa,vector-combine,mldst-motion,gvn<>,sccp,bdce,instcombine,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm),coro-elide,simplifycfg,instcombine),function-attrs,function(require),coro-split,coro-annotation-elide)),function(invalidate),cgscc(devirt<4>())" on module ""
2. Running pass "cgscc(devirt<4>(inline,function-attrs,argpromotion,openmp-opt-cgscc,function(sroa,early-cse,speculative-execution,jump-threading,correlated-propagation,simplifycfg,instcombine,aggressive-instcombine,libcalls-shrinkwrap,tailcallelim,simplifycfg,reassociate,constraint-elimination,loop-mssa(loop-instsimplify,loop-simplifycfg,licm,loop-rotate,licm,simple-loop-unswitch),simplifycfg,instcombine,loop(loop-idiom,indvars,extra-simple-loop-unswitch-passes,loop-deletion,loop-unroll-full),sroa,vector-combine,mldst-motion,gvn<>,sccp,bdce,instcombine,jump-threading,correlated-propagation,adce,memcpyopt,dse,move-auto-init,loop-mssa(licm),coro-elide,simplifycfg,instcombine),function-attrs,function(require),coro-split,coro-annotation-elide))" on module ""
3. Running pass "loop(loop-idiom,indvars,extra-simple-loop-unswitch-passes,loop-deletion,loop-unroll-full)" on function "dav1d_init_qm_tables"
#0 0x0000000005ce2c38 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5ce2c38)
#1 0x0000000005cdfa64 llvm::sys::RunSignalHandlers() (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5cdfa64)
#2 0x0000000005cdfbda SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0
#3 0x00007bd44de42520 (/lib/x86_64-linux-gnu/libc.so.6+0x42520)
#4 0x00007bd44de969fc pthread_kill (/lib/x86_64-linux-gnu/libc.so.6+0x969fc)
#5 0x00007bd44de42476 gsignal (/lib/x86_64-linux-gnu/libc.so.6+0x42476)
#6 0x00007bd44de287f3 abort (/lib/x86_64-linux-gnu/libc.so.6+0x287f3)
#7 0x00007bd44de2871b (/lib/x86_64-linux-gnu/libc.so.6+0x2871b)
#8 0x00007bd44de39e96 (/lib/x86_64-linux-gnu/libc.so.6+0x39e96)
#9 0x00000000052c76e2 llvm::ScalarEvolution::getBackedgeTakenInfo(llvm::Loop const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c76e2)
#10 0x00000000052e8bd2 llvm::ScalarEvolution::getBackedgeTakenCount(llvm::Loop const*, llvm::ScalarEvolution::ExitCountKind) (.constprop.0) ScalarEvolution.cpp:0:0
#11 0x00000000052f0e3e llvm::ScalarEvolution::computeSCEVAtScope(llvm::SCEV const*, llvm::Loop const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52f0e3e)
#12 0x00000000052f1294 llvm::ScalarEvolution::getSCEVAtScope(llvm::SCEV const*, llvm::Loop const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52f1294)
#13 0x00000000052c4663 llvm::ScalarEvolution::computeExitLimitFromICmp(llvm::Loop const*, llvm::CmpPredicate, llvm::SCEVUseT, llvm::SCEVUseT, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c4663)
#14 0x00000000052e2b21 llvm::ScalarEvolution::computeExitLimitFromICmp(llvm::Loop const*, llvm::ICmpInst*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52e2b21)
#15 0x00000000052c57c2 llvm::ScalarEvolution::computeExitLimitFromCondImpl(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c57c2)
#16 0x00000000052c5b93 llvm::ScalarEvolution::computeExitLimitFromCondCached(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c5b93)
#17 0x00000000053065e2 llvm::ScalarEvolution::computeExitLimitFromCondFromBinOp(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x53065e2)
#18 0x00000000052c53ea llvm::ScalarEvolution::computeExitLimitFromCondImpl(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c53ea)
#19 0x00000000052c5b93 llvm::ScalarEvolution::computeExitLimitFromCondCached(llvm::ScalarEvolution::ExitLimitCache&, llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c5b93)
#20 0x00000000052c5ccf llvm::ScalarEvolution::computeExitLimitFromCond(llvm::Loop const*, llvm::Value*, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c5ccf)
#21 0x00000000052c5f08 llvm::ScalarEvolution::computeExitLimit(llvm::Loop const*, llvm::BasicBlock*, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c5f08)
#22 0x00000000052c628a llvm::ScalarEvolution::computeBackedgeTakenCount(llvm::Loop const*, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c628a)
#23 0x00000000052c738d llvm::ScalarEvolution::getBackedgeTakenInfo(llvm::Loop const*) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52c738d)
#24 0x00000000052e8405 llvm::ScalarEvolution::getBackedgeTakenCount(llvm::Loop const*, llvm::ScalarEvolution::ExitCountKind) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x52e8405)
#25 0x000000000493705e (anonymous namespace)::IndVarSimplify::predicateLoopExits(llvm::Loop*, llvm::SCEVExpander&) IndVarSimplify.cpp:0:0
#26 0x000000000493d2e6 (anonymous namespace)::IndVarSimplify::run(llvm::Loop*) IndVarSimplify.cpp:0:0
#27 0x000000000493f600 llvm::IndVarSimplifyPass::run(llvm::Loop&, llvm::AnalysisManager&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x493f600)
#28 0x0000000002edae2e llvm::detail::PassModel, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2edae2e)
#29 0x00000000049e54d6 std::optional llvm::PassManager, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runSinglePass, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>>(llvm::Loop&, std::unique_ptr, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>, std::default_delete, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>>>&, llvm::AnalysisManager&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&, llvm::PassInstrumentation&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49e54d6)
#30 0x00000000049e567f llvm::PassManager, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::runWithoutLoopNestPasses(llvm::Loop&, llvm::AnalysisManager&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49e567f)
#31 0x00000000049e6cd4 llvm::PassManager, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&>::run(llvm::Loop&, llvm::AnalysisManager&, llvm::LoopStandardAnalysisResults&, llvm::LPMUpdater&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49e6cd4)
#32 0x00000000049e7d0f llvm::FunctionToLoopPassAdaptor::run(llvm::Function&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x49e7d0f)
#33 0x0000000000f34b7e llvm::detail::PassModel>::run(llvm::Function&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xf34b7e)
#34 0x0000000005a42916 llvm::PassManager>::run(llvm::Function&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5a42916)
#35 0x0000000000f3599e llvm::detail::PassModel>, llvm::AnalysisManager>::run(llvm::Function&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xf3599e)
#36 0x0000000005042a33 llvm::CGSCCToFunctionPassAdaptor::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5042a33)
#37 0x0000000000f346fe llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xf346fe)
#38 0x000000000503b43e llvm::PassManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x503b43e)
#39 0x0000000003229ebe llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>, llvm::AnalysisManager, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3229ebe)
#40 0x000000000503f906 llvm::DevirtSCCRepeatedPass::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x503f906)
#41 0x0000000003229ede llvm::detail::PassModel, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&>::run(llvm::LazyCallGraph::SCC&, llvm::AnalysisManager&, llvm::LazyCallGraph&, llvm::CGSCCUpdateResult&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x3229ede)
#42 0x000000000503ca39 llvm::ModuleToPostOrderCGSCCPassAdaptor::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x503ca39)
#43 0x0000000000f346de llvm::detail::PassModel>::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0xf346de)
#44 0x0000000005a44476 llvm::PassManager>::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5a44476)
#45 0x00000000034df643 llvm::ModuleInlinerWrapperPass::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x34df643)
#46 0x0000000002edae5e llvm::detail::PassModel>::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x2edae5e)
#47 0x0000000005a44476 llvm::PassManager>::run(llvm::Module&, llvm::AnalysisManager&) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x5a44476)
#48 0x00000000009756da llvm::runPassPipeline(llvm::StringRef, llvm::Module&, llvm::TargetMachine*, llvm::TargetLibraryInfoImpl*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::ToolOutputFile*, llvm::StringRef, llvm::ArrayRef, llvm::ArrayRef>, llvm::opt_tool::OutputKind, llvm::opt_tool::VerifierKind, bool, bool, bool, bool, bool, bool, bool, bool) (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x9756da)
#49 0x000000000096977f optMain (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x96977f)
#50 0x00007bd44de29d90 (/lib/x86_64-linux-gnu/libc.so.6+0x29d90)
#51 0x00007bd44de29e40 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x29e40)
#52 0x000000000095ec65 _start (/opt/compiler-explorer/clang-assertions-trunk/bin/opt+0x95ec65)
```

It crashes at least as far back as LLVM 19.1.0 (https://godbolt.org/z/z9KGzcM7T). The test case is not compatible with 18.1.0 because 'getelementptr nusw' is unsupported; if I remove the 'nusw' qualifier, the test case passes both at 18.1.0 and trunk.

I tried to reduce the test case to use a specific pass instead of -O3, but skill issue.

Contributor guide

Open the contributing guide

Research direction

Reproduce the crash with opt -O3 using the reduced LLVM IR from the issue. Start in llvm/lib/Analysis/ScalarEvolution.cpp at ScalarEvolution::getBackedgeTakenInfo and inspect the DenseMap assertion in llvm/include/llvm/ADT/DenseMap.h; done means opt completes successfully on this reproducer without dereferencing an end iterator.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.