| Issue |
61599
|
| Summary |
Printing llvm::module instance crashes when removing `llvm.stacksave` and `llvm.stackrestore` intrinsics
|
| Labels |
|
| Assignees |
|
| Reporter |
yoonminnam
|
I found that the llvm crashes when trying to print llvm module like:
```
std::stringstream ss;
llvm::raw_os_ostream os(ss);
llvm_module->print(os, nullptr); <---- crash
os.flush();
```
The crash only happens when adding `llvm::createJumpThreadingPass()` as one of the optimization steps for the IR.
When investigating the generated IR, I found that it has a phi node having two operands holding values generated from `llvm.stacksave()` intrinsic such as:
```
; Function Attrs: uwtable
define void @... local_unnamed_addr #13 {
.entry:
...
.BODY: ; preds = ...
...
%savedstack = call i8* @llvm.stacksave()
...
br i1 %13, label %LABEL1.i.i, label %LABEL2.i
EXIT: ; preds = %LABEL1.i, %LABEL2.i.i
%savedstack.i2 = phi i8* [ %savedstack.i1, %LABEL1.i.i ], [ %savedstack.i, %LABEL2.i ] <----
call void @llvm.stackrestore(i8* %savedstack.i2)
...
```
If I do not add the optimization pass, the generated IR does not have such a phi node.
The problem is this IR is used to generate a CUDA PTX to process the logic on GPU.
But as far as I know, NVIDIA PTX does not know about such intrinsic provided by llvm, I remove them before calling PTX compilation such as:
```
void cleanup_llvm_ir(...) {
// optimizations might add attributes to the function
// and NVPTX doesn't understand all of them; play it
// safe and clear all attributes
...
std::vector<llvm::Instruction*> stackrestore_intrinsics;
std::vector<llvm::Instruction*> stacksave_intrinsics;
std::vector<llvm::Instruction*> lifetime;
for (auto& BB : *query_func) {
for (llvm::Instruction& I : BB) {
if (const llvm::IntrinsicInst* II = llvm::dyn_cast<llvm::IntrinsicInst>(&I)) {
std::cout << II->getName().str() << std::endl;
if (II->getIntrinsicID() == llvm::Intrinsic::stacksave) {
stacksave_intrinsics.push_back(&I);
} else if (II->getIntrinsicID() == llvm::Intrinsic::stackrestore) {
stackrestore_intrinsics.push_back(&I);
} else if (II->getIntrinsicID() == llvm::Intrinsic::lifetime_start ||
II->getIntrinsicID() == llvm::Intrinsic::lifetime_end) {
lifetime.push_back(&I);
}
}
}
}
// stacksave and stackrestore intrinsics appear together, and
// stackrestore uses stacksaved result as its argument
// so it should be removed first.
for (auto& II : stackrestore_intrinsics) {
std::cout << II->getName().str() << std::endl;
II->eraseFromParent();
}
for (auto& II : stacksave_intrinsics) {
std::cout << II->getName().str() << std::endl;
II->eraseFromParent();
}
```
And after removing them, I got the crash.
Overall,
1) I got a crash when trying to llvm module
2) it looks like a specific llvm IR optimization pass can push `stackrestore` and `stacksave` intrinsic multiple times
3) in the IR, I found a phi node having two operands from `llvm::stacksave` intrinsic
4) after removing any `stackrestore` and `stacksave` intrinsic, the crash happens when accessing llvm module.
I hope this provides enough information for reproducing the issue.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs