forked from OSchip/llvm-project
[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.
This commit is contained in:
parent
4d6cda9bda
commit
a0d2fd4a1f
|
@ -134,6 +134,53 @@ public:
|
||||||
cast<PointerType>(getActualCalledOperand()->getType())->getElementType();
|
cast<PointerType>(getActualCalledOperand()->getType())->getElementType();
|
||||||
return cast<FunctionType>(CalleeTy)->getReturnType();
|
return cast<FunctionType>(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<const_op_iterator> 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<ConstantInt>(NumGCTransitionArgs)->getZExtValue();
|
||||||
|
const_op_iterator trans_end = actual_arg_end() + 1 + NumTrans;
|
||||||
|
const Value *NumDeoptArgs = *trans_end;
|
||||||
|
uint64_t NumDeopt = cast<ConstantInt>(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<const_op_iterator> 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
|
/// 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);
|
return getCall()->doesNotThrow() || (F ? F->doesNotThrow() : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t arg_size() const { return getCall()->actual_arg_size(); }
|
||||||
size_t arg_size() const { return getNumCallArgs(); }
|
arg_iterator arg_begin() const { return getCall()->actual_arg_begin(); }
|
||||||
arg_iterator arg_begin() const {
|
arg_iterator arg_end() const { return getCall()->actual_arg_end(); }
|
||||||
assert(CallArgsBeginPos <= (int)getCall()->arg_size());
|
iterator_range<arg_iterator> call_args() const {
|
||||||
return getCall()->arg_begin() + CallArgsBeginPos;
|
return getCall()->actual_args();
|
||||||
}
|
|
||||||
arg_iterator arg_end() const {
|
|
||||||
auto I = arg_begin() + arg_size();
|
|
||||||
assert((getCall()->arg_end() - I) >= 0);
|
|
||||||
return I;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueTy *getArgument(unsigned Index) {
|
ValueTy *getArgument(unsigned Index) {
|
||||||
|
@ -218,11 +260,6 @@ public:
|
||||||
return *(arg_begin() + Index);
|
return *(arg_begin() + Index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// range adapter for call arguments
|
|
||||||
iterator_range<arg_iterator> call_args() const {
|
|
||||||
return make_range(arg_begin(), arg_end());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return true if the call or the callee has the given attribute.
|
/// Return true if the call or the callee has the given attribute.
|
||||||
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
|
bool paramHasAttr(unsigned i, Attribute::AttrKind A) const {
|
||||||
Function *F = getCalledFunction();
|
Function *F = getCalledFunction();
|
||||||
|
@ -274,16 +311,15 @@ public:
|
||||||
return make_range(deopt_begin(), deopt_end());
|
return make_range(deopt_begin(), deopt_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
arg_iterator gc_args_begin() const { return deopt_end(); }
|
arg_iterator gc_args_begin() const {
|
||||||
arg_iterator gc_args_end() const { return getCall()->arg_end(); }
|
auto I = getCall()->gc_args_begin();
|
||||||
|
assert(I == deopt_end());
|
||||||
unsigned gcArgsStartIdx() const {
|
return I;
|
||||||
return gc_args_begin() - getCall()->op_begin();
|
|
||||||
}
|
}
|
||||||
|
arg_iterator gc_args_end() const { return getCall()->gc_args_end(); }
|
||||||
/// range adapter for gc arguments
|
unsigned gcArgsStartIdx() const { return getCall()->gcArgsStartIdx(); }
|
||||||
iterator_range<arg_iterator> gc_args() const {
|
iterator_range<arg_iterator> 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
|
/// Get list of all gc reloactes linked to this statepoint
|
||||||
|
|
|
@ -864,7 +864,7 @@ SelectionDAGBuilder::LowerStatepoint(const GCStatepointInst &I,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SI.GCArgs = ArrayRef<const Use>(ISP.gc_args_begin(), ISP.gc_args_end());
|
SI.GCArgs = ArrayRef<const Use>(I.gc_args_begin(), I.gc_args_end());
|
||||||
SI.StatepointInstr = &I;
|
SI.StatepointInstr = &I;
|
||||||
SI.ID = I.getID();
|
SI.ID = I.getID();
|
||||||
|
|
||||||
|
|
|
@ -271,7 +271,7 @@ struct PartiallyConstructedSafepointRecord {
|
||||||
|
|
||||||
/// The *new* gc.statepoint instruction itself. This produces the token
|
/// The *new* gc.statepoint instruction itself. This produces the token
|
||||||
/// that normal path gc.relocates and the gc.result are tied to.
|
/// that normal path gc.relocates and the gc.result are tied to.
|
||||||
Instruction *StatepointToken;
|
GCStatepointInst *StatepointToken;
|
||||||
|
|
||||||
/// Instruction to which exceptional gc relocates are attached
|
/// Instruction to which exceptional gc relocates are attached
|
||||||
/// Makes it easier to iterate through them during relocationViaAlloca.
|
/// 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
|
// Create the statepoint given all the arguments
|
||||||
Instruction *Token = nullptr;
|
GCStatepointInst *Token = nullptr;
|
||||||
if (auto *CI = dyn_cast<CallInst>(Call)) {
|
if (auto *CI = dyn_cast<CallInst>(Call)) {
|
||||||
CallInst *SPCall = Builder.CreateGCStatepointCall(
|
CallInst *SPCall = Builder.CreateGCStatepointCall(
|
||||||
StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs,
|
StatepointID, NumPatchBytes, CallTarget, Flags, CallArgs,
|
||||||
|
@ -1562,7 +1562,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */
|
||||||
SPCall->setAttributes(
|
SPCall->setAttributes(
|
||||||
legalizeCallAttributes(CI->getContext(), CI->getAttributes()));
|
legalizeCallAttributes(CI->getContext(), CI->getAttributes()));
|
||||||
|
|
||||||
Token = SPCall;
|
Token = cast<GCStatepointInst>(SPCall);
|
||||||
|
|
||||||
// Put the following gc_result and gc_relocate calls immediately after the
|
// Put the following gc_result and gc_relocate calls immediately after the
|
||||||
// the old call (which we're about to delete)
|
// the old call (which we're about to delete)
|
||||||
|
@ -1589,7 +1589,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */
|
||||||
SPInvoke->setAttributes(
|
SPInvoke->setAttributes(
|
||||||
legalizeCallAttributes(II->getContext(), II->getAttributes()));
|
legalizeCallAttributes(II->getContext(), II->getAttributes()));
|
||||||
|
|
||||||
Token = SPInvoke;
|
Token = cast<GCStatepointInst>(SPInvoke);
|
||||||
|
|
||||||
// Generate gc relocates in exceptional path
|
// Generate gc relocates in exceptional path
|
||||||
BasicBlock *UnwindBlock = II->getUnwindDest();
|
BasicBlock *UnwindBlock = II->getUnwindDest();
|
||||||
|
@ -1604,7 +1604,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */
|
||||||
Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst();
|
Instruction *ExceptionalToken = UnwindBlock->getLandingPadInst();
|
||||||
Result.UnwindToken = ExceptionalToken;
|
Result.UnwindToken = ExceptionalToken;
|
||||||
|
|
||||||
const unsigned LiveStartIdx = Statepoint(Token).gcArgsStartIdx();
|
const unsigned LiveStartIdx = Token->gcArgsStartIdx();
|
||||||
CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs, ExceptionalToken,
|
CreateGCRelocates(LiveVariables, LiveStartIdx, BasePtrs, ExceptionalToken,
|
||||||
Builder);
|
Builder);
|
||||||
|
|
||||||
|
@ -1652,7 +1652,7 @@ makeStatepointExplicitImpl(CallBase *Call, /* to replace */
|
||||||
Result.StatepointToken = Token;
|
Result.StatepointToken = Token;
|
||||||
|
|
||||||
// Second, create a gc.relocate for every live variable
|
// 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);
|
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.
|
// 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
|
// Thankfully, the live set is embedded in the statepoint (and updated), so
|
||||||
// we just grab that.
|
// we just grab that.
|
||||||
Statepoint Statepoint(Info.StatepointToken);
|
Live.insert(Live.end(), Info.StatepointToken->gc_args_begin(),
|
||||||
Live.insert(Live.end(), Statepoint.gc_args_begin(),
|
Info.StatepointToken->gc_args_end());
|
||||||
Statepoint.gc_args_end());
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Do some basic sanity checks on our liveness results before performing
|
// Do some basic sanity checks on our liveness results before performing
|
||||||
// relocation. Relocation can and will turn mistakes in liveness results
|
// 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
|
// TODO: It would be nice to test consistency as well
|
||||||
assert(DT.isReachableFromEntry(Info.StatepointToken->getParent()) &&
|
assert(DT.isReachableFromEntry(Info.StatepointToken->getParent()) &&
|
||||||
"statepoint must be reachable or liveness is meaningless");
|
"statepoint must be reachable or liveness is meaningless");
|
||||||
for (Value *V : Statepoint.gc_args()) {
|
for (Value *V : Info.StatepointToken->gc_args()) {
|
||||||
if (!isa<Instruction>(V))
|
if (!isa<Instruction>(V))
|
||||||
// Non-instruction values trivial dominate all possible uses
|
// Non-instruction values trivial dominate all possible uses
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Reference in New Issue