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

Reply via email to