mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-24 05:09:34 +00:00
Introduce an GCRelocateInst class [NFC]
Previously, we were using isGCRelocate predicates. Using a subclass of IntrinsicInst is far more idiomatic. The refactoring also enables a couple of minor simplifications and code sharing. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@266098 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7fa1223ec4
commit
0802f714a2
@ -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 *>
|
||||
|
@ -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: {
|
||||
|
@ -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!");
|
||||
|
@ -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>(
|
||||
|
@ -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) {
|
||||
|
@ -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)) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user