diff options
-rw-r--r-- | llvm/include/llvm/IR/Statepoint.h | 41 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp | 9 | ||||
-rw-r--r-- | llvm/lib/IR/Statepoint.cpp | 8 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 4 |
6 files changed, 41 insertions, 25 deletions
diff --git a/llvm/include/llvm/IR/Statepoint.h b/llvm/include/llvm/IR/Statepoint.h index 416301572ae..8ae08f1e1ce 100644 --- a/llvm/include/llvm/IR/Statepoint.h +++ b/llvm/include/llvm/IR/Statepoint.h @@ -39,6 +39,7 @@ enum class StatepointFlags { }; class GCRelocateInst; +class GCResultInst; class ImmutableStatepoint; bool isStatepoint(ImmutableCallSite CS); @@ -46,8 +47,6 @@ bool isStatepoint(const Value *V); bool isStatepoint(const Value &V); bool isGCRelocate(ImmutableCallSite CS); - -bool isGCResult(const Value *V); bool isGCResult(ImmutableCallSite CS); /// Analogous to CallSiteBase, this provides most of the actual @@ -253,11 +252,10 @@ public: /// Get the experimental_gc_result call tied to this statepoint. Can be /// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to /// be a CallInst if non-null. - InstructionTy *getGCResult() const { + const GCResultInst *getGCResult() const { for (auto *U : getInstruction()->users()) - if (isGCResult(U)) - return cast<CallInst>(U); - + if (auto *GRI = dyn_cast<GCResultInst>(U)) + return GRI; return nullptr; } @@ -306,11 +304,13 @@ public: explicit Statepoint(CallSite CS) : Base(CS) {} }; -/// This represents the gc.relocate intrinsic. -class GCRelocateInst : public IntrinsicInst { +/// Common base class for representing values projected from a statepoint. +/// Currently, the only projections available are gc.result and gc.relocate. +class GCProjectionInst : public IntrinsicInst { public: static inline bool classof(const IntrinsicInst *I) { - return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; + return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate || + I->getIntrinsicID() == Intrinsic::experimental_gc_result; } static inline bool classof(const Value *V) { return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); @@ -331,6 +331,7 @@ public: // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. if (!isa<LandingPadInst>(Token)) { + assert(isStatepoint(Token)); return cast<Instruction>(Token); } @@ -345,6 +346,17 @@ public: return InvokeBB->getTerminator(); } +}; + +/// This represents the gc.relocate intrinsic. +class GCRelocateInst : public GCProjectionInst { +public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } /// The index into the associate statepoint's argument list /// which contains the base pointer of the pointer whose @@ -370,6 +382,17 @@ public: } }; +/// This represents the gc.result intrinsic. +class GCResultInst : public GCProjectionInst { +public: + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::experimental_gc_result; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } +}; + template <typename FunTy, typename InstructionTy, typename ValueTy, typename CallSiteTy> std::vector<const GCRelocateInst *> diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 27d24222aff..6f4cd4280f4 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5539,7 +5539,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) { return nullptr; } case Intrinsic::experimental_gc_result: { - visitGCResult(I); + visitGCResult(cast<GCResultInst>(I)); return nullptr; } case Intrinsic::experimental_gc_relocate: { diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h index 47d8870cd95..591361e040c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -904,7 +904,7 @@ private: // These two are implemented in StatepointLowering.cpp void visitGCRelocate(const GCRelocateInst &I); - void visitGCResult(const CallInst &I); + void visitGCResult(const GCResultInst &I); void visitUserOp1(const Instruction &I) { llvm_unreachable("UserOp1 should not exist at instruction selection time!"); diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index f489e3b1c8c..9b745516eab 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -788,7 +788,7 @@ SelectionDAGBuilder::LowerStatepoint(ImmutableStatepoint ISP, SDValue ReturnValue = LowerAsSTATEPOINT(SI); // Export the result value if needed - const Instruction *GCResult = ISP.getGCResult(); + const GCResultInst *GCResult = ISP.getGCResult(); Type *RetTy = ISP.getActualReturnType(); if (!RetTy->isVoidTy() && GCResult) { if (GCResult->getParent() != ISP.getCallSite().getParent()) { @@ -862,17 +862,16 @@ void SelectionDAGBuilder::LowerCallSiteWithDeoptBundle( /* ForceVoidReturnTy = */ false); } -void SelectionDAGBuilder::visitGCResult(const CallInst &CI) { +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. - Instruction *I = cast<Instruction>(CI.getArgOperand(0)); - assert(isStatepoint(I) && "first argument must be a statepoint token"); + const Instruction *I = CI.getStatepoint(); if (I->getParent() != CI.getParent()) { // Statepoint is in different basic block so we should have stored call // result in a virtual register. // We can not use default getValue() functionality to copy value from this - // register because statepoint and actuall call return types can be + // register because statepoint and actual call return types can be // different, and getValue() will use CopyFromReg of the wrong type, // which is always i32 in our case. PointerType *CalleeType = cast<PointerType>( diff --git a/llvm/lib/IR/Statepoint.cpp b/llvm/lib/IR/Statepoint.cpp index 13e8c6312a6..63be1e780d8 100644 --- a/llvm/lib/IR/Statepoint.cpp +++ b/llvm/lib/IR/Statepoint.cpp @@ -45,13 +45,7 @@ bool llvm::isGCRelocate(ImmutableCallSite CS) { } bool llvm::isGCResult(ImmutableCallSite CS) { - if (auto *F = getCalledFunction(CS)) - return F->getIntrinsicID() == Intrinsic::experimental_gc_result; - return false; -} - -bool llvm::isGCResult(const Value *V) { - return isGCResult(ImmutableCallSite(V)); + return CS.getInstruction() && isa<GCResultInst>(CS.getInstruction()); } bool llvm::isStatepointDirectiveAttr(Attribute Attr) { diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 686c1ccfca5..8f055886efe 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -1774,11 +1774,11 @@ void Verifier::verifyStatepoint(ImmutableCallSite CS) { const CallInst *Call = dyn_cast<const CallInst>(U); Assert(Call, "illegal use of statepoint token", &CI, U); if (!Call) continue; - Assert(isa<GCRelocateInst>(Call) || isGCResult(Call), + Assert(isa<GCRelocateInst>(Call) || isa<GCResultInst>(Call), "gc.result or gc.relocate are the only value uses" "of a gc.statepoint", &CI, U); - if (isGCResult(Call)) { + if (isa<GCResultInst>(Call)) { Assert(Call->getArgOperand(0) == &CI, "gc.result connected to wrong gc.statepoint", &CI, Call); } else if (isa<GCRelocateInst>(Call)) { |