139d628a0SDimitry Andric //===-- StatepointLowering.cpp - SDAGBuilder's statepoint code -----------===// 239d628a0SDimitry Andric // 339d628a0SDimitry Andric // The LLVM Compiler Infrastructure 439d628a0SDimitry Andric // 539d628a0SDimitry Andric // This file is distributed under the University of Illinois Open Source 639d628a0SDimitry Andric // License. See LICENSE.TXT for details. 739d628a0SDimitry Andric // 839d628a0SDimitry Andric //===----------------------------------------------------------------------===// 939d628a0SDimitry Andric // 1039d628a0SDimitry Andric // This file includes support code use by SelectionDAGBuilder when lowering a 1139d628a0SDimitry Andric // statepoint sequence in SelectionDAG IR. 1239d628a0SDimitry Andric // 1339d628a0SDimitry Andric //===----------------------------------------------------------------------===// 1439d628a0SDimitry Andric 1539d628a0SDimitry Andric #include "StatepointLowering.h" 1639d628a0SDimitry Andric #include "SelectionDAGBuilder.h" 1739d628a0SDimitry Andric #include "llvm/ADT/SmallSet.h" 1839d628a0SDimitry Andric #include "llvm/ADT/Statistic.h" 1939d628a0SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h" 2039d628a0SDimitry Andric #include "llvm/CodeGen/GCStrategy.h" 2139d628a0SDimitry Andric #include "llvm/CodeGen/SelectionDAG.h" 2239d628a0SDimitry Andric #include "llvm/CodeGen/StackMaps.h" 2339d628a0SDimitry Andric #include "llvm/IR/CallingConv.h" 2439d628a0SDimitry Andric #include "llvm/IR/Instructions.h" 2539d628a0SDimitry Andric #include "llvm/IR/IntrinsicInst.h" 2639d628a0SDimitry Andric #include "llvm/IR/Intrinsics.h" 2739d628a0SDimitry Andric #include "llvm/IR/Statepoint.h" 2839d628a0SDimitry Andric #include "llvm/Target/TargetLowering.h" 2939d628a0SDimitry Andric #include <algorithm> 3039d628a0SDimitry Andric using namespace llvm; 3139d628a0SDimitry Andric 3239d628a0SDimitry Andric #define DEBUG_TYPE "statepoint-lowering" 3339d628a0SDimitry Andric 3439d628a0SDimitry Andric STATISTIC(NumSlotsAllocatedForStatepoints, 3539d628a0SDimitry Andric "Number of stack slots allocated for statepoints"); 3639d628a0SDimitry Andric STATISTIC(NumOfStatepoints, "Number of statepoint nodes encountered"); 3739d628a0SDimitry Andric STATISTIC(StatepointMaxSlotsRequired, 3839d628a0SDimitry Andric "Maximum number of stack slots required for a singe statepoint"); 3939d628a0SDimitry Andric 4039d628a0SDimitry Andric void 4139d628a0SDimitry Andric StatepointLoweringState::startNewStatepoint(SelectionDAGBuilder &Builder) { 4239d628a0SDimitry Andric // Consistency check 4339d628a0SDimitry Andric assert(PendingGCRelocateCalls.empty() && 4439d628a0SDimitry Andric "Trying to visit statepoint before finished processing previous one"); 4539d628a0SDimitry Andric Locations.clear(); 4639d628a0SDimitry Andric RelocLocations.clear(); 4739d628a0SDimitry Andric NextSlotToAllocate = 0; 4839d628a0SDimitry Andric // Need to resize this on each safepoint - we need the two to stay in 4939d628a0SDimitry Andric // sync and the clear patterns of a SelectionDAGBuilder have no relation 5039d628a0SDimitry Andric // to FunctionLoweringInfo. 5139d628a0SDimitry Andric AllocatedStackSlots.resize(Builder.FuncInfo.StatepointStackSlots.size()); 5239d628a0SDimitry Andric for (size_t i = 0; i < AllocatedStackSlots.size(); i++) { 5339d628a0SDimitry Andric AllocatedStackSlots[i] = false; 5439d628a0SDimitry Andric } 5539d628a0SDimitry Andric } 5639d628a0SDimitry Andric void StatepointLoweringState::clear() { 5739d628a0SDimitry Andric Locations.clear(); 5839d628a0SDimitry Andric RelocLocations.clear(); 5939d628a0SDimitry Andric AllocatedStackSlots.clear(); 6039d628a0SDimitry Andric assert(PendingGCRelocateCalls.empty() && 6139d628a0SDimitry Andric "cleared before statepoint sequence completed"); 6239d628a0SDimitry Andric } 6339d628a0SDimitry Andric 6439d628a0SDimitry Andric SDValue 6539d628a0SDimitry Andric StatepointLoweringState::allocateStackSlot(EVT ValueType, 6639d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 6739d628a0SDimitry Andric 6839d628a0SDimitry Andric NumSlotsAllocatedForStatepoints++; 6939d628a0SDimitry Andric 7039d628a0SDimitry Andric // The basic scheme here is to first look for a previously created stack slot 7139d628a0SDimitry Andric // which is not in use (accounting for the fact arbitrary slots may already 7239d628a0SDimitry Andric // be reserved), or to create a new stack slot and use it. 7339d628a0SDimitry Andric 7439d628a0SDimitry Andric // If this doesn't succeed in 40000 iterations, something is seriously wrong 7539d628a0SDimitry Andric for (int i = 0; i < 40000; i++) { 7639d628a0SDimitry Andric assert(Builder.FuncInfo.StatepointStackSlots.size() == 7739d628a0SDimitry Andric AllocatedStackSlots.size() && 7839d628a0SDimitry Andric "broken invariant"); 7939d628a0SDimitry Andric const size_t NumSlots = AllocatedStackSlots.size(); 8039d628a0SDimitry Andric assert(NextSlotToAllocate <= NumSlots && "broken invariant"); 8139d628a0SDimitry Andric 8239d628a0SDimitry Andric if (NextSlotToAllocate >= NumSlots) { 8339d628a0SDimitry Andric assert(NextSlotToAllocate == NumSlots); 8439d628a0SDimitry Andric // record stats 8539d628a0SDimitry Andric if (NumSlots + 1 > StatepointMaxSlotsRequired) { 8639d628a0SDimitry Andric StatepointMaxSlotsRequired = NumSlots + 1; 8739d628a0SDimitry Andric } 8839d628a0SDimitry Andric 8939d628a0SDimitry Andric SDValue SpillSlot = Builder.DAG.CreateStackTemporary(ValueType); 9039d628a0SDimitry Andric const unsigned FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex(); 9139d628a0SDimitry Andric Builder.FuncInfo.StatepointStackSlots.push_back(FI); 9239d628a0SDimitry Andric AllocatedStackSlots.push_back(true); 9339d628a0SDimitry Andric return SpillSlot; 9439d628a0SDimitry Andric } 9539d628a0SDimitry Andric if (!AllocatedStackSlots[NextSlotToAllocate]) { 9639d628a0SDimitry Andric const int FI = Builder.FuncInfo.StatepointStackSlots[NextSlotToAllocate]; 9739d628a0SDimitry Andric AllocatedStackSlots[NextSlotToAllocate] = true; 9839d628a0SDimitry Andric return Builder.DAG.getFrameIndex(FI, ValueType); 9939d628a0SDimitry Andric } 10039d628a0SDimitry Andric // Note: We deliberately choose to advance this only on the failing path. 10139d628a0SDimitry Andric // Doing so on the suceeding path involes a bit of complexity that caused a 10239d628a0SDimitry Andric // minor bug previously. Unless performance shows this matters, please 10339d628a0SDimitry Andric // keep this code as simple as possible. 10439d628a0SDimitry Andric NextSlotToAllocate++; 10539d628a0SDimitry Andric } 10639d628a0SDimitry Andric llvm_unreachable("infinite loop?"); 10739d628a0SDimitry Andric } 10839d628a0SDimitry Andric 10939d628a0SDimitry Andric /// Try to find existing copies of the incoming values in stack slots used for 11039d628a0SDimitry Andric /// statepoint spilling. If we can find a spill slot for the incoming value, 11139d628a0SDimitry Andric /// mark that slot as allocated, and reuse the same slot for this safepoint. 11239d628a0SDimitry Andric /// This helps to avoid series of loads and stores that only serve to resuffle 11339d628a0SDimitry Andric /// values on the stack between calls. 11439d628a0SDimitry Andric static void reservePreviousStackSlotForValue(SDValue Incoming, 11539d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 11639d628a0SDimitry Andric 11739d628a0SDimitry Andric if (isa<ConstantSDNode>(Incoming) || isa<FrameIndexSDNode>(Incoming)) { 11839d628a0SDimitry Andric // We won't need to spill this, so no need to check for previously 11939d628a0SDimitry Andric // allocated stack slots 12039d628a0SDimitry Andric return; 12139d628a0SDimitry Andric } 12239d628a0SDimitry Andric 12339d628a0SDimitry Andric SDValue Loc = Builder.StatepointLowering.getLocation(Incoming); 12439d628a0SDimitry Andric if (Loc.getNode()) { 12539d628a0SDimitry Andric // duplicates in input 12639d628a0SDimitry Andric return; 12739d628a0SDimitry Andric } 12839d628a0SDimitry Andric 12939d628a0SDimitry Andric // Search back for the load from a stack slot pattern to find the original 13039d628a0SDimitry Andric // slot we allocated for this value. We could extend this to deal with 13139d628a0SDimitry Andric // simple modification patterns, but simple dealing with trivial load/store 13239d628a0SDimitry Andric // sequences helps a lot already. 13339d628a0SDimitry Andric if (LoadSDNode *Load = dyn_cast<LoadSDNode>(Incoming)) { 13439d628a0SDimitry Andric if (auto *FI = dyn_cast<FrameIndexSDNode>(Load->getBasePtr())) { 13539d628a0SDimitry Andric const int Index = FI->getIndex(); 13639d628a0SDimitry Andric auto Itr = std::find(Builder.FuncInfo.StatepointStackSlots.begin(), 13739d628a0SDimitry Andric Builder.FuncInfo.StatepointStackSlots.end(), Index); 13839d628a0SDimitry Andric if (Itr == Builder.FuncInfo.StatepointStackSlots.end()) { 13939d628a0SDimitry Andric // not one of the lowering stack slots, can't reuse! 14039d628a0SDimitry Andric // TODO: Actually, we probably could reuse the stack slot if the value 14139d628a0SDimitry Andric // hasn't changed at all, but we'd need to look for intervening writes 14239d628a0SDimitry Andric return; 14339d628a0SDimitry Andric } else { 14439d628a0SDimitry Andric // This is one of our dedicated lowering slots 14539d628a0SDimitry Andric const int Offset = 14639d628a0SDimitry Andric std::distance(Builder.FuncInfo.StatepointStackSlots.begin(), Itr); 14739d628a0SDimitry Andric if (Builder.StatepointLowering.isStackSlotAllocated(Offset)) { 14839d628a0SDimitry Andric // stack slot already assigned to someone else, can't use it! 14939d628a0SDimitry Andric // TODO: currently we reserve space for gc arguments after doing 15039d628a0SDimitry Andric // normal allocation for deopt arguments. We should reserve for 15139d628a0SDimitry Andric // _all_ deopt and gc arguments, then start allocating. This 15239d628a0SDimitry Andric // will prevent some moves being inserted when vm state changes, 15339d628a0SDimitry Andric // but gc state doesn't between two calls. 15439d628a0SDimitry Andric return; 15539d628a0SDimitry Andric } 15639d628a0SDimitry Andric // Reserve this stack slot 15739d628a0SDimitry Andric Builder.StatepointLowering.reserveStackSlot(Offset); 15839d628a0SDimitry Andric } 15939d628a0SDimitry Andric 16039d628a0SDimitry Andric // Cache this slot so we find it when going through the normal 16139d628a0SDimitry Andric // assignment loop. 16239d628a0SDimitry Andric SDValue Loc = 16339d628a0SDimitry Andric Builder.DAG.getTargetFrameIndex(Index, Incoming.getValueType()); 16439d628a0SDimitry Andric 16539d628a0SDimitry Andric Builder.StatepointLowering.setLocation(Incoming, Loc); 16639d628a0SDimitry Andric } 16739d628a0SDimitry Andric } 16839d628a0SDimitry Andric 16939d628a0SDimitry Andric // TODO: handle case where a reloaded value flows through a phi to 17039d628a0SDimitry Andric // another safepoint. e.g. 17139d628a0SDimitry Andric // bb1: 17239d628a0SDimitry Andric // a' = relocated... 17339d628a0SDimitry Andric // bb2: % pred: bb1, bb3, bb4, etc. 17439d628a0SDimitry Andric // a_phi = phi(a', ...) 17539d628a0SDimitry Andric // statepoint ... a_phi 17639d628a0SDimitry Andric // NOTE: This will require reasoning about cross basic block values. This is 17739d628a0SDimitry Andric // decidedly non trivial and this might not be the right place to do it. We 17839d628a0SDimitry Andric // don't really have the information we need here... 17939d628a0SDimitry Andric 18039d628a0SDimitry Andric // TODO: handle simple updates. If a value is modified and the original 18139d628a0SDimitry Andric // value is no longer live, it would be nice to put the modified value in the 18239d628a0SDimitry Andric // same slot. This allows folding of the memory accesses for some 18339d628a0SDimitry Andric // instructions types (like an increment). 18439d628a0SDimitry Andric // statepoint (i) 18539d628a0SDimitry Andric // i1 = i+1 18639d628a0SDimitry Andric // statepoint (i1) 18739d628a0SDimitry Andric } 18839d628a0SDimitry Andric 18939d628a0SDimitry Andric /// Remove any duplicate (as SDValues) from the derived pointer pairs. This 19039d628a0SDimitry Andric /// is not required for correctness. It's purpose is to reduce the size of 19139d628a0SDimitry Andric /// StackMap section. It has no effect on the number of spill slots required 19239d628a0SDimitry Andric /// or the actual lowering. 19339d628a0SDimitry Andric static void removeDuplicatesGCPtrs(SmallVectorImpl<const Value *> &Bases, 19439d628a0SDimitry Andric SmallVectorImpl<const Value *> &Ptrs, 19539d628a0SDimitry Andric SmallVectorImpl<const Value *> &Relocs, 19639d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 19739d628a0SDimitry Andric 19839d628a0SDimitry Andric // This is horribly ineffecient, but I don't care right now 19939d628a0SDimitry Andric SmallSet<SDValue, 64> Seen; 20039d628a0SDimitry Andric 20139d628a0SDimitry Andric SmallVector<const Value *, 64> NewBases, NewPtrs, NewRelocs; 20239d628a0SDimitry Andric for (size_t i = 0; i < Ptrs.size(); i++) { 20339d628a0SDimitry Andric SDValue SD = Builder.getValue(Ptrs[i]); 20439d628a0SDimitry Andric // Only add non-duplicates 20539d628a0SDimitry Andric if (Seen.count(SD) == 0) { 20639d628a0SDimitry Andric NewBases.push_back(Bases[i]); 20739d628a0SDimitry Andric NewPtrs.push_back(Ptrs[i]); 20839d628a0SDimitry Andric NewRelocs.push_back(Relocs[i]); 20939d628a0SDimitry Andric } 21039d628a0SDimitry Andric Seen.insert(SD); 21139d628a0SDimitry Andric } 21239d628a0SDimitry Andric assert(Bases.size() >= NewBases.size()); 21339d628a0SDimitry Andric assert(Ptrs.size() >= NewPtrs.size()); 21439d628a0SDimitry Andric assert(Relocs.size() >= NewRelocs.size()); 21539d628a0SDimitry Andric Bases = NewBases; 21639d628a0SDimitry Andric Ptrs = NewPtrs; 21739d628a0SDimitry Andric Relocs = NewRelocs; 21839d628a0SDimitry Andric assert(Ptrs.size() == Bases.size()); 21939d628a0SDimitry Andric assert(Ptrs.size() == Relocs.size()); 22039d628a0SDimitry Andric } 22139d628a0SDimitry Andric 22239d628a0SDimitry Andric /// Extract call from statepoint, lower it and return pointer to the 22339d628a0SDimitry Andric /// call node. Also update NodeMap so that getValue(statepoint) will 22439d628a0SDimitry Andric /// reference lowered call result 22539d628a0SDimitry Andric static SDNode *lowerCallFromStatepoint(const CallInst &CI, 22639d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 22739d628a0SDimitry Andric 22839d628a0SDimitry Andric assert(Intrinsic::experimental_gc_statepoint == 22939d628a0SDimitry Andric dyn_cast<IntrinsicInst>(&CI)->getIntrinsicID() && 23039d628a0SDimitry Andric "function called must be the statepoint function"); 23139d628a0SDimitry Andric 23239d628a0SDimitry Andric ImmutableStatepoint StatepointOperands(&CI); 23339d628a0SDimitry Andric 23439d628a0SDimitry Andric // Lower the actual call itself - This is a bit of a hack, but we want to 23539d628a0SDimitry Andric // avoid modifying the actual lowering code. This is similiar in intent to 23639d628a0SDimitry Andric // the LowerCallOperands mechanism used by PATCHPOINT, but is structured 23739d628a0SDimitry Andric // differently. Hopefully, this is slightly more robust w.r.t. calling 23839d628a0SDimitry Andric // convention, return values, and other function attributes. 23939d628a0SDimitry Andric Value *ActualCallee = const_cast<Value *>(StatepointOperands.actualCallee()); 24039d628a0SDimitry Andric 24139d628a0SDimitry Andric std::vector<Value *> Args; 24239d628a0SDimitry Andric CallInst::const_op_iterator arg_begin = StatepointOperands.call_args_begin(); 24339d628a0SDimitry Andric CallInst::const_op_iterator arg_end = StatepointOperands.call_args_end(); 24439d628a0SDimitry Andric Args.insert(Args.end(), arg_begin, arg_end); 24539d628a0SDimitry Andric // TODO: remove the creation of a new instruction! We should not be 24639d628a0SDimitry Andric // modifying the IR (even temporarily) at this point. 24739d628a0SDimitry Andric CallInst *Tmp = CallInst::Create(ActualCallee, Args); 24839d628a0SDimitry Andric Tmp->setTailCall(CI.isTailCall()); 24939d628a0SDimitry Andric Tmp->setCallingConv(CI.getCallingConv()); 25039d628a0SDimitry Andric Tmp->setAttributes(CI.getAttributes()); 25139d628a0SDimitry Andric Builder.LowerCallTo(Tmp, Builder.getValue(ActualCallee), false); 25239d628a0SDimitry Andric 25339d628a0SDimitry Andric // Handle the return value of the call iff any. 25439d628a0SDimitry Andric const bool HasDef = !Tmp->getType()->isVoidTy(); 25539d628a0SDimitry Andric if (HasDef) { 25639d628a0SDimitry Andric // The value of the statepoint itself will be the value of call itself. 25739d628a0SDimitry Andric // We'll replace the actually call node shortly. gc_result will grab 25839d628a0SDimitry Andric // this value. 25939d628a0SDimitry Andric Builder.setValue(&CI, Builder.getValue(Tmp)); 26039d628a0SDimitry Andric } else { 26139d628a0SDimitry Andric // The token value is never used from here on, just generate a poison value 26239d628a0SDimitry Andric Builder.setValue(&CI, Builder.DAG.getIntPtrConstant(-1)); 26339d628a0SDimitry Andric } 26439d628a0SDimitry Andric // Remove the fake entry we created so we don't have a hanging reference 26539d628a0SDimitry Andric // after we delete this node. 26639d628a0SDimitry Andric Builder.removeValue(Tmp); 26739d628a0SDimitry Andric delete Tmp; 26839d628a0SDimitry Andric Tmp = nullptr; 26939d628a0SDimitry Andric 27039d628a0SDimitry Andric // Search for the call node 27139d628a0SDimitry Andric // The following code is essentially reverse engineering X86's 27239d628a0SDimitry Andric // LowerCallTo. 27339d628a0SDimitry Andric SDNode *CallNode = nullptr; 27439d628a0SDimitry Andric 27539d628a0SDimitry Andric // We just emitted a call, so it should be last thing generated 27639d628a0SDimitry Andric SDValue Chain = Builder.DAG.getRoot(); 27739d628a0SDimitry Andric 27839d628a0SDimitry Andric // Find closest CALLSEQ_END walking back through lowered nodes if needed 27939d628a0SDimitry Andric SDNode *CallEnd = Chain.getNode(); 28039d628a0SDimitry Andric int Sanity = 0; 28139d628a0SDimitry Andric while (CallEnd->getOpcode() != ISD::CALLSEQ_END) { 28239d628a0SDimitry Andric CallEnd = CallEnd->getGluedNode(); 28339d628a0SDimitry Andric assert(CallEnd && "Can not find call node"); 28439d628a0SDimitry Andric assert(Sanity < 20 && "should have found call end already"); 28539d628a0SDimitry Andric Sanity++; 28639d628a0SDimitry Andric } 28739d628a0SDimitry Andric assert(CallEnd->getOpcode() == ISD::CALLSEQ_END && 28839d628a0SDimitry Andric "Expected a callseq node."); 28939d628a0SDimitry Andric assert(CallEnd->getGluedNode()); 29039d628a0SDimitry Andric 29139d628a0SDimitry Andric // Step back inside the CALLSEQ 29239d628a0SDimitry Andric CallNode = CallEnd->getGluedNode(); 29339d628a0SDimitry Andric return CallNode; 29439d628a0SDimitry Andric } 29539d628a0SDimitry Andric 29639d628a0SDimitry Andric /// Callect all gc pointers coming into statepoint intrinsic, clean them up, 29739d628a0SDimitry Andric /// and return two arrays: 29839d628a0SDimitry Andric /// Bases - base pointers incoming to this statepoint 29939d628a0SDimitry Andric /// Ptrs - derived pointers incoming to this statepoint 30039d628a0SDimitry Andric /// Relocs - the gc_relocate corresponding to each base/ptr pair 30139d628a0SDimitry Andric /// Elements of this arrays should be in one-to-one correspondence with each 30239d628a0SDimitry Andric /// other i.e Bases[i], Ptrs[i] are from the same gcrelocate call 30339d628a0SDimitry Andric static void 30439d628a0SDimitry Andric getIncomingStatepointGCValues(SmallVectorImpl<const Value *> &Bases, 30539d628a0SDimitry Andric SmallVectorImpl<const Value *> &Ptrs, 30639d628a0SDimitry Andric SmallVectorImpl<const Value *> &Relocs, 30739d628a0SDimitry Andric ImmutableCallSite Statepoint, 30839d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 30939d628a0SDimitry Andric // Search for relocated pointers. Note that working backwards from the 31039d628a0SDimitry Andric // gc_relocates ensures that we only get pairs which are actually relocated 31139d628a0SDimitry Andric // and used after the statepoint. 31239d628a0SDimitry Andric // TODO: This logic should probably become a utility function in Statepoint.h 31339d628a0SDimitry Andric for (const User *U : cast<CallInst>(Statepoint.getInstruction())->users()) { 31439d628a0SDimitry Andric if (!isGCRelocate(U)) { 31539d628a0SDimitry Andric continue; 31639d628a0SDimitry Andric } 31739d628a0SDimitry Andric GCRelocateOperands relocateOpers(U); 31839d628a0SDimitry Andric Relocs.push_back(cast<Value>(U)); 31939d628a0SDimitry Andric Bases.push_back(relocateOpers.basePtr()); 32039d628a0SDimitry Andric Ptrs.push_back(relocateOpers.derivedPtr()); 32139d628a0SDimitry Andric } 32239d628a0SDimitry Andric 32339d628a0SDimitry Andric // Remove any redundant llvm::Values which map to the same SDValue as another 32439d628a0SDimitry Andric // input. Also has the effect of removing duplicates in the original 32539d628a0SDimitry Andric // llvm::Value input list as well. This is a useful optimization for 32639d628a0SDimitry Andric // reducing the size of the StackMap section. It has no other impact. 32739d628a0SDimitry Andric removeDuplicatesGCPtrs(Bases, Ptrs, Relocs, Builder); 32839d628a0SDimitry Andric 32939d628a0SDimitry Andric assert(Bases.size() == Ptrs.size() && Ptrs.size() == Relocs.size()); 33039d628a0SDimitry Andric } 33139d628a0SDimitry Andric 33239d628a0SDimitry Andric /// Spill a value incoming to the statepoint. It might be either part of 33339d628a0SDimitry Andric /// vmstate 33439d628a0SDimitry Andric /// or gcstate. In both cases unconditionally spill it on the stack unless it 33539d628a0SDimitry Andric /// is a null constant. Return pair with first element being frame index 33639d628a0SDimitry Andric /// containing saved value and second element with outgoing chain from the 33739d628a0SDimitry Andric /// emitted store 33839d628a0SDimitry Andric static std::pair<SDValue, SDValue> 33939d628a0SDimitry Andric spillIncomingStatepointValue(SDValue Incoming, SDValue Chain, 34039d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 34139d628a0SDimitry Andric SDValue Loc = Builder.StatepointLowering.getLocation(Incoming); 34239d628a0SDimitry Andric 34339d628a0SDimitry Andric // Emit new store if we didn't do it for this ptr before 34439d628a0SDimitry Andric if (!Loc.getNode()) { 34539d628a0SDimitry Andric Loc = Builder.StatepointLowering.allocateStackSlot(Incoming.getValueType(), 34639d628a0SDimitry Andric Builder); 34739d628a0SDimitry Andric assert(isa<FrameIndexSDNode>(Loc)); 34839d628a0SDimitry Andric int Index = cast<FrameIndexSDNode>(Loc)->getIndex(); 34939d628a0SDimitry Andric // We use TargetFrameIndex so that isel will not select it into LEA 35039d628a0SDimitry Andric Loc = Builder.DAG.getTargetFrameIndex(Index, Incoming.getValueType()); 35139d628a0SDimitry Andric 35239d628a0SDimitry Andric // TODO: We can create TokenFactor node instead of 35339d628a0SDimitry Andric // chaining stores one after another, this may allow 35439d628a0SDimitry Andric // a bit more optimal scheduling for them 35539d628a0SDimitry Andric Chain = Builder.DAG.getStore(Chain, Builder.getCurSDLoc(), Incoming, Loc, 35639d628a0SDimitry Andric MachinePointerInfo::getFixedStack(Index), 35739d628a0SDimitry Andric false, false, 0); 35839d628a0SDimitry Andric 35939d628a0SDimitry Andric Builder.StatepointLowering.setLocation(Incoming, Loc); 36039d628a0SDimitry Andric } 36139d628a0SDimitry Andric 36239d628a0SDimitry Andric assert(Loc.getNode()); 36339d628a0SDimitry Andric return std::make_pair(Loc, Chain); 36439d628a0SDimitry Andric } 36539d628a0SDimitry Andric 36639d628a0SDimitry Andric /// Lower a single value incoming to a statepoint node. This value can be 36739d628a0SDimitry Andric /// either a deopt value or a gc value, the handling is the same. We special 36839d628a0SDimitry Andric /// case constants and allocas, then fall back to spilling if required. 36939d628a0SDimitry Andric static void lowerIncomingStatepointValue(SDValue Incoming, 37039d628a0SDimitry Andric SmallVectorImpl<SDValue> &Ops, 37139d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 37239d628a0SDimitry Andric SDValue Chain = Builder.getRoot(); 37339d628a0SDimitry Andric 37439d628a0SDimitry Andric if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Incoming)) { 37539d628a0SDimitry Andric // If the original value was a constant, make sure it gets recorded as 37639d628a0SDimitry Andric // such in the stackmap. This is required so that the consumer can 37739d628a0SDimitry Andric // parse any internal format to the deopt state. It also handles null 37839d628a0SDimitry Andric // pointers and other constant pointers in GC states 37939d628a0SDimitry Andric Ops.push_back( 38039d628a0SDimitry Andric Builder.DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64)); 38139d628a0SDimitry Andric Ops.push_back(Builder.DAG.getTargetConstant(C->getSExtValue(), MVT::i64)); 38239d628a0SDimitry Andric } else if (FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Incoming)) { 38339d628a0SDimitry Andric // This handles allocas as arguments to the statepoint 38439d628a0SDimitry Andric const TargetLowering &TLI = Builder.DAG.getTargetLoweringInfo(); 38539d628a0SDimitry Andric Ops.push_back( 38639d628a0SDimitry Andric Builder.DAG.getTargetFrameIndex(FI->getIndex(), TLI.getPointerTy())); 38739d628a0SDimitry Andric } else { 38839d628a0SDimitry Andric // Otherwise, locate a spill slot and explicitly spill it so it 38939d628a0SDimitry Andric // can be found by the runtime later. We currently do not support 39039d628a0SDimitry Andric // tracking values through callee saved registers to their eventual 39139d628a0SDimitry Andric // spill location. This would be a useful optimization, but would 39239d628a0SDimitry Andric // need to be optional since it requires a lot of complexity on the 39339d628a0SDimitry Andric // runtime side which not all would support. 39439d628a0SDimitry Andric std::pair<SDValue, SDValue> Res = 39539d628a0SDimitry Andric spillIncomingStatepointValue(Incoming, Chain, Builder); 39639d628a0SDimitry Andric Ops.push_back(Res.first); 39739d628a0SDimitry Andric Chain = Res.second; 39839d628a0SDimitry Andric } 39939d628a0SDimitry Andric 40039d628a0SDimitry Andric Builder.DAG.setRoot(Chain); 40139d628a0SDimitry Andric } 40239d628a0SDimitry Andric 40339d628a0SDimitry Andric /// Lower deopt state and gc pointer arguments of the statepoint. The actual 40439d628a0SDimitry Andric /// lowering is described in lowerIncomingStatepointValue. This function is 40539d628a0SDimitry Andric /// responsible for lowering everything in the right position and playing some 40639d628a0SDimitry Andric /// tricks to avoid redundant stack manipulation where possible. On 40739d628a0SDimitry Andric /// completion, 'Ops' will contain ready to use operands for machine code 40839d628a0SDimitry Andric /// statepoint. The chain nodes will have already been created and the DAG root 40939d628a0SDimitry Andric /// will be set to the last value spilled (if any were). 41039d628a0SDimitry Andric static void lowerStatepointMetaArgs(SmallVectorImpl<SDValue> &Ops, 41139d628a0SDimitry Andric ImmutableStatepoint Statepoint, 41239d628a0SDimitry Andric SelectionDAGBuilder &Builder) { 41339d628a0SDimitry Andric 41439d628a0SDimitry Andric // Lower the deopt and gc arguments for this statepoint. Layout will 41539d628a0SDimitry Andric // be: deopt argument length, deopt arguments.., gc arguments... 41639d628a0SDimitry Andric 41739d628a0SDimitry Andric SmallVector<const Value *, 64> Bases, Ptrs, Relocations; 41839d628a0SDimitry Andric getIncomingStatepointGCValues(Bases, Ptrs, Relocations, 41939d628a0SDimitry Andric Statepoint.getCallSite(), Builder); 42039d628a0SDimitry Andric 42139d628a0SDimitry Andric #ifndef NDEBUG 42239d628a0SDimitry Andric // Check that each of the gc pointer and bases we've gotten out of the 42339d628a0SDimitry Andric // safepoint is something the strategy thinks might be a pointer into the GC 42439d628a0SDimitry Andric // heap. This is basically just here to help catch errors during statepoint 42539d628a0SDimitry Andric // insertion. TODO: This should actually be in the Verifier, but we can't get 42639d628a0SDimitry Andric // to the GCStrategy from there (yet). 42739d628a0SDimitry Andric if (Builder.GFI) { 42839d628a0SDimitry Andric GCStrategy &S = Builder.GFI->getStrategy(); 42939d628a0SDimitry Andric for (const Value *V : Bases) { 43039d628a0SDimitry Andric auto Opt = S.isGCManagedPointer(V); 43139d628a0SDimitry Andric if (Opt.hasValue()) { 43239d628a0SDimitry Andric assert(Opt.getValue() && 43339d628a0SDimitry Andric "non gc managed base pointer found in statepoint"); 43439d628a0SDimitry Andric } 43539d628a0SDimitry Andric } 43639d628a0SDimitry Andric for (const Value *V : Ptrs) { 43739d628a0SDimitry Andric auto Opt = S.isGCManagedPointer(V); 43839d628a0SDimitry Andric if (Opt.hasValue()) { 43939d628a0SDimitry Andric assert(Opt.getValue() && 44039d628a0SDimitry Andric "non gc managed derived pointer found in statepoint"); 44139d628a0SDimitry Andric } 44239d628a0SDimitry Andric } 44339d628a0SDimitry Andric for (const Value *V : Relocations) { 44439d628a0SDimitry Andric auto Opt = S.isGCManagedPointer(V); 44539d628a0SDimitry Andric if (Opt.hasValue()) { 44639d628a0SDimitry Andric assert(Opt.getValue() && "non gc managed pointer relocated"); 44739d628a0SDimitry Andric } 44839d628a0SDimitry Andric } 44939d628a0SDimitry Andric } 45039d628a0SDimitry Andric #endif 45139d628a0SDimitry Andric 45239d628a0SDimitry Andric 45339d628a0SDimitry Andric 45439d628a0SDimitry Andric // Before we actually start lowering (and allocating spill slots for values), 45539d628a0SDimitry Andric // reserve any stack slots which we judge to be profitable to reuse for a 45639d628a0SDimitry Andric // particular value. This is purely an optimization over the code below and 45739d628a0SDimitry Andric // doesn't change semantics at all. It is important for performance that we 45839d628a0SDimitry Andric // reserve slots for both deopt and gc values before lowering either. 45939d628a0SDimitry Andric for (auto I = Statepoint.vm_state_begin() + 1, E = Statepoint.vm_state_end(); 46039d628a0SDimitry Andric I != E; ++I) { 46139d628a0SDimitry Andric Value *V = *I; 46239d628a0SDimitry Andric SDValue Incoming = Builder.getValue(V); 46339d628a0SDimitry Andric reservePreviousStackSlotForValue(Incoming, Builder); 46439d628a0SDimitry Andric } 46539d628a0SDimitry Andric for (unsigned i = 0; i < Bases.size() * 2; ++i) { 46639d628a0SDimitry Andric // Even elements will contain base, odd elements - derived ptr 46739d628a0SDimitry Andric const Value *V = i % 2 ? Bases[i / 2] : Ptrs[i / 2]; 46839d628a0SDimitry Andric SDValue Incoming = Builder.getValue(V); 46939d628a0SDimitry Andric reservePreviousStackSlotForValue(Incoming, Builder); 47039d628a0SDimitry Andric } 47139d628a0SDimitry Andric 47239d628a0SDimitry Andric // First, prefix the list with the number of unique values to be 47339d628a0SDimitry Andric // lowered. Note that this is the number of *Values* not the 47439d628a0SDimitry Andric // number of SDValues required to lower them. 47539d628a0SDimitry Andric const int NumVMSArgs = Statepoint.numTotalVMSArgs(); 47639d628a0SDimitry Andric Ops.push_back( 47739d628a0SDimitry Andric Builder.DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64)); 47839d628a0SDimitry Andric Ops.push_back(Builder.DAG.getTargetConstant(NumVMSArgs, MVT::i64)); 47939d628a0SDimitry Andric 48039d628a0SDimitry Andric assert(NumVMSArgs + 1 == std::distance(Statepoint.vm_state_begin(), 48139d628a0SDimitry Andric Statepoint.vm_state_end())); 48239d628a0SDimitry Andric 48339d628a0SDimitry Andric // The vm state arguments are lowered in an opaque manner. We do 48439d628a0SDimitry Andric // not know what type of values are contained within. We skip the 48539d628a0SDimitry Andric // first one since that happens to be the total number we lowered 48639d628a0SDimitry Andric // explicitly just above. We could have left it in the loop and 48739d628a0SDimitry Andric // not done it explicitly, but it's far easier to understand this 48839d628a0SDimitry Andric // way. 48939d628a0SDimitry Andric for (auto I = Statepoint.vm_state_begin() + 1, E = Statepoint.vm_state_end(); 49039d628a0SDimitry Andric I != E; ++I) { 49139d628a0SDimitry Andric const Value *V = *I; 49239d628a0SDimitry Andric SDValue Incoming = Builder.getValue(V); 49339d628a0SDimitry Andric lowerIncomingStatepointValue(Incoming, Ops, Builder); 49439d628a0SDimitry Andric } 49539d628a0SDimitry Andric 49639d628a0SDimitry Andric // Finally, go ahead and lower all the gc arguments. There's no prefixed 49739d628a0SDimitry Andric // length for this one. After lowering, we'll have the base and pointer 49839d628a0SDimitry Andric // arrays interwoven with each (lowered) base pointer immediately followed by 49939d628a0SDimitry Andric // it's (lowered) derived pointer. i.e 50039d628a0SDimitry Andric // (base[0], ptr[0], base[1], ptr[1], ...) 50139d628a0SDimitry Andric for (unsigned i = 0; i < Bases.size() * 2; ++i) { 50239d628a0SDimitry Andric // Even elements will contain base, odd elements - derived ptr 50339d628a0SDimitry Andric const Value *V = i % 2 ? Bases[i / 2] : Ptrs[i / 2]; 50439d628a0SDimitry Andric SDValue Incoming = Builder.getValue(V); 50539d628a0SDimitry Andric lowerIncomingStatepointValue(Incoming, Ops, Builder); 50639d628a0SDimitry Andric } 50739d628a0SDimitry Andric } 50839d628a0SDimitry Andric void SelectionDAGBuilder::visitStatepoint(const CallInst &CI) { 50939d628a0SDimitry Andric // The basic scheme here is that information about both the original call and 51039d628a0SDimitry Andric // the safepoint is encoded in the CallInst. We create a temporary call and 51139d628a0SDimitry Andric // lower it, then reverse engineer the calling sequence. 51239d628a0SDimitry Andric 51339d628a0SDimitry Andric // Check some preconditions for sanity 51439d628a0SDimitry Andric assert(isStatepoint(&CI) && 51539d628a0SDimitry Andric "function called must be the statepoint function"); 51639d628a0SDimitry Andric NumOfStatepoints++; 51739d628a0SDimitry Andric // Clear state 51839d628a0SDimitry Andric StatepointLowering.startNewStatepoint(*this); 51939d628a0SDimitry Andric 52039d628a0SDimitry Andric #ifndef NDEBUG 52139d628a0SDimitry Andric // Consistency check 52239d628a0SDimitry Andric for (const User *U : CI.users()) { 52339d628a0SDimitry Andric const CallInst *Call = cast<CallInst>(U); 52439d628a0SDimitry Andric if (isGCRelocate(Call)) 52539d628a0SDimitry Andric StatepointLowering.scheduleRelocCall(*Call); 52639d628a0SDimitry Andric } 52739d628a0SDimitry Andric #endif 52839d628a0SDimitry Andric 52939d628a0SDimitry Andric ImmutableStatepoint ISP(&CI); 53039d628a0SDimitry Andric #ifndef NDEBUG 53139d628a0SDimitry Andric // If this is a malformed statepoint, report it early to simplify debugging. 53239d628a0SDimitry Andric // This should catch any IR level mistake that's made when constructing or 53339d628a0SDimitry Andric // transforming statepoints. 53439d628a0SDimitry Andric ISP.verify(); 53539d628a0SDimitry Andric 53639d628a0SDimitry Andric // Check that the associated GCStrategy expects to encounter statepoints. 53739d628a0SDimitry Andric // TODO: This if should become an assert. For now, we allow the GCStrategy 53839d628a0SDimitry Andric // to be optional for backwards compatibility. This will only last a short 53939d628a0SDimitry Andric // period (i.e. a couple of weeks). 54039d628a0SDimitry Andric if (GFI) { 54139d628a0SDimitry Andric assert(GFI->getStrategy().useStatepoints() && 54239d628a0SDimitry Andric "GCStrategy does not expect to encounter statepoints"); 54339d628a0SDimitry Andric } 54439d628a0SDimitry Andric #endif 54539d628a0SDimitry Andric 54639d628a0SDimitry Andric 54739d628a0SDimitry Andric // Lower statepoint vmstate and gcstate arguments 54839d628a0SDimitry Andric SmallVector<SDValue, 10> LoweredArgs; 54939d628a0SDimitry Andric lowerStatepointMetaArgs(LoweredArgs, ISP, *this); 55039d628a0SDimitry Andric 55139d628a0SDimitry Andric // Get call node, we will replace it later with statepoint 55239d628a0SDimitry Andric SDNode *CallNode = lowerCallFromStatepoint(CI, *this); 55339d628a0SDimitry Andric 55439d628a0SDimitry Andric // Construct the actual STATEPOINT node with all the appropriate arguments 55539d628a0SDimitry Andric // and return values. 55639d628a0SDimitry Andric 55739d628a0SDimitry Andric // TODO: Currently, all of these operands are being marked as read/write in 55839d628a0SDimitry Andric // PrologEpilougeInserter.cpp, we should special case the VMState arguments 55939d628a0SDimitry Andric // and flags to be read-only. 56039d628a0SDimitry Andric SmallVector<SDValue, 40> Ops; 56139d628a0SDimitry Andric 56239d628a0SDimitry Andric // Calculate and push starting position of vmstate arguments 56339d628a0SDimitry Andric // Call Node: Chain, Target, {Args}, RegMask, [Glue] 56439d628a0SDimitry Andric SDValue Glue; 56539d628a0SDimitry Andric if (CallNode->getGluedNode()) { 56639d628a0SDimitry Andric // Glue is always last operand 56739d628a0SDimitry Andric Glue = CallNode->getOperand(CallNode->getNumOperands() - 1); 56839d628a0SDimitry Andric } 56939d628a0SDimitry Andric // Get number of arguments incoming directly into call node 57039d628a0SDimitry Andric unsigned NumCallRegArgs = 57139d628a0SDimitry Andric CallNode->getNumOperands() - (Glue.getNode() ? 4 : 3); 57239d628a0SDimitry Andric Ops.push_back(DAG.getTargetConstant(NumCallRegArgs, MVT::i32)); 57339d628a0SDimitry Andric 57439d628a0SDimitry Andric // Add call target 57539d628a0SDimitry Andric SDValue CallTarget = SDValue(CallNode->getOperand(1).getNode(), 0); 57639d628a0SDimitry Andric Ops.push_back(CallTarget); 57739d628a0SDimitry Andric 57839d628a0SDimitry Andric // Add call arguments 57939d628a0SDimitry Andric // Get position of register mask in the call 58039d628a0SDimitry Andric SDNode::op_iterator RegMaskIt; 58139d628a0SDimitry Andric if (Glue.getNode()) 58239d628a0SDimitry Andric RegMaskIt = CallNode->op_end() - 2; 58339d628a0SDimitry Andric else 58439d628a0SDimitry Andric RegMaskIt = CallNode->op_end() - 1; 58539d628a0SDimitry Andric Ops.insert(Ops.end(), CallNode->op_begin() + 2, RegMaskIt); 58639d628a0SDimitry Andric 58739d628a0SDimitry Andric // Add a leading constant argument with the Flags and the calling convention 58839d628a0SDimitry Andric // masked together 58939d628a0SDimitry Andric CallingConv::ID CallConv = CI.getCallingConv(); 59039d628a0SDimitry Andric int Flags = dyn_cast<ConstantInt>(CI.getArgOperand(2))->getZExtValue(); 59139d628a0SDimitry Andric assert(Flags == 0 && "not expected to be used"); 59239d628a0SDimitry Andric Ops.push_back(DAG.getTargetConstant(StackMaps::ConstantOp, MVT::i64)); 59339d628a0SDimitry Andric Ops.push_back( 59439d628a0SDimitry Andric DAG.getTargetConstant(Flags | ((unsigned)CallConv << 1), MVT::i64)); 59539d628a0SDimitry Andric 59639d628a0SDimitry Andric // Insert all vmstate and gcstate arguments 59739d628a0SDimitry Andric Ops.insert(Ops.end(), LoweredArgs.begin(), LoweredArgs.end()); 59839d628a0SDimitry Andric 59939d628a0SDimitry Andric // Add register mask from call node 60039d628a0SDimitry Andric Ops.push_back(*RegMaskIt); 60139d628a0SDimitry Andric 60239d628a0SDimitry Andric // Add chain 60339d628a0SDimitry Andric Ops.push_back(CallNode->getOperand(0)); 60439d628a0SDimitry Andric 60539d628a0SDimitry Andric // Same for the glue, but we add it only if original call had it 60639d628a0SDimitry Andric if (Glue.getNode()) 60739d628a0SDimitry Andric Ops.push_back(Glue); 60839d628a0SDimitry Andric 60939d628a0SDimitry Andric // Compute return values 61039d628a0SDimitry Andric SmallVector<EVT, 21> ValueVTs; 61139d628a0SDimitry Andric ValueVTs.push_back(MVT::Other); 61239d628a0SDimitry Andric ValueVTs.push_back(MVT::Glue); // provide a glue output since we consume one 61339d628a0SDimitry Andric // as input. This allows someone else to chain 61439d628a0SDimitry Andric // off us as needed. 61539d628a0SDimitry Andric SDVTList NodeTys = DAG.getVTList(ValueVTs); 61639d628a0SDimitry Andric 61739d628a0SDimitry Andric SDNode *StatepointMCNode = DAG.getMachineNode(TargetOpcode::STATEPOINT, 61839d628a0SDimitry Andric getCurSDLoc(), NodeTys, Ops); 61939d628a0SDimitry Andric 62039d628a0SDimitry Andric // Replace original call 62139d628a0SDimitry Andric DAG.ReplaceAllUsesWith(CallNode, StatepointMCNode); // This may update Root 62239d628a0SDimitry Andric // Remove originall call node 62339d628a0SDimitry Andric DAG.DeleteNode(CallNode); 62439d628a0SDimitry Andric 62539d628a0SDimitry Andric // DON'T set the root - under the assumption that it's already set past the 62639d628a0SDimitry Andric // inserted node we created. 62739d628a0SDimitry Andric 62839d628a0SDimitry Andric // TODO: A better future implementation would be to emit a single variable 62939d628a0SDimitry Andric // argument, variable return value STATEPOINT node here and then hookup the 63039d628a0SDimitry Andric // return value of each gc.relocate to the respective output of the 63139d628a0SDimitry Andric // previously emitted STATEPOINT value. Unfortunately, this doesn't appear 63239d628a0SDimitry Andric // to actually be possible today. 63339d628a0SDimitry Andric } 63439d628a0SDimitry Andric 63539d628a0SDimitry Andric void SelectionDAGBuilder::visitGCResult(const CallInst &CI) { 63639d628a0SDimitry Andric // The result value of the gc_result is simply the result of the actual 63739d628a0SDimitry Andric // call. We've already emitted this, so just grab the value. 63839d628a0SDimitry Andric Instruction *I = cast<Instruction>(CI.getArgOperand(0)); 63939d628a0SDimitry Andric assert(isStatepoint(I) && 64039d628a0SDimitry Andric "first argument must be a statepoint token"); 64139d628a0SDimitry Andric 64239d628a0SDimitry Andric setValue(&CI, getValue(I)); 64339d628a0SDimitry Andric } 64439d628a0SDimitry Andric 64539d628a0SDimitry Andric void SelectionDAGBuilder::visitGCRelocate(const CallInst &CI) { 64639d628a0SDimitry Andric #ifndef NDEBUG 64739d628a0SDimitry Andric // Consistency check 64839d628a0SDimitry Andric StatepointLowering.relocCallVisited(CI); 64939d628a0SDimitry Andric #endif 65039d628a0SDimitry Andric 65139d628a0SDimitry Andric GCRelocateOperands relocateOpers(&CI); 65239d628a0SDimitry Andric SDValue SD = getValue(relocateOpers.derivedPtr()); 65339d628a0SDimitry Andric 65439d628a0SDimitry Andric if (isa<ConstantSDNode>(SD) || isa<FrameIndexSDNode>(SD)) { 65539d628a0SDimitry Andric // We didn't need to spill these special cases (constants and allocas). 65639d628a0SDimitry Andric // See the handling in spillIncomingValueForStatepoint for detail. 65739d628a0SDimitry Andric setValue(&CI, SD); 65839d628a0SDimitry Andric return; 65939d628a0SDimitry Andric } 66039d628a0SDimitry Andric 66139d628a0SDimitry Andric SDValue Loc = StatepointLowering.getRelocLocation(SD); 66239d628a0SDimitry Andric // Emit new load if we did not emit it before 66339d628a0SDimitry Andric if (!Loc.getNode()) { 66439d628a0SDimitry Andric SDValue SpillSlot = StatepointLowering.getLocation(SD); 66539d628a0SDimitry Andric int FI = cast<FrameIndexSDNode>(SpillSlot)->getIndex(); 66639d628a0SDimitry Andric 66739d628a0SDimitry Andric // Be conservative: flush all pending loads 66839d628a0SDimitry Andric // TODO: Probably we can be less restrictive on this, 66939d628a0SDimitry Andric // it may allow more scheduling opprtunities 67039d628a0SDimitry Andric SDValue Chain = getRoot(); 67139d628a0SDimitry Andric 67239d628a0SDimitry Andric Loc = DAG.getLoad(SpillSlot.getValueType(), getCurSDLoc(), Chain, 67339d628a0SDimitry Andric SpillSlot, MachinePointerInfo::getFixedStack(FI), false, 67439d628a0SDimitry Andric false, false, 0); 67539d628a0SDimitry Andric 67639d628a0SDimitry Andric StatepointLowering.setRelocLocation(SD, Loc); 67739d628a0SDimitry Andric 67839d628a0SDimitry Andric // Again, be conservative, don't emit pending loads 67939d628a0SDimitry Andric DAG.setRoot(Loc.getValue(1)); 68039d628a0SDimitry Andric } 68139d628a0SDimitry Andric 68239d628a0SDimitry Andric assert(Loc.getNode()); 68339d628a0SDimitry Andric setValue(&CI, Loc); 68439d628a0SDimitry Andric } 685