diff --git a/llvm/include/llvm/IR/IntrinsicInst.h b/llvm/include/llvm/IR/IntrinsicInst.h --- a/llvm/include/llvm/IR/IntrinsicInst.h +++ b/llvm/include/llvm/IR/IntrinsicInst.h @@ -1381,7 +1381,7 @@ } /// The statepoint with which this gc.relocate is associated. - const GCStatepointInst *getStatepoint() const; + const Value *getStatepoint() const; }; /// Represents calls to the gc.relocate intrinsic. diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -169,8 +169,14 @@ // Spill location is known for gc relocates if (const auto *Relocate = dyn_cast(Val)) { - const auto &RelocationMap = - Builder.FuncInfo.StatepointRelocationMaps[Relocate->getStatepoint()]; + const Value *Statepoint = Relocate->getStatepoint(); + assert((isa(Statepoint) || isa(Statepoint)) && + "GetStatepoint must return one of two types"); + if (isa(Statepoint)) + return None; + + const auto &RelocationMap = Builder.FuncInfo.StatepointRelocationMaps + [cast(Statepoint)]; auto It = RelocationMap.find(Relocate); if (It == RelocationMap.end()) @@ -1196,9 +1202,13 @@ void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) { // The result value of the gc_result is simply the result of the actual // call. We've already emitted this, so just grab the value. - const GCStatepointInst *SI = CI.getStatepoint(); + const Value *SI = CI.getStatepoint(); + assert((isa(SI) || isa(SI)) && + "GetStatepoint must return one of two types"); + if (isa(SI)) + return; - if (SI->getParent() == CI.getParent()) { + if (cast(SI)->getParent() == CI.getParent()) { setValue(&CI, getValue(SI)); return; } @@ -1221,7 +1231,13 @@ // We skip this check for relocates not in the same basic block as their // statepoint. It would be too expensive to preserve validation info through // different basic blocks. - if (Relocate.getStatepoint()->getParent() == Relocate.getParent()) + const Value *Statepoint = Relocate.getStatepoint(); + assert((isa(Statepoint) || isa(Statepoint)) && + "GetStatepoint must return one of two types"); + if (isa(Statepoint)) + return; + + if (cast(Statepoint)->getParent() == Relocate.getParent()) StatepointLowering.relocCallVisited(Relocate); auto *Ty = Relocate.getType()->getScalarType(); @@ -1231,14 +1247,15 @@ const Value *DerivedPtr = Relocate.getDerivedPtr(); auto &RelocationMap = - FuncInfo.StatepointRelocationMaps[Relocate.getStatepoint()]; + FuncInfo.StatepointRelocationMaps[cast(Statepoint)]; auto SlotIt = RelocationMap.find(&Relocate); assert(SlotIt != RelocationMap.end() && "Relocating not lowered gc value"); const RecordType &Record = SlotIt->second; // If relocation was done via virtual register.. if (Record.type == RecordType::SDValueNode) { - assert(Relocate.getStatepoint()->getParent() == Relocate.getParent() && + assert(cast(Statepoint)->getParent() == + Relocate.getParent() && "Nonlocal gc.relocate mapped via SDValue"); SDValue SDV = StatepointLowering.getLocation(getValue(DerivedPtr)); assert(SDV.getNode() && "empty SDValue"); diff --git a/llvm/lib/IR/IntrinsicInst.cpp b/llvm/lib/IR/IntrinsicInst.cpp --- a/llvm/lib/IR/IntrinsicInst.cpp +++ b/llvm/lib/IR/IntrinsicInst.cpp @@ -694,8 +694,10 @@ return OverflowingBinaryOperator::NoUnsignedWrap; } -const GCStatepointInst *GCProjectionInst::getStatepoint() const { +const Value *GCProjectionInst::getStatepoint() const { const Value *Token = getArgOperand(0); + if (isa(Token)) + return Token; // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. @@ -714,13 +716,23 @@ } Value *GCRelocateInst::getBasePtr() const { - if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live)) + auto Statepoint = getStatepoint(); + if (isa(Statepoint)) + return UndefValue::get(Statepoint->getType()); + + auto *GCInst = cast(Statepoint); + if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) return *(Opt->Inputs.begin() + getBasePtrIndex()); - return *(getStatepoint()->arg_begin() + getBasePtrIndex()); + return *(GCInst->arg_begin() + getBasePtrIndex()); } Value *GCRelocateInst::getDerivedPtr() const { - if (auto Opt = getStatepoint()->getOperandBundle(LLVMContext::OB_gc_live)) + auto *Statepoint = getStatepoint(); + if (isa(Statepoint)) + return UndefValue::get(Statepoint->getType()); + + auto *GCInst = cast(Statepoint); + if (auto Opt = GCInst->getOperandBundle(LLVMContext::OB_gc_live)) return *(Opt->Inputs.begin() + getDerivedPtrIndex()); - return *(getStatepoint()->arg_begin() + getDerivedPtrIndex()); + return *(GCInst->arg_begin() + getDerivedPtrIndex()); } 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 @@ -5156,14 +5156,13 @@ // In all other cases relocate should be tied to the statepoint directly. // This covers relocates on a normal return path of invoke statepoint and // relocates of a call statepoint. - auto Token = Call.getArgOperand(0); - Check(isa(Token), + auto *Token = Call.getArgOperand(0); + Check(isa(Token) || isa(Token), "gc relocate is incorrectly tied to the statepoint", Call, Token); } // Verify rest of the relocate arguments. - const CallBase &StatepointCall = - *cast(Call).getStatepoint(); + const Value &StatepointCall = *cast(Call).getStatepoint(); // Both the base and derived must be piped through the safepoint. Value *Base = Call.getArgOperand(1); @@ -5178,7 +5177,10 @@ const uint64_t DerivedIndex = cast(Derived)->getZExtValue(); // Check the bounds - if (auto Opt = StatepointCall.getOperandBundle(LLVMContext::OB_gc_live)) { + if (isa(StatepointCall)) + break; + if (auto Opt = cast(StatepointCall) + .getOperandBundle(LLVMContext::OB_gc_live)) { Check(BaseIndex < Opt->Inputs.size(), "gc.relocate: statepoint base index out of bounds", Call); Check(DerivedIndex < Opt->Inputs.size(), diff --git a/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll b/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/gc.relocate-verify.ll @@ -0,0 +1,17 @@ +; RUN: opt -S -passes=verify < %s | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" + +define i32 @check_verify_undef_token() gc "statepoint-example" { + +entry: + ; CHECK: ret i32 0 + ret i32 0 + +unreach: + ; CHECK: token undef + %token_call = call i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token undef, i32 0, i32 0) + ret i32 1 +} + +declare i32 addrspace(1)* @llvm.experimental.gc.relocate.p1i32(token, i32, i32)