llvm.org GIT mirror llvm / 0802f71
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 Philip Reames 3 years ago
6 changed file(s) with 41 addition(s) and 25 deletion(s). Raw diff Collapse all Expand all
3838 };
3939
4040 class GCRelocateInst;
41 class GCResultInst;
4142 class ImmutableStatepoint;
4243
4344 bool isStatepoint(ImmutableCallSite CS);
4546 bool isStatepoint(const Value &V);
4647
4748 bool isGCRelocate(ImmutableCallSite CS);
48
49 bool isGCResult(const Value *V);
5049 bool isGCResult(ImmutableCallSite CS);
5150
5251 /// Analogous to CallSiteBase, this provides most of the actual
252251 /// Get the experimental_gc_result call tied to this statepoint. Can be
253252 /// nullptr if there isn't a gc_result tied to this statepoint. Guaranteed to
254253 /// be a CallInst if non-null.
255 InstructionTy *getGCResult() const {
254 const GCResultInst *getGCResult() const {
256255 for (auto *U : getInstruction()->users())
257 if (isGCResult(U))
258 return cast(U);
259
256 if (auto *GRI = dyn_cast(U))
257 return GRI;
260258 return nullptr;
261259 }
262260
305303 explicit Statepoint(CallSite CS) : Base(CS) {}
306304 };
307305
308 /// This represents the gc.relocate intrinsic.
309 class GCRelocateInst : public IntrinsicInst {
306 /// Common base class for representing values projected from a statepoint.
307 /// Currently, the only projections available are gc.result and gc.relocate.
308 class GCProjectionInst : public IntrinsicInst {
310309 public:
311310 static inline bool classof(const IntrinsicInst *I) {
312 return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
311 return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate ||
312 I->getIntrinsicID() == Intrinsic::experimental_gc_result;
313313 }
314314 static inline bool classof(const Value *V) {
315315 return isa(V) && classof(cast(V));
330330 // This takes care both of relocates for call statepoints and relocates
331331 // on normal path of invoke statepoint.
332332 if (!isa(Token)) {
333 assert(isStatepoint(Token));
333334 return cast(Token);
334335 }
335336
343344 assert(isStatepoint(InvokeBB->getTerminator()));
344345
345346 return InvokeBB->getTerminator();
347 }
348 };
349
350 /// This represents the gc.relocate intrinsic.
351 class GCRelocateInst : public GCProjectionInst {
352 public:
353 static inline bool classof(const IntrinsicInst *I) {
354 return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate;
355 }
356 static inline bool classof(const Value *V) {
357 return isa(V) && classof(cast(V));
346358 }
347359
348360 /// The index into the associate statepoint's argument list
366378 Value *getDerivedPtr() const {
367379 ImmutableCallSite CS(getStatepoint());
368380 return *(CS.arg_begin() + getDerivedPtrIndex());
381 }
382 };
383
384 /// This represents the gc.result intrinsic.
385 class GCResultInst : public GCProjectionInst {
386 public:
387 static inline bool classof(const IntrinsicInst *I) {
388 return I->getIntrinsicID() == Intrinsic::experimental_gc_result;
389 }
390 static inline bool classof(const Value *V) {
391 return isa(V) && classof(cast(V));
369392 }
370393 };
371394
55385538 return nullptr;
55395539 }
55405540 case Intrinsic::experimental_gc_result: {
5541 visitGCResult(I);
5541 visitGCResult(cast(I));
55425542 return nullptr;
55435543 }
55445544 case Intrinsic::experimental_gc_relocate: {
903903
904904 // These two are implemented in StatepointLowering.cpp
905905 void visitGCRelocate(const GCRelocateInst &I);
906 void visitGCResult(const CallInst &I);
906 void visitGCResult(const GCResultInst &I);
907907
908908 void visitUserOp1(const Instruction &I) {
909909 llvm_unreachable("UserOp1 should not exist at instruction selection time!");
787787 SDValue ReturnValue = LowerAsSTATEPOINT(SI);
788788
789789 // Export the result value if needed
790 const Instruction *GCResult = ISP.getGCResult();
790 const GCResultInst *GCResult = ISP.getGCResult();
791791 Type *RetTy = ISP.getActualReturnType();
792792 if (!RetTy->isVoidTy() && GCResult) {
793793 if (GCResult->getParent() != ISP.getCallSite().getParent()) {
861861 /* ForceVoidReturnTy = */ false);
862862 }
863863
864 void SelectionDAGBuilder::visitGCResult(const CallInst &CI) {
864 void SelectionDAGBuilder::visitGCResult(const GCResultInst &CI) {
865865 // The result value of the gc_result is simply the result of the actual
866866 // call. We've already emitted this, so just grab the value.
867 Instruction *I = cast(CI.getArgOperand(0));
868 assert(isStatepoint(I) && "first argument must be a statepoint token");
867 const Instruction *I = CI.getStatepoint();
869868
870869 if (I->getParent() != CI.getParent()) {
871870 // Statepoint is in different basic block so we should have stored call
872871 // result in a virtual register.
873872 // We can not use default getValue() functionality to copy value from this
874 // register because statepoint and actuall call return types can be
873 // register because statepoint and actual call return types can be
875874 // different, and getValue() will use CopyFromReg of the wrong type,
876875 // which is always i32 in our case.
877876 PointerType *CalleeType = cast(
4444 }
4545
4646 bool llvm::isGCResult(ImmutableCallSite CS) {
47 if (auto *F = getCalledFunction(CS))
48 return F->getIntrinsicID() == Intrinsic::experimental_gc_result;
49 return false;
50 }
51
52 bool llvm::isGCResult(const Value *V) {
53 return isGCResult(ImmutableCallSite(V));
47 return CS.getInstruction() && isa(CS.getInstruction());
5448 }
5549
5650 bool llvm::isStatepointDirectiveAttr(Attribute Attr) {
17731773 const CallInst *Call = dyn_cast(U);
17741774 Assert(Call, "illegal use of statepoint token", &CI, U);
17751775 if (!Call) continue;
1776 Assert(isa(Call) || isGCResult(Call),
1776 Assert(isa(Call) || isa(Call),
17771777 "gc.result or gc.relocate are the only value uses"
17781778 "of a gc.statepoint",
17791779 &CI, U);
1780 if (isGCResult(Call)) {
1780 if (isa(Call)) {
17811781 Assert(Call->getArgOperand(0) == &CI,
17821782 "gc.result connected to wrong gc.statepoint", &CI, Call);
17831783 } else if (isa(Call)) {