diff --git a/llvm/include/llvm/IR/Statepoint.h b/llvm/include/llvm/IR/Statepoint.h index 5ca6939ce773..81679e2612da 100644 --- a/llvm/include/llvm/IR/Statepoint.h +++ b/llvm/include/llvm/IR/Statepoint.h @@ -134,6 +134,53 @@ public: cast(getActualCalledOperand()->getType())->getElementType(); return cast(CalleeTy)->getReturnType(); } + + + /// Return the number of arguments to the underlying call. + size_t actual_arg_size() const { return getNumCallArgs(); } + /// Return an iterator to the begining of the arguments to the underlying call + const_op_iterator actual_arg_begin() const { + assert(CallArgsBeginPos <= (int)arg_size()); + return arg_begin() + CallArgsBeginPos; + } + /// Return an end iterator of the arguments to the underlying call + const_op_iterator actual_arg_end() const { + auto I = actual_arg_begin() + actual_arg_size(); + assert((arg_end() - I) >= 0); + return I; + } + /// range adapter for actual call arguments + iterator_range actual_args() const { + return make_range(actual_arg_begin(), actual_arg_end()); + } + + /// Returns an iterator to the begining of the argument range describing gc + /// values for the statepoint. + const_op_iterator gc_args_begin() const { + // The current format has two length prefix bundles between call args and + // start of gc args. This will be removed in the near future. + const Value *NumGCTransitionArgs = *actual_arg_end(); + uint64_t NumTrans = cast(NumGCTransitionArgs)->getZExtValue(); + const_op_iterator trans_end = actual_arg_end() + 1 + NumTrans; + const Value *NumDeoptArgs = *trans_end; + uint64_t NumDeopt = cast(NumDeoptArgs)->getZExtValue(); + auto I = trans_end + 1 + NumDeopt; + assert((arg_end() - I) >= 0); + return I; + } + + /// Return an end iterator for the gc argument range + const_op_iterator gc_args_end() const { return arg_end(); } + + /// Return the operand index at which the gc args begin + unsigned gcArgsStartIdx() const { + return gc_args_begin() - op_begin(); + } + + /// range adapter for gc arguments + iterator_range gc_args() const { + return make_range(gc_args_begin(), gc_args_end()); + } }; /// A wrapper around a GC intrinsic call, this provides most of the actual @@ -201,16 +248,11 @@ public: return getCall()->doesNotThrow() || (F ? F->doesNotThrow() : false); } - - size_t arg_size() const { return getNumCallArgs(); } - arg_iterator arg_begin() const { - assert(CallArgsBeginPos <= (int)getCall()->arg_size()); - return getCall()->arg_begin() + CallArgsBeginPos; - } - arg_iterator arg_end() const { - auto I = arg_begin() + arg_size(); - assert((getCall()->arg_end() - I) >= 0); - return I; + size_t arg_size() const { return getCall()->actual_arg_size(); } + arg_iterator arg_begin() const { return getCall()->actual_arg_begin(); } + arg_iterator arg_end() const { return getCall()->actual_arg_end(); } + iterator_range call_args() const { + return getCall()->actual_args(); } ValueTy *getArgument(unsigned Index) { @@ -218,11 +260,6 @@ public: return *(arg_begin() + Index); } - /// range adapter for call arguments - iterator_range call_args() const { - return make_range(arg_begin(), arg_end()); - } - /// Return true if the call or the callee has the given attribute. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const { Function *F = getCalledFunction(); @@ -274,16 +311,15 @@ public: return make_range(deopt_begin(), deopt_end()); } - arg_iterator gc_args_begin() const { return deopt_end(); } - arg_iterator gc_args_end() const { return getCall()->arg_end(); } - - unsigned gcArgsStartIdx() const { - return gc_args_begin() - getCall()->op_begin(); + arg_iterator gc_args_begin() const { + auto I = getCall()->gc_args_begin(); + assert(I == deopt_end()); + return I; } - - /// range adapter for gc arguments + arg_iterator gc_args_end() const { return getCall()->gc_args_end(); } + unsigned gcArgsStartIdx() const { return getCall()->gcArgsStartIdx(); } iterator_range gc_args() const { - return make_range(gc_args_begin(), gc_args_end()); + return getCall()->gc_args(); } /// Get list of all gc reloactes linked to this statepoint diff --git a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp index fd961d1908a4..4f51efd09472 100644 --- a/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -864,7 +864,7 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I, } } - SI.GCArgs = ArrayRef(ISP.gc_args_begin(), ISP.gc_args_end()); + SI.GCArgs = ArrayRef(I.gc_args_begin(), I.gc_args_end()); SI.StatepointInstr = &I; SI.ID = I.getID(); diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp index ec14bca90801..974213232050 100644 --- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -271,7 +271,7 @@ struct PartiallyConstructedSafepointRecord { /// The *new* gc.statepoint instruction itself. This produces the token /// that normal path gc.relocates and the gc.result are tied to. - Instruction *StatepointToken; + GCStatepointInst *StatepointToken; /// Instruction to which exceptional gc relocates are attached /// Makes it easier to iterate through them during relocationViaAlloca. @@ -1546,7 +1546,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ } // Create the statepoint given all the arguments - Instruction *Token = nullptr; + GCStatepointInst *Token = nullptr; if (auto *CI = dyn_cast(Call)) { CallInst *SPCall = Builder.CreateGCStatepointCall( StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs, @@ -1562,7 +1562,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ SPCall->setAttributes( legalizeCallAttributes(CI->getContext(), CI->getAttributes())); - Token = SPCall; + Token = cast(SPCall); // Put the following gc_result and gc_relocate calls immediately after the // the old call (which we're about to delete) @@ -1589,7 +1589,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ SPInvoke->setAttributes( legalizeCallAttributes(II->getContext(), II->getAttributes())); - Token = SPInvoke; + Token = cast(SPInvoke); // Generate gc relocates in exceptional path BasicBlock *UnwindBlock = II->getUnwindDest(); @@ -1604,7 +1604,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst(); Result.UnwindToken = ExceptionalToken; - const unsigned LiveStartIdx = Statepoint(Token).gcArgsStartIdx(); + const unsigned LiveStartIdx = Token->gcArgsStartIdx(); CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs, ExceptionalToken, Builder); @@ -1652,7 +1652,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */ Result.StatepointToken = Token; // Second, create a gc.relocate for every live variable - const unsigned LiveStartIdx = Statepoint(Token).gcArgsStartIdx(); + const unsigned LiveStartIdx = Token->gcArgsStartIdx(); CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs, Token, Builder); } @@ -2409,9 +2409,8 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, // That Value* no longer exists and we need to use the new gc_result. // Thankfully, the live set is embedded in the statepoint (and updated), so // we just grab that. - Statepoint Statepoint(Info.StatepointToken); - Live.insert(Live.end(), Statepoint.gc_args_begin(), - Statepoint.gc_args_end()); + Live.insert(Live.end(), Info.StatepointToken->gc_args_begin(), + Info.StatepointToken->gc_args_end()); #ifndef NDEBUG // Do some basic sanity checks on our liveness results before performing // relocation. Relocation can and will turn mistakes in liveness results @@ -2419,7 +2418,7 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, // TODO: It would be nice to test consistency as well assert(DT.isReachableFromEntry(Info.StatepointToken->getParent()) && "statepoint must be reachable or liveness is meaningless"); - for (Value *V : Statepoint.gc_args()) { + for (Value *V : Info.StatepointToken->gc_args()) { if (!isa(V)) // Non-instruction values trivial dominate all possible uses continue;