From a0d2fd4a1f785230120df2bb5f74917dc0c357e5 Mon Sep 17 00:00:00 2001 From: Philip Reames Date: Thu, 28 May 2020 13:34:12 -0700 Subject: [PATCH] [Statepoint] Sink actual_args and gc_args to GCStatepointInst [NFC] These are the two operand sets which are expected to survive more than another week or so. Instead of bothering to update the deopt and gc-transition operands, we'll just wait until those are removed and delete the code. For those following along, this is likely to be the last (major) change in this sequence for about a week. I want to wait until all of this has been merged downstream to ensure I haven't introduced any bugs (and migrate some downstream code to the new interfaces). Once that's done, we should be able to delete Statepoint/ImmutableStatepoint without too much work. --- llvm/include/llvm/IR/Statepoint.h | 82 ++++++++++++++++------ .../CodeGen/SelectionDAG/StatepointLowering.cpp | 2 +- .../Transforms/Scalar/RewriteStatepointsForGC.cpp | 19 +++-- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/llvm/include/llvm/IR/Statepoint.h b/llvm/include/llvm/IR/Statepoint.h index 5ca6939..81679e2 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 fd961d1..4f51efd 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 ec14bca9..9742132 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; -- 2.7.4