Index: llvm/trunk/include/llvm/IR/Statepoint.h =================================================================== --- llvm/trunk/include/llvm/IR/Statepoint.h +++ llvm/trunk/include/llvm/IR/Statepoint.h @@ -22,6 +22,7 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/Support/Compiler.h" @@ -36,14 +37,13 @@ MaskAll = GCTransition ///< A bitmask that includes all valid flags. }; -class GCRelocateOperands; +class GCRelocateInst; class ImmutableStatepoint; bool isStatepoint(const ImmutableCallSite &CS); bool isStatepoint(const Value *V); bool isStatepoint(const Value &V); -bool isGCRelocate(const Value *V); bool isGCRelocate(const ImmutableCallSite &CS); bool isGCResult(const Value *V); @@ -247,7 +247,7 @@ /// May contain several relocations for the same base/derived pair. /// For example this could happen due to relocations on unwinding /// path of invoke. - std::vector getRelocates() const; + std::vector getRelocates() const; /// 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 @@ -305,33 +305,27 @@ explicit Statepoint(CallSite CS) : Base(CS) {} }; -/// Wraps a call to a gc.relocate and provides access to it's operands. -/// TODO: This should likely be refactored to resememble the wrappers in -/// InstrinsicInst.h. -class GCRelocateOperands { - ImmutableCallSite RelocateCS; - +/// This represents the gc.relocate intrinsic. +class GCRelocateInst : public IntrinsicInst { public: - GCRelocateOperands(const User *U) : RelocateCS(U) { assert(isGCRelocate(U)); } - GCRelocateOperands(const Instruction *inst) : RelocateCS(inst) { - assert(isGCRelocate(inst)); + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::experimental_gc_relocate; + } + static inline bool classof(const Value *V) { + return isa(V) && classof(cast(V)); } - GCRelocateOperands(CallSite CS) : RelocateCS(CS) { assert(isGCRelocate(CS)); } /// Return true if this relocate is tied to the invoke statepoint. /// This includes relocates which are on the unwinding path. bool isTiedToInvoke() const { - const Value *Token = RelocateCS.getArgument(0); + const Value *Token = getArgOperand(0); return isa(Token) || isa(Token); } - /// Get enclosed relocate intrinsic - ImmutableCallSite getUnderlyingCallSite() { return RelocateCS; } - /// The statepoint with which this gc.relocate is associated. - const Instruction *getStatepoint() { - const Value *Token = RelocateCS.getArgument(0); + const Instruction *getStatepoint() const { + const Value *Token = getArgOperand(0); // This takes care both of relocates for call statepoints and relocates // on normal path of invoke statepoint. @@ -354,22 +348,22 @@ /// The index into the associate statepoint's argument list /// which contains the base pointer of the pointer whose /// relocation this gc.relocate describes. - unsigned getBasePtrIndex() { - return cast(RelocateCS.getArgument(1))->getZExtValue(); + unsigned getBasePtrIndex() const { + return cast(getArgOperand(1))->getZExtValue(); } /// The index into the associate statepoint's argument list which /// contains the pointer whose relocation this gc.relocate describes. - unsigned getDerivedPtrIndex() { - return cast(RelocateCS.getArgument(2))->getZExtValue(); + unsigned getDerivedPtrIndex() const { + return cast(getArgOperand(2))->getZExtValue(); } - Value *getBasePtr() { + Value *getBasePtr() const { ImmutableCallSite CS(getStatepoint()); return *(CS.arg_begin() + getBasePtrIndex()); } - Value *getDerivedPtr() { + Value *getDerivedPtr() const { ImmutableCallSite CS(getStatepoint()); return *(CS.arg_begin() + getDerivedPtrIndex()); } @@ -377,11 +371,11 @@ template -std::vector +std::vector StatepointBase::getRelocates() const { - std::vector Result; + std::vector Result; CallSiteTy StatepointCS = getCallSite(); @@ -389,8 +383,8 @@ // gc_relocates ensures that we only get pairs which are actually relocated // and used after the statepoint. for (const User *U : getInstruction()->users()) - if (isGCRelocate(U)) - Result.push_back(GCRelocateOperands(U)); + if (auto *Relocate = dyn_cast(U)) + Result.push_back(Relocate); if (!StatepointCS.isInvoke()) return Result; @@ -401,8 +395,8 @@ // Search for gc relocates that are attached to this landingpad. for (const User *LandingPadUser : LandingPad->users()) { - if (isGCRelocate(LandingPadUser)) - Result.push_back(GCRelocateOperands(LandingPadUser)); + if (auto *Relocate = dyn_cast(LandingPadUser)) + Result.push_back(Relocate); } return Result; } Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -3274,12 +3274,9 @@ } // For gc.relocate, look through relocations - if (const IntrinsicInst *I = dyn_cast(V)) - if (I->getIntrinsicID() == Intrinsic::experimental_gc_relocate) { - GCRelocateOperands RelocateInst(I); - return isDereferenceableAndAlignedPointer( - RelocateInst.getDerivedPtr(), Align, DL, CtxI, DT, TLI, Visited); - } + if (const GCRelocateInst *RelocateInst = dyn_cast(V)) + return isDereferenceableAndAlignedPointer( + RelocateInst->getDerivedPtr(), Align, DL, CtxI, DT, TLI, Visited); if (const AddrSpaceCastInst *ASC = dyn_cast(V)) return isDereferenceableAndAlignedPointer(ASC->getOperand(0), Align, DL, Index: llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp =================================================================== --- llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp +++ llvm/trunk/lib/CodeGen/CodeGenPrepare.cpp @@ -532,19 +532,17 @@ // Computes a map of base pointer relocation instructions to corresponding // derived pointer relocation instructions given a vector of all relocate calls static void computeBaseDerivedRelocateMap( - const SmallVectorImpl &AllRelocateCalls, - DenseMap> & - RelocateInstMap) { + const SmallVectorImpl &AllRelocateCalls, + DenseMap> + &RelocateInstMap) { // Collect information in two maps: one primarily for locating the base object // while filling the second map; the second map is the final structure holding // a mapping between Base and corresponding Derived relocate calls - DenseMap, IntrinsicInst *> RelocateIdxMap; - for (auto &U : AllRelocateCalls) { - GCRelocateOperands ThisRelocate(U); - IntrinsicInst *I = cast(U); - auto K = std::make_pair(ThisRelocate.getBasePtrIndex(), - ThisRelocate.getDerivedPtrIndex()); - RelocateIdxMap.insert(std::make_pair(K, I)); + DenseMap, GCRelocateInst *> RelocateIdxMap; + for (auto *ThisRelocate : AllRelocateCalls) { + auto K = std::make_pair(ThisRelocate->getBasePtrIndex(), + ThisRelocate->getDerivedPtrIndex()); + RelocateIdxMap.insert(std::make_pair(K, ThisRelocate)); } for (auto &Item : RelocateIdxMap) { std::pair Key = Item.first; @@ -552,7 +550,7 @@ // Base relocation: nothing to insert continue; - IntrinsicInst *I = Item.second; + GCRelocateInst *I = Item.second; auto BaseKey = std::make_pair(Key.first, Key.first); // We're iterating over RelocateIdxMap so we cannot modify it. @@ -585,16 +583,13 @@ // Takes a RelocatedBase (base pointer relocation instruction) and Targets to // replace, computes a replacement, and affects it. static bool -simplifyRelocatesOffABase(IntrinsicInst *RelocatedBase, - const SmallVectorImpl &Targets) { +simplifyRelocatesOffABase(GCRelocateInst *RelocatedBase, + const SmallVectorImpl &Targets) { bool MadeChange = false; - for (auto &ToReplace : Targets) { - GCRelocateOperands MasterRelocate(RelocatedBase); - GCRelocateOperands ThisRelocate(ToReplace); - - assert(ThisRelocate.getBasePtrIndex() == MasterRelocate.getBasePtrIndex() && + for (GCRelocateInst *ToReplace : Targets) { + assert(ToReplace->getBasePtrIndex() == RelocatedBase->getBasePtrIndex() && "Not relocating a derived object of the original base object"); - if (ThisRelocate.getBasePtrIndex() == ThisRelocate.getDerivedPtrIndex()) { + if (ToReplace->getBasePtrIndex() == ToReplace->getDerivedPtrIndex()) { // A duplicate relocate call. TODO: coalesce duplicates. continue; } @@ -607,8 +602,8 @@ continue; } - Value *Base = ThisRelocate.getBasePtr(); - auto Derived = dyn_cast(ThisRelocate.getDerivedPtr()); + Value *Base = ToReplace->getBasePtr(); + auto Derived = dyn_cast(ToReplace->getDerivedPtr()); if (!Derived || Derived->getPointerOperand() != Base) continue; @@ -686,12 +681,12 @@ // %val = load %ptr' bool CodeGenPrepare::simplifyOffsetableRelocate(Instruction &I) { bool MadeChange = false; - SmallVector AllRelocateCalls; + SmallVector AllRelocateCalls; for (auto *U : I.users()) - if (isGCRelocate(dyn_cast(U))) + if (GCRelocateInst *Relocate = dyn_cast(U)) // Collect all the relocate calls associated with a statepoint - AllRelocateCalls.push_back(U); + AllRelocateCalls.push_back(Relocate); // We need atleast one base pointer relocation + one derived pointer // relocation to mangle @@ -700,7 +695,7 @@ // RelocateInstMap is a mapping from the base relocate instruction to the // corresponding derived relocate instructions - DenseMap> RelocateInstMap; + DenseMap> RelocateInstMap; computeBaseDerivedRelocateMap(AllRelocateCalls, RelocateInstMap); if (RelocateInstMap.empty()) return false; Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.h @@ -855,7 +855,7 @@ // These three are implemented in StatepointLowering.cpp void visitStatepoint(const CallInst &I); - void visitGCRelocate(const CallInst &I); + void visitGCRelocate(const GCRelocateInst &I); void visitGCResult(const CallInst &I); void visitUserOp1(const Instruction &I) { Index: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -5189,7 +5189,7 @@ return nullptr; } case Intrinsic::experimental_gc_relocate: { - visitGCRelocate(I); + visitGCRelocate(cast(I)); return nullptr; } case Intrinsic::instrprof_increment: Index: llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp =================================================================== --- llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp +++ llvm/trunk/lib/CodeGen/SelectionDAG/StatepointLowering.cpp @@ -128,13 +128,11 @@ return Optional(); // Spill location is known for gc relocates - if (isGCRelocate(Val)) { - GCRelocateOperands RelocOps(cast(Val)); - + if (const auto *Relocate = dyn_cast(Val)) { FunctionLoweringInfo::StatepointSpilledValueMapTy &SpillMap = - Builder.FuncInfo.StatepointRelocatedValues[RelocOps.getStatepoint()]; + Builder.FuncInfo.StatepointRelocatedValues[Relocate->getStatepoint()]; - auto It = SpillMap.find(RelocOps.getDerivedPtr()); + auto It = SpillMap.find(Relocate->getDerivedPtr()); if (It == SpillMap.end()) return Optional(); @@ -401,10 +399,10 @@ SmallVectorImpl &Bases, SmallVectorImpl &Ptrs, SmallVectorImpl &Relocs, ImmutableStatepoint StatepointSite, SelectionDAGBuilder &Builder) { - for (GCRelocateOperands relocateOpers : StatepointSite.getRelocates()) { - Relocs.push_back(relocateOpers.getUnderlyingCallSite().getInstruction()); - Bases.push_back(relocateOpers.getBasePtr()); - Ptrs.push_back(relocateOpers.getDerivedPtr()); + for (const GCRelocateInst *Relocate : StatepointSite.getRelocates()) { + Relocs.push_back(Relocate); + Bases.push_back(Relocate->getBasePtr()); + Ptrs.push_back(Relocate->getDerivedPtr()); } // Remove any redundant llvm::Values which map to the same SDValue as another @@ -602,8 +600,8 @@ FunctionLoweringInfo::StatepointSpilledValueMapTy &SpillMap = Builder.FuncInfo.StatepointRelocatedValues[StatepointInstr]; - for (GCRelocateOperands RelocateOpers : StatepointSite.getRelocates()) { - const Value *V = RelocateOpers.getDerivedPtr(); + for (const GCRelocateInst *Relocate : StatepointSite.getRelocates()) { + const Value *V = Relocate->getDerivedPtr(); SDValue SDV = Builder.getValue(V); SDValue Loc = Builder.StatepointLowering.getLocation(SDV); @@ -624,8 +622,7 @@ // uses of the corresponding values so that it would automatically // export them. Relocates of the spilled values does not use original // value. - if (RelocateOpers.getUnderlyingCallSite().getParent() != - StatepointInstr->getParent()) + if (Relocate->getParent() != StatepointInstr->getParent()) Builder.ExportFromCurrentBlock(V); } } @@ -656,7 +653,7 @@ // statepoint. for (const User *U : CS->users()) { const CallInst *Call = cast(U); - if (isGCRelocate(Call) && Call->getParent() == CS.getParent()) + if (isa(Call) && Call->getParent() == CS.getParent()) StatepointLowering.scheduleRelocCall(*Call); } #endif @@ -859,24 +856,22 @@ } } -void SelectionDAGBuilder::visitGCRelocate(const CallInst &CI) { - GCRelocateOperands RelocateOpers(&CI); - +void SelectionDAGBuilder::visitGCRelocate(const GCRelocateInst &Relocate) { #ifndef NDEBUG // Consistency check // We skip this check for relocates not in the same basic block as thier // statepoint. It would be too expensive to preserve validation info through // different basic blocks. - if (RelocateOpers.getStatepoint()->getParent() == CI.getParent()) { - StatepointLowering.relocCallVisited(CI); + if (Relocate.getStatepoint()->getParent() == Relocate.getParent()) { + StatepointLowering.relocCallVisited(Relocate); } #endif - const Value *DerivedPtr = RelocateOpers.getDerivedPtr(); + const Value *DerivedPtr = Relocate.getDerivedPtr(); SDValue SD = getValue(DerivedPtr); FunctionLoweringInfo::StatepointSpilledValueMapTy &SpillMap = - FuncInfo.StatepointRelocatedValues[RelocateOpers.getStatepoint()]; + FuncInfo.StatepointRelocatedValues[Relocate.getStatepoint()]; // We should have recorded location for this pointer assert(SpillMap.count(DerivedPtr) && "Relocating not lowered gc value"); @@ -885,7 +880,7 @@ // We didn't need to spill these special cases (constants and allocas). // See the handling in spillIncomingValueForStatepoint for detail. if (!DerivedPtrLocation) { - setValue(&CI, SD); + setValue(&Relocate, SD); return; } @@ -907,5 +902,5 @@ DAG.setRoot(SpillLoad.getValue(1)); assert(SpillLoad.getNode()); - setValue(&CI, SpillLoad); + setValue(&Relocate, SpillLoad); } Index: llvm/trunk/lib/IR/AsmWriter.cpp =================================================================== --- llvm/trunk/lib/IR/AsmWriter.cpp +++ llvm/trunk/lib/IR/AsmWriter.cpp @@ -2060,7 +2060,7 @@ // printGCRelocateComment - print comment after call to the gc.relocate // intrinsic indicating base and derived pointer names. - void printGCRelocateComment(const Value &V); + void printGCRelocateComment(const GCRelocateInst &Relocate); }; } // namespace @@ -2722,14 +2722,11 @@ /// printGCRelocateComment - print comment after call to the gc.relocate /// intrinsic indicating base and derived pointer names. -void AssemblyWriter::printGCRelocateComment(const Value &V) { - assert(isGCRelocate(&V)); - GCRelocateOperands GCOps(cast(&V)); - +void AssemblyWriter::printGCRelocateComment(const GCRelocateInst &Relocate) { Out << " ; ("; - writeOperand(GCOps.getBasePtr(), false); + writeOperand(Relocate.getBasePtr(), false); Out << ", "; - writeOperand(GCOps.getDerivedPtr(), false); + writeOperand(Relocate.getDerivedPtr(), false); Out << ")"; } @@ -2737,8 +2734,8 @@ /// which slot it occupies. /// void AssemblyWriter::printInfoComment(const Value &V) { - if (isGCRelocate(&V)) - printGCRelocateComment(V); + if (const auto *Relocate = dyn_cast(&V)) + printGCRelocateComment(*Relocate); if (AnnotationWriter) AnnotationWriter->printInfoComment(V, Out); Index: llvm/trunk/lib/IR/Statepoint.cpp =================================================================== --- llvm/trunk/lib/IR/Statepoint.cpp +++ llvm/trunk/lib/IR/Statepoint.cpp @@ -40,20 +40,7 @@ } bool llvm::isGCRelocate(const ImmutableCallSite &CS) { - if (!CS.getInstruction()) { - // This is not a call site - return false; - } - - return isGCRelocate(CS.getInstruction()); -} -bool llvm::isGCRelocate(const Value *inst) { - if (const CallInst *call = dyn_cast(inst)) { - if (const Function *F = call->getCalledFunction()) { - return F->getIntrinsicID() == Intrinsic::experimental_gc_relocate; - } - } - return false; + return CS.getInstruction() && isa(CS.getInstruction()); } bool llvm::isGCResult(const ImmutableCallSite &CS) { Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -1657,14 +1657,14 @@ const CallInst *Call = dyn_cast(U); Assert(Call, "illegal use of statepoint token", &CI, U); if (!Call) continue; - Assert(isGCRelocate(Call) || isGCResult(Call), + Assert(isa(Call) || isGCResult(Call), "gc.result or gc.relocate are the only value uses" "of a gc.statepoint", &CI, U); if (isGCResult(Call)) { Assert(Call->getArgOperand(0) == &CI, "gc.result connected to wrong gc.statepoint", &CI, Call); - } else if (isGCRelocate(Call)) { + } else if (isa(Call)) { Assert(Call->getArgOperand(0) == &CI, "gc.relocate connected to wrong gc.statepoint", &CI, Call); } @@ -3681,8 +3681,8 @@ // Verify rest of the relocate arguments - GCRelocateOperands Ops(CS); - ImmutableCallSite StatepointCS(Ops.getStatepoint()); + ImmutableCallSite StatepointCS( + cast(*CS.getInstruction()).getStatepoint()); // Both the base and derived must be piped through the safepoint Value* Base = CS.getArgOperand(1); @@ -3737,14 +3737,14 @@ // Relocated value must be a pointer type, but gc_relocate does not need to return the // same pointer type as the relocated pointer. It can be casted to the correct type later // if it's desired. However, they must have the same address space. - GCRelocateOperands Operands(CS); - Assert(Operands.getDerivedPtr()->getType()->isPointerTy(), + GCRelocateInst &Relocate = cast(*CS.getInstruction()); + Assert(Relocate.getDerivedPtr()->getType()->isPointerTy(), "gc.relocate: relocated value must be a gc pointer", CS); // gc_relocate return type must be a pointer type, and is verified earlier in // VerifyIntrinsicType(). Assert(cast(CS.getType())->getAddressSpace() == - cast(Operands.getDerivedPtr()->getType())->getAddressSpace(), + cast(Relocate.getDerivedPtr()->getType())->getAddressSpace(), "gc.relocate: relocating a pointer shouldn't change its address space", CS); break; } Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1747,8 +1747,7 @@ // Translate facts known about a pointer before relocating into // facts about the relocate value, while being careful to // preserve relocation semantics. - GCRelocateOperands Operands(II); - Value *DerivedPtr = Operands.getDerivedPtr(); + Value *DerivedPtr = cast(II)->getDerivedPtr(); auto *GCRelocateType = cast(II->getType()); // Remove the relocation if unused, note that this check is required Index: llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp +++ llvm/trunk/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp @@ -1642,33 +1642,24 @@ DenseSet &VisitedLiveValues) { for (User *U : GCRelocs) { - if (!isa(U)) + GCRelocateInst *Relocate = dyn_cast(U); + if (!Relocate) continue; - IntrinsicInst *RelocatedValue = cast(U); - - // We only care about relocates - if (RelocatedValue->getIntrinsicID() != - Intrinsic::experimental_gc_relocate) { - continue; - } - - GCRelocateOperands RelocateOperands(RelocatedValue); - Value *OriginalValue = - const_cast(RelocateOperands.getDerivedPtr()); + Value *OriginalValue = const_cast(Relocate->getDerivedPtr()); assert(AllocaMap.count(OriginalValue)); Value *Alloca = AllocaMap[OriginalValue]; // Emit store into the related alloca // All gc_relocates are i8 addrspace(1)* typed, and it must be bitcasted to // the correct type according to alloca. - assert(RelocatedValue->getNextNode() && + assert(Relocate->getNextNode() && "Should always have one since it's not a terminator"); - IRBuilder<> Builder(RelocatedValue->getNextNode()); + IRBuilder<> Builder(Relocate->getNextNode()); Value *CastedRelocatedValue = - Builder.CreateBitCast(RelocatedValue, + Builder.CreateBitCast(Relocate, cast(Alloca)->getAllocatedType(), - suffixed_name_or(RelocatedValue, ".casted", "")); + suffixed_name_or(Relocate, ".casted", "")); StoreInst *Store = new StoreInst(CastedRelocatedValue, Alloca); Store->insertAfter(cast(CastedRelocatedValue));