[VPlan] Crashes at -O3: Assertion `(!BB || Parent == NodeTrait::getParent(const_cast<NodeT *>(BB))) && "cannot get DomTreeNode of block with different parent"' failed.
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Compiler Explorer: https://godbolt.org/z/KW531jq7f
Reproduce:
```
opt -O3 small.ll -o /dev/null
```
Crash:
```
opt: /data/x27zhou/compiler-nightly/src/llvm-project/llvm/include/llvm/Support/GenericDomTree.h:429: DomTreeNodeBase *llvm::DominatorTreeBase::getNode(const NodeT *) const [NodeT = llvm::VPBlockBase, IsPostDom = false]: Assertion `(!BB || Parent == NodeTrait::getParent(const_cast(BB))) && "cannot get DomTreeNode of block with different parent"' 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 -O3 small.ll -o /dev/null
1. Running pass "function(drop-unnecessary-assumes,float2int,lower-constant-intrinsics,chr,loop(loop-rotate,loop-deletion),loop-distribute,inject-tli-mappings,loop-vectorize,drop-unnecessary-assumes,infer-alignment,loop-load-elim,instcombine,simplifycfg,slp-vectorizer,vector-combine,instcombine,loop-unroll,transform-warning,sroa,infer-alignment,instcombine,loop-mssa(licm),alignment-from-assumptions,loop-sink,instsimplify,div-rem-pairs,mergeicmps,expand-memcmp,tailcallelim,simplifycfg)" on module "small.ll"
2. Running pass "loop-vectorize" on function "j"
Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
0 opt 0x00005571b5ed4697 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 39
1 opt 0x00005571b5ed233a llvm::sys::RunSignalHandlers() + 154
2 opt 0x00005571b5ed5535
3 libc.so.6 0x00007fda7b6e8520
4 libc.so.6 0x00007fda7b73c9fc pthread_kill + 300
5 libc.so.6 0x00007fda7b6e8476 raise + 22
6 libc.so.6 0x00007fda7b6ce7f3 abort + 211
7 libc.so.6 0x00007fda7b6ce71b
8 libc.so.6 0x00007fda7b6dfe96
9 opt 0x00005571b4381635
10 opt 0x00005571b443520f
11 opt 0x00005571b4432e29 llvm::verifyVPlanIsValid(llvm::VPlan const&) + 2649
12 opt 0x00005571b41c9081 llvm::LoopVectorizationPlanner::executePlan(llvm::ElementCount, unsigned int, llvm::VPlan&, llvm::InnerLoopVectorizer&, llvm::DominatorTree*, llvm::LoopVectorizationPlanner::EpilogueVectorizationKind) + 1553
13 opt 0x00005571b41d5371 llvm::LoopVectorizePass::processLoop(llvm::Loop*) + 12833
14 opt 0x00005571b41de9e4 llvm::LoopVectorizePass::runImpl(llvm::Function&) + 452
15 opt 0x00005571b41df29f llvm::LoopVectorizePass::run(llvm::Function&, llvm::AnalysisManager&) + 1183
16 opt 0x00005571b3cbb64d
17 opt 0x00005571b5cb7617 llvm::PassManager>::run(llvm::Function&, llvm::AnalysisManager&) + 407
18 opt 0x00005571b245cbbd
19 opt 0x00005571b5cbb15e llvm::ModuleToFunctionPassAdaptor::run(llvm::Module&, llvm::AnalysisManager&) + 478
20 opt 0x00005571b1f8a5cd
21 opt 0x00005571b5cb66f7 llvm::PassManager>::run(llvm::Module&, llvm::AnalysisManager&) + 407
22 opt 0x00005571b1f8218f 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) + 11455
23 opt 0x00005571b1f77f9c optMain + 9068
24 libc.so.6 0x00007fda7b6cfd90
25 libc.so.6 0x00007fda7b6cfe40 __libc_start_main + 128
26 opt 0x00005571b1f75555 _start + 37
[1] 932404 IOT instruction (core dumped) opt -O3 small.ll -o /dev/null
```
small.ll
```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-unknown-linux-gnu"
@g = external global i32
@a = external global i32
define void @j(i32 %0, ptr %d) {
entry:
br label %a1
a1: ; preds = %sw.epilog25, %entry
%b.0 = phi i32 [ 10, %entry ], [ 0, %sw.epilog25 ]
br label %d1
d1: ; preds = %for.cond15, %a1
%e.0 = phi i32 [ -2114967296, %a1 ], [ 0, %for.cond15 ]
%b.1 = phi i32 [ %b.0, %a1 ], [ %b.2, %for.cond15 ]
br label %for.cond1
for.cond1: ; preds = %for.inc40, %d1
%h.0 = phi i32 [ 0, %d1 ], [ %inc41, %for.inc40 ]
%cmp2 = icmp slt i32 %h.0, 8
br i1 %cmp2, label %for.cond4, label %for.end42
for.cond4: ; preds = %for.inc37, %for.cond1
%e.22 = phi i32 [ 0, %for.inc37 ], [ %e.0, %for.cond1 ]
%c.0 = phi i32 [ %inc38, %for.inc37 ], [ 0, %for.cond1 ]
%cmp5 = icmp slt i32 %c.0, 7
br i1 %cmp5, label %g, label %for.inc40
g: ; preds = %for.cond4
%tobool12.not = icmp eq i32 %0, 0
br i1 %tobool12.not, label %for.inc, label %for.end
for.inc: ; preds = %g
store i32 0, ptr %d, align 4
br label %for.end
for.end: ; preds = %for.inc, %g
%and = and i32 %b.1, %0
switch i32 %and, label %sw.epilog25 [
i32 6, label %sw.bb
i32 1, label %sw.bb14
]
sw.bb: ; preds = %for.end
br label %sw.bb14
sw.bb14: ; preds = %sw.bb, %for.end
%e.3 = phi i32 [ 0, %sw.bb ], [ %0, %for.end ]
store i32 0, ptr @a, align 4
br label %sw.epilog25
for.cond15: ; preds = %for.inc34, %if.end20
%b.2 = phi i32 [ 0, %if.end20 ], [ %b.0, %for.inc34 ]
br i1 %tobool12.not, label %if.end20, label %d1
if.end20: ; preds = %for.cond15
store i32 0, ptr @a, align 4
br label %for.cond15
sw.epilog25: ; preds = %sw.bb14, %for.end
%e.4 = phi i32 [ %e.22, %for.end ], [ %e.3, %sw.bb14 ]
%xor = xor i32 %e.4, -2124967296
%cmp30 = icmp sgt i32 %xor, 0
br i1 %cmp30, label %a1, label %for.inc34
for.inc34: ; preds = %sw.epilog25
%1 = load i32, ptr @g, align 4
%inc35 = add i32 %1, 1
store i32 %inc35, ptr @g, align 4
%cmp8 = icmp eq i32 %inc35, 0
br i1 %cmp8, label %for.cond15, label %for.inc37
for.inc37: ; preds = %for.inc34
%inc38 = add i32 %c.0, 1
br label %for.cond4
for.inc40: ; preds = %for.cond4
%inc41 = add i32 %h.0, 1
br label %for.cond1
for.end42: ; preds = %for.cond1
ret void
}
define i32 @main() {
entry:
ret i32 0
}
```
### C reproducer
small.c
```c
unsigned g;
int a, d;
short i() { return d; }
void j() {
char b = 10;
int f = 0;
for (; f < 1; f = 1)
a:
if (i()) {
int e = 2180000000;
d:
for (int h = 0; h < 8; h++)
for (int c = 0; c < 7; c++) {
goto g;
for (; g <= 0; g++) {
switch (a) {
for (; 0; a--)
g:
if (d)
break;
switch (b & a) {
case 6:
e = a;
case 1:
a = 0;
}
break;
default:
e = 0;
for (; a; a--) {
if (d)
break;
b++;
}
goto d;
b:;
}
int a = e ^ 2170000000;
for (; 0 < a;)
goto a;
}
}
for (int a; a; a++)
for (; b;)
goto b;
}
}
static int k() {
for (; a != -20; a--)
j();
}
int main() { k(); }
```
Reproduce with PGO:
```
$ clang-trunk -O3 -fprofile-instr-generate small.c
$ LLVM_PROFILE_FILE="test.profraw" ./a.out
$ llvm-profdata merge -o test.profdata test.profraw
$ clang-trunk -O3 -fprofile-instr-use=test.profdata small.c # crash
```
label: generated by fuzzer
Contributor guide
Research direction
Start with small.ll and reproduce the failure using `opt -O3 small.ll -o /dev/null`; the stack points to `verifyVPlanIsValid`, `LoopVectorizationPlanner::executePlan`, and the `loop-vectorize` pass, with the assertion in `llvm/include/llvm/Support/GenericDomTree.h`. Compare the LLVM IR and C reproducers while tracing the VPlan and dominator-tree state; done means the reproducer no longer asserts.
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
- Needs clarification
- Newbie friendliness
- 35/100