diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -5230,8 +5230,13 @@ case Intrinsic::experimental_gc_result: { Check(Call.getParent()->getParent()->hasGC(), "Enclosing function does not use GC.", Call); + + auto *Statepoint = Call.getArgOperand(0); + if (isa(Statepoint)) + break; + // Are we tied to a statepoint properly? - const auto *StatepointCall = dyn_cast(Call.getArgOperand(0)); + const auto *StatepointCall = dyn_cast(Statepoint); const Function *StatepointFn = StatepointCall ? StatepointCall->getCalledFunction() : nullptr; Check(StatepointFn && StatepointFn->isDeclaration() && diff --git a/llvm/test/Verifier/gc_result_token.ll b/llvm/test/Verifier/gc_result_token.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Verifier/gc_result_token.ll @@ -0,0 +1,21 @@ +; RUN: opt -S -passes=verify < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define void @foo() gc "statepoint_example" personality ptr @P { +; CHECK-NOT: gc.result operand #1 must be from a statepoint +entry: + br label %label_1 +label_1: + ; CHECK: ret void + ret void + +label_2: + ; CHECK: token poison + %call = call noundef i32 @llvm.experimental.gc.result.i32(token poison) + unreachable +} + +declare i32 @llvm.experimental.gc.result.i32(token) + +declare ptr @P()