llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
29.16k stars 12.03k forks source link

`IndirectBrExpandPass` Crashes due to PHI in `indirectbr` Destination #63042

Open HazyFish opened 1 year ago

HazyFish commented 1 year ago

Description

IndirectBrExpandPass could create invalid IR when the destination contains PHI instruction. This causes error PHINode should have one entry for each predecessor of its parent basic block! during verification.

Should we consider this as a bug for IndirectBrExpandPass, or should we not allow PHI in indirectbr destination?

Minimal Reproduction

https://godbolt.org/z/1s5arzWPG

In this example, a new BB switch_bb is created to replace indirectbr. However, the PHI instruction in bb1 is left unchanged and becomes invalid.

Code

target triple = "wasm32"

@f.targets = constant [2 x ptr] [ptr blockaddress(@f, %bb1), ptr blockaddress(@f, %latch)]

define i8 @f(i32 %i, i32 %j) {
entry:
  %target0.ptr = getelementptr [2 x ptr], ptr @f.targets, i32 0, i32 %i
  %target0 = load ptr, ptr %target0.ptr
  indirectbr ptr %target0, [label %bb1, label %latch]

bb1:                                              ; preds = %latch, %entry
  %0 = phi i8 [ 2, %latch ], [ 1, %entry ]
  ret i8 %0

latch:                                            ; preds = %latch, %entry
  %target1.ptr = getelementptr [2 x ptr], ptr @f.targets, i32 0, i32 %j
  %target1 = load ptr, ptr %target1.ptr
  indirectbr ptr %target1, [label %bb1, label %latch]
}

Stack Trace

*** IR Dump After Expand indirectbr instructions (indirectbr-expand) ***
define i8 @f(i32 %i, i32 %j) {
entry:
  %target0.ptr = getelementptr [2 x ptr], ptr @f.targets, i32 0, i32 %i
  %target0 = load ptr, ptr %target0.ptr, align 8
  %target0.switch_cast = ptrtoint ptr %target0 to i64
  br label %switch_bb

bb1:                                              ; preds = %switch_bb
  %0 = phi i8 [ 2, %latch ], [ 1, %entry ]
  ret i8 %0

latch:                                            ; preds = %switch_bb
  %target1.ptr = getelementptr [2 x ptr], ptr @f.targets, i32 0, i32 %j
  %target1 = load ptr, ptr %target1.ptr, align 8
  %target1.switch_cast = ptrtoint ptr %target1 to i64
  br label %switch_bb

switch_bb:                                        ; preds = %latch, %entry
  %switch_value_phi = phi i64 [ %target0.switch_cast, %entry ], [ %target1.switch_cast, %latch ]
  switch i64 %switch_value_phi, label %bb1 [
    i64 2, label %latch
  ]
}
PHINode should have one entry for each predecessor of its parent basic block!
  %0 = phi i8 [ 2, %latch ], [ 1, %entry ]
in function f
LLVM ERROR: Broken function found, compilation aborted!
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0.  Program arguments: /opt/compiler-explorer/clang-trunk/bin/opt -o /app/output.s -S --indirectbr-expand --print-after-all <source>
1.  Running pass 'Function Pass Manager' on module '<source>'.
2.  Running pass 'Module Verifier' on function '@f'
 #0 0x0000556ee5d8f48f llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/opt/compiler-explorer/clang-trunk/bin/opt+0x30a248f)
 #1 0x0000556ee5d8cf04 SignalHandler(int) Signals.cpp:0:0
 #2 0x00007f9d7e969420 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x14420)
 #3 0x00007f9d7e43600b raise (/lib/x86_64-linux-gnu/libc.so.6+0x4300b)
 #4 0x00007f9d7e415859 abort (/lib/x86_64-linux-gnu/libc.so.6+0x22859)
 #5 0x0000556ee338ffd4 llvm::UniqueStringSaver::save(llvm::StringRef) (.cold) StringSaver.cpp:0:0
 #6 0x0000556ee5ce40be (/opt/compiler-explorer/clang-trunk/bin/opt+0x2ff70be)
 #7 0x0000556ee572fe96 (anonymous namespace)::VerifierLegacyPass::runOnFunction(llvm::Function&) Verifier.cpp:0:0
 #8 0x0000556ee56816ca llvm::FPPassManager::runOnFunction(llvm::Function&) (/opt/compiler-explorer/clang-trunk/bin/opt+0x29946ca)
 #9 0x0000556ee5681859 llvm::FPPassManager::runOnModule(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/opt+0x2994859)
#10 0x0000556ee5682440 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/opt/compiler-explorer/clang-trunk/bin/opt+0x2995440)
#11 0x0000556ee33a923a main (/opt/compiler-explorer/clang-trunk/bin/opt+0x6bc23a)
#12 0x00007f9d7e417083 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24083)
#13 0x0000556ee34944ae _start (/opt/compiler-explorer/clang-trunk/bin/opt+0x7a74ae)
Compiler returned: 139
HazyFish commented 1 year ago

@DataCorrupted

llvmbot commented 1 year ago

@llvm/issue-subscribers-bug