Skip to content

Compiler crash in Cilk's exception handling logic #483

Description

@kennyzzhang

Describe the bug

The compiler crashes when optimizing (-O1 or higher) the expression cilk_spawn f(arg1, arg2) where both arg1 and arg2 invoke copy constructors that may throw an exception.

Expected behavior

The compiler should not crash.

OpenCilk version

v4.0-rc2
Built from source:

opencilk-project: dev/21.x (https://github.com/OpenCilk/opencilk-project/commit/ea1fea200c4e62bf6e46a4718546650ad844368b)
cheetah: opencilk/v4.0-rc2 (https://github.com/OpenCilk/cheetah/commit/e8a730e7acbd6c9dbce0a28cf2a9f4cc7dc02d19)
productivity-tools: dev (https://github.com/OpenCilk/productivity-tools/commit/3049053b784bc37d2ce9ff4449c7985703957006)

System information

OS: Debian 13
CPU: Intel Core i7-8700K

Steps to reproduce (include relevant output)

Compile the example code with

clang++ example.cpp -fopencilk -O1 -c

This generates the following crash and stackdump:

While deleting: token %                                                                                            
Use still stuck around after Def is destroyed:  invoke void @llvm.taskframe.resume.sl_p0i32s(token <badref>, { ptr, i32 } %lpad.val2)
          to label %unreachable unwind label %lpad3
Uses remain when a value is destroyed!
UNREACHABLE executed at /home/kzzhang/OpenCilk/opencilk-project/llvm/lib/IR/Value.cpp:102!
PLEASE submit a bug report to https://github.com/OpenCilk/opencilk-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:                    
0.      Program arguments: /home/kzzhang/OpenCilk/build/bin/clang-21 -cc1 -triple x86_64-unknown-linux-gnu -O1 -emit-obj -dumpdir a- -disable-free -clear-ast-before-backend -main-file-name example.cpp -mrelocation-model pic -pic-le
vel 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/home/kzzhang/OpenCil
k/opencilk-project-cilkprace/cilktools/cilkprace/race_detection_examples -fcoverage-compilation-dir=/home/kzzhang/OpenCilk/opencilk-project-cilkprace/cilktools/cilkprace/race_detection_examples -resource-dir /home/kzzhang/OpenCilk/
build/lib/clang/21 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-l
inux-gnu/14/../../../../include/c++/14/backward -internal-isystem /home/kzzhang/OpenCilk/build/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gn
u/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fdeprecated-macro -ferror-limit 19 -fmessage-length=231 -fopencilk --opencilk-abi-bitcode=
/home/kzzhang/OpenCilk/build/lib/clang/21/lib/x86_64-unknown-linux-gnu/libopencilk-abi.bc -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fcxx-exceptions -fexceptions -fcolor-diagnostics -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tm
p/example-d7c2dd.o -x c++ example.cpp
1.      <eof> parser at end of file
2.      Optimizer                                                                                                  
3.      Running pass "function<eager-inv>(ee-instrument<>,lower-expect,simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-wit
h-cond-faulting;no-sink-common-insts;speculate-blocks;simplify-cond-branch;no-speculate-unpredictables>,sroa<modify-cfg>,early-cse<>)" on module "example.cpp"                                                     
4.      Running pass "simplifycfg<bonus-inst-threshold=1;no-forward-switch-cond;no-switch-range-to-icmp;no-switch-to-lookup;keep-loops;no-hoist-common-insts;no-hoist-loads-stores-with-cond-faulting;no-sink-common-insts;speculate-bl
ocks;simplify-cond-branch;no-speculate-unpredictables>" on function "_Z3foo6mytype"                                                                                                                                                    
 #0 0x00005652266e2c0b llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/kzzhang/OpenCilk/build/bin/clang-21+0x2d02c0b)                                                                              
 #1 0x00005652266dfa9a SignalHandler(int, siginfo_t*, void*) Signals.cpp:0:0                                                                                                                                                           
 #2 0x00007fb62b55bdf0 (/lib/x86_64-linux-gnu/libc.so.6+0x3fdf0)                                                                                                                                                                       
 #3 0x00007fb62b5b095c (/lib/x86_64-linux-gnu/libc.so.6+0x9495c)                                          
 #4 0x00007fb62b55bcc2 raise (/lib/x86_64-linux-gnu/libc.so.6+0x3fcc2)
 #5 0x00007fb62b5444ac abort (/lib/x86_64-linux-gnu/libc.so.6+0x284ac)
 #6 0x00005652266303ca (/home/kzzhang/OpenCilk/build/bin/clang-21+0x2c503ca)
 #7 0x00005652261b3b69 llvm::Value::~Value() (/home/kzzhang/OpenCilk/build/bin/clang-21+0x27d3b69)
 #8 0x00005652261b3d0a llvm::Value::deleteValue() (/home/kzzhang/OpenCilk/build/bin/clang-21+0x27d3d0a)
 #9 0x00005652260f0a76 llvm::Instruction::eraseFromParent() (/home/kzzhang/OpenCilk/build/bin/clang-21+0x2710a76)
#10 0x00005652268cda4d llvm::simplifyCFG(llvm::BasicBlock*, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&, llvm::ArrayRef<llvm::WeakVH>) (/home/kzzhang/OpenCilk/build/bin/clang-21+0x2eeda4
d)
#11 0x00005652265c1f15 iterativelySimplifyCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DomTreeUpdater*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#12 0x00005652265c42b1 simplifyFunctionCFGImpl(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#13 0x00005652265c53e5 simplifyFunctionCFG(llvm::Function&, llvm::TargetTransformInfo const&, llvm::DominatorTree*, llvm::SimplifyCFGOptions const&) SimplifyCFGPass.cpp:0:0
#14 0x00005652265c5501 llvm::SimplifyCFGPass::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/kzzhang/OpenCilk/build/bin/clang-21+0x2be5501)
#15 0x00005652276e8aad llvm::detail::PassModel<llvm::Function, llvm::SimplifyCFGPass, llvm::AnalysisManager<llvm::Function>>::run(llvm::Function&, llvm::AnalysisManager<llvm::Function>&) (/home/kzzhang/OpenCilk/build/bin/clang-21+0
x3d08aad)
...

Working example code

example.c

class mytype {
  int* beg;

public:
  mytype() {}
  ~mytype() {}
  mytype(const mytype& other) {
    // This allocation may throw
    beg = new int[8];
  }
};

void foo(mytype fooarg1, mytype fooarg2) { }

void bar(mytype bararg) {
  cilk_spawn foo(bararg, bararg);
}

Additional comments

This crash shown in example.c is slightly different than the original one I ran into.
The original crash was specific to compiling with Cilksan.

clang++ example2.cpp -fopencilk -O1 -c -fsanitize=cilk

This generates the following crash and stackdump:

clang++: /home/kzzhang/OpenCilk/opencilk-project/llvm/lib/Transforms/Utils/TapirUtils.cpp:1835: void llvm::fixupTaskFrameExternalUses(Spindle*, const TaskInfo&, const DominatorTree&): Assertion `(nullptr == TFResumeContin) || (TFResumeContin == TFResume->getUnwindDest()) && "Multiple taskframe.resume destinations found"' failed.
PLEASE submit a bug report to https://github.com/OpenCilk/opencilk-project/issues/ and include the crash backtrace, preprocessed source, and associated run script.
Stack dump:
0.      Program arguments: /home/kzzhang/OpenCilk/build/bin/clang++ example2.cpp -fopencilk -O1 -fsanitize=cilk -c
1.      <eof> parser at end of file
2.      Optimizer
3.      Running pass "tapir2target" on module "example2.cpp"
 #0 0x00005594503a5c0b llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/kzzhang/OpenCilk/build/bin/clang+++0x2d02c0b)
 #1 0x00005594503a33c4 llvm::sys::CleanupOnSignal(unsigned long) (/home/kzzhang/OpenCilk/build/bin/clang+++0x2d003c4)
 #2 0x00005594502e8980 CrashRecoverySignalHandler(int) CrashRecoveryContext.cpp:0:0
 #3 0x00007f42b2a1edf0 (/lib/x86_64-linux-gnu/libc.so.6+0x3fdf0)
 #4 0x00007f42b2a7395c (/lib/x86_64-linux-gnu/libc.so.6+0x9495c)
 #5 0x00007f42b2a1ecc2 raise (/lib/x86_64-linux-gnu/libc.so.6+0x3fcc2)
 #6 0x00007f42b2a074ac abort (/lib/x86_64-linux-gnu/libc.so.6+0x284ac)
 #7 0x00007f42b2a07420 __assert_perror_fail (/lib/x86_64-linux-gnu/libc.so.6+0x28420)
 #8 0x000055944e417e88 llvm::fixupTaskFrameExternalUses(llvm::Spindle*, llvm::TaskInfo const&, llvm::DominatorTree const&) (.cold) TapirUtils.cpp:0:0
 #9 0x0000559451503d89 TapirToTargetImpl::processFunction(llvm::Function&, llvm::SmallVectorImpl<llvm::Function*>&) (/home/kzzhang/OpenCilk/build/bin/clang+++0x3e60d89)
#10 0x00005594515053ba TapirToTargetImpl::run() (/home/kzzhang/OpenCilk/build/bin/clang+++0x3e623ba)
#11 0x00005594515056e3 llvm::TapirToTargetPass::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/kzzhang/OpenCilk/build/bin/clang+++0x3e626e3)
#12 0x00005594513aaced llvm::detail::PassModel<llvm::Module, llvm::TapirToTargetPass, llvm::AnalysisManager<llvm::Module>>::run(llvm::Module&, llvm::AnalysisManager<llvm::Module>&) (/home/kzzhang/OpenCilk/build/bin/clang+++0x3d07ced)
...

example2.cpp

#include <vector>

int bar(std::vector<int> bararg);

int foo(std::vector<int> fooarg) {
  bar(fooarg);

  int ret;

  ret = cilk_spawn bar(fooarg);
  bar({1});
  cilk_sync;

  return ret;
}

While I was fiddling with the examples to try make them as minimal as possible, I felt like it only took subtle changes to the code to make the crash appear and disappear. I was having trouble parsing what was happening in the landing pads and couldn't find a pattern to the crash, hence why I'm filing this bug report.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions