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.
Describe the bug
The compiler crashes when optimizing (
-O1or higher) the expressioncilk_spawn f(arg1, arg2)where botharg1andarg2invoke copy constructors that may throw an exception.Expected behavior
The compiler should not crash.
OpenCilk version
v4.0-rc2
Built from source:
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 -cThis generates the following crash and stackdump:
Working example code
example.cAdditional comments
This crash shown in
example.cis 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=cilkThis generates the following crash and stackdump:
example2.cppWhile 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.