109467b48Spatrick //===- StatepointLowering.h - SDAGBuilder's statepoint code ---*- C++ -*---===// 209467b48Spatrick // 309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 609467b48Spatrick // 709467b48Spatrick //===----------------------------------------------------------------------===// 809467b48Spatrick // 909467b48Spatrick // This file includes support code use by SelectionDAGBuilder when lowering a 1009467b48Spatrick // statepoint sequence in SelectionDAG IR. 1109467b48Spatrick // 1209467b48Spatrick //===----------------------------------------------------------------------===// 1309467b48Spatrick 1409467b48Spatrick #ifndef LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 1509467b48Spatrick #define LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 1609467b48Spatrick 1709467b48Spatrick #include "llvm/ADT/DenseMap.h" 1809467b48Spatrick #include "llvm/ADT/SmallBitVector.h" 1909467b48Spatrick #include "llvm/ADT/SmallVector.h" 2009467b48Spatrick #include "llvm/CodeGen/SelectionDAGNodes.h" 21*73471bf0Spatrick #include "llvm/IR/IntrinsicInst.h" 2209467b48Spatrick #include <cassert> 2309467b48Spatrick 2409467b48Spatrick namespace llvm { 2509467b48Spatrick 2609467b48Spatrick class SelectionDAGBuilder; 2709467b48Spatrick 2809467b48Spatrick /// This class tracks both per-statepoint and per-selectiondag information. 2909467b48Spatrick /// For each statepoint it tracks locations of it's gc valuess (incoming and 3009467b48Spatrick /// relocated) and list of gcreloc calls scheduled for visiting (this is 3109467b48Spatrick /// used for a debug mode consistency check only). The spill slot tracking 3209467b48Spatrick /// works in concert with information in FunctionLoweringInfo. 3309467b48Spatrick class StatepointLoweringState { 3409467b48Spatrick public: 3509467b48Spatrick StatepointLoweringState() = default; 3609467b48Spatrick 3709467b48Spatrick /// Reset all state tracking for a newly encountered safepoint. Also 3809467b48Spatrick /// performs some consistency checking. 3909467b48Spatrick void startNewStatepoint(SelectionDAGBuilder &Builder); 4009467b48Spatrick 4109467b48Spatrick /// Clear the memory usage of this object. This is called from 4209467b48Spatrick /// SelectionDAGBuilder::clear. We require this is never called in the 4309467b48Spatrick /// midst of processing a statepoint sequence. 4409467b48Spatrick void clear(); 4509467b48Spatrick 4609467b48Spatrick /// Returns the spill location of a value incoming to the current 4709467b48Spatrick /// statepoint. Will return SDValue() if this value hasn't been 4809467b48Spatrick /// spilled. Otherwise, the value has already been spilled and no 4909467b48Spatrick /// further action is required by the caller. getLocation(SDValue Val)5009467b48Spatrick SDValue getLocation(SDValue Val) { 5109467b48Spatrick auto I = Locations.find(Val); 5209467b48Spatrick if (I == Locations.end()) 5309467b48Spatrick return SDValue(); 5409467b48Spatrick return I->second; 5509467b48Spatrick } 5609467b48Spatrick setLocation(SDValue Val,SDValue Location)5709467b48Spatrick void setLocation(SDValue Val, SDValue Location) { 5809467b48Spatrick assert(!Locations.count(Val) && 5909467b48Spatrick "Trying to allocate already allocated location"); 6009467b48Spatrick Locations[Val] = Location; 6109467b48Spatrick } 6209467b48Spatrick 6309467b48Spatrick /// Record the fact that we expect to encounter a given gc_relocate 6409467b48Spatrick /// before the next statepoint. If we don't see it, we'll report 6509467b48Spatrick /// an assertion. scheduleRelocCall(const GCRelocateInst & RelocCall)66*73471bf0Spatrick void scheduleRelocCall(const GCRelocateInst &RelocCall) { 6709467b48Spatrick // We are not interested in lowering dead instructions. 6809467b48Spatrick if (!RelocCall.use_empty()) 6909467b48Spatrick PendingGCRelocateCalls.push_back(&RelocCall); 7009467b48Spatrick } 7109467b48Spatrick 7209467b48Spatrick /// Remove this gc_relocate from the list we're expecting to see 7309467b48Spatrick /// before the next statepoint. If we weren't expecting to see 7409467b48Spatrick /// it, we'll report an assertion. relocCallVisited(const GCRelocateInst & RelocCall)75*73471bf0Spatrick void relocCallVisited(const GCRelocateInst &RelocCall) { 7609467b48Spatrick // We are not interested in lowering dead instructions. 7709467b48Spatrick if (RelocCall.use_empty()) 7809467b48Spatrick return; 7909467b48Spatrick auto I = llvm::find(PendingGCRelocateCalls, &RelocCall); 8009467b48Spatrick assert(I != PendingGCRelocateCalls.end() && 8109467b48Spatrick "Visited unexpected gcrelocate call"); 8209467b48Spatrick PendingGCRelocateCalls.erase(I); 8309467b48Spatrick } 8409467b48Spatrick 8509467b48Spatrick // TODO: Should add consistency tracking to ensure we encounter 8609467b48Spatrick // expected gc_result calls too. 8709467b48Spatrick 8809467b48Spatrick /// Get a stack slot we can use to store an value of type ValueType. This 8909467b48Spatrick /// will hopefully be a recylced slot from another statepoint. 9009467b48Spatrick SDValue allocateStackSlot(EVT ValueType, SelectionDAGBuilder &Builder); 9109467b48Spatrick reserveStackSlot(int Offset)9209467b48Spatrick void reserveStackSlot(int Offset) { 9309467b48Spatrick assert(Offset >= 0 && Offset < (int)AllocatedStackSlots.size() && 9409467b48Spatrick "out of bounds"); 9509467b48Spatrick assert(!AllocatedStackSlots.test(Offset) && "already reserved!"); 9609467b48Spatrick assert(NextSlotToAllocate <= (unsigned)Offset && "consistency!"); 9709467b48Spatrick AllocatedStackSlots.set(Offset); 9809467b48Spatrick } 9909467b48Spatrick isStackSlotAllocated(int Offset)10009467b48Spatrick bool isStackSlotAllocated(int Offset) { 10109467b48Spatrick assert(Offset >= 0 && Offset < (int)AllocatedStackSlots.size() && 10209467b48Spatrick "out of bounds"); 10309467b48Spatrick return AllocatedStackSlots.test(Offset); 10409467b48Spatrick } 10509467b48Spatrick 10609467b48Spatrick private: 10709467b48Spatrick /// Maps pre-relocation value (gc pointer directly incoming into statepoint) 10809467b48Spatrick /// into it's location (currently only stack slots) 10909467b48Spatrick DenseMap<SDValue, SDValue> Locations; 11009467b48Spatrick 11109467b48Spatrick /// A boolean indicator for each slot listed in the FunctionInfo as to 11209467b48Spatrick /// whether it has been used in the current statepoint. Since we try to 11309467b48Spatrick /// preserve stack slots across safepoints, there can be gaps in which 11409467b48Spatrick /// slots have been allocated. 11509467b48Spatrick SmallBitVector AllocatedStackSlots; 11609467b48Spatrick 11709467b48Spatrick /// Points just beyond the last slot known to have been allocated 11809467b48Spatrick unsigned NextSlotToAllocate = 0; 11909467b48Spatrick 12009467b48Spatrick /// Keep track of pending gcrelocate calls for consistency check 121*73471bf0Spatrick SmallVector<const GCRelocateInst *, 10> PendingGCRelocateCalls; 12209467b48Spatrick }; 12309467b48Spatrick 12409467b48Spatrick } // end namespace llvm 12509467b48Spatrick 12609467b48Spatrick #endif // LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 127