1*09467b48Spatrick //===- StatepointLowering.h - SDAGBuilder's statepoint code ---*- C++ -*---===// 2*09467b48Spatrick // 3*09467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*09467b48Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*09467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*09467b48Spatrick // 7*09467b48Spatrick //===----------------------------------------------------------------------===// 8*09467b48Spatrick // 9*09467b48Spatrick // This file includes support code use by SelectionDAGBuilder when lowering a 10*09467b48Spatrick // statepoint sequence in SelectionDAG IR. 11*09467b48Spatrick // 12*09467b48Spatrick //===----------------------------------------------------------------------===// 13*09467b48Spatrick 14*09467b48Spatrick #ifndef LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 15*09467b48Spatrick #define LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 16*09467b48Spatrick 17*09467b48Spatrick #include "llvm/ADT/DenseMap.h" 18*09467b48Spatrick #include "llvm/ADT/STLExtras.h" 19*09467b48Spatrick #include "llvm/ADT/SmallBitVector.h" 20*09467b48Spatrick #include "llvm/ADT/SmallVector.h" 21*09467b48Spatrick #include "llvm/CodeGen/SelectionDAGNodes.h" 22*09467b48Spatrick #include "llvm/CodeGen/ValueTypes.h" 23*09467b48Spatrick #include <cassert> 24*09467b48Spatrick 25*09467b48Spatrick namespace llvm { 26*09467b48Spatrick 27*09467b48Spatrick class CallInst; 28*09467b48Spatrick class SelectionDAGBuilder; 29*09467b48Spatrick 30*09467b48Spatrick /// This class tracks both per-statepoint and per-selectiondag information. 31*09467b48Spatrick /// For each statepoint it tracks locations of it's gc valuess (incoming and 32*09467b48Spatrick /// relocated) and list of gcreloc calls scheduled for visiting (this is 33*09467b48Spatrick /// used for a debug mode consistency check only). The spill slot tracking 34*09467b48Spatrick /// works in concert with information in FunctionLoweringInfo. 35*09467b48Spatrick class StatepointLoweringState { 36*09467b48Spatrick public: 37*09467b48Spatrick StatepointLoweringState() = default; 38*09467b48Spatrick 39*09467b48Spatrick /// Reset all state tracking for a newly encountered safepoint. Also 40*09467b48Spatrick /// performs some consistency checking. 41*09467b48Spatrick void startNewStatepoint(SelectionDAGBuilder &Builder); 42*09467b48Spatrick 43*09467b48Spatrick /// Clear the memory usage of this object. This is called from 44*09467b48Spatrick /// SelectionDAGBuilder::clear. We require this is never called in the 45*09467b48Spatrick /// midst of processing a statepoint sequence. 46*09467b48Spatrick void clear(); 47*09467b48Spatrick 48*09467b48Spatrick /// Returns the spill location of a value incoming to the current 49*09467b48Spatrick /// statepoint. Will return SDValue() if this value hasn't been 50*09467b48Spatrick /// spilled. Otherwise, the value has already been spilled and no 51*09467b48Spatrick /// further action is required by the caller. 52*09467b48Spatrick SDValue getLocation(SDValue Val) { 53*09467b48Spatrick auto I = Locations.find(Val); 54*09467b48Spatrick if (I == Locations.end()) 55*09467b48Spatrick return SDValue(); 56*09467b48Spatrick return I->second; 57*09467b48Spatrick } 58*09467b48Spatrick 59*09467b48Spatrick void setLocation(SDValue Val, SDValue Location) { 60*09467b48Spatrick assert(!Locations.count(Val) && 61*09467b48Spatrick "Trying to allocate already allocated location"); 62*09467b48Spatrick Locations[Val] = Location; 63*09467b48Spatrick } 64*09467b48Spatrick 65*09467b48Spatrick /// Record the fact that we expect to encounter a given gc_relocate 66*09467b48Spatrick /// before the next statepoint. If we don't see it, we'll report 67*09467b48Spatrick /// an assertion. 68*09467b48Spatrick void scheduleRelocCall(const CallInst &RelocCall) { 69*09467b48Spatrick // We are not interested in lowering dead instructions. 70*09467b48Spatrick if (!RelocCall.use_empty()) 71*09467b48Spatrick PendingGCRelocateCalls.push_back(&RelocCall); 72*09467b48Spatrick } 73*09467b48Spatrick 74*09467b48Spatrick /// Remove this gc_relocate from the list we're expecting to see 75*09467b48Spatrick /// before the next statepoint. If we weren't expecting to see 76*09467b48Spatrick /// it, we'll report an assertion. 77*09467b48Spatrick void relocCallVisited(const CallInst &RelocCall) { 78*09467b48Spatrick // We are not interested in lowering dead instructions. 79*09467b48Spatrick if (RelocCall.use_empty()) 80*09467b48Spatrick return; 81*09467b48Spatrick auto I = llvm::find(PendingGCRelocateCalls, &RelocCall); 82*09467b48Spatrick assert(I != PendingGCRelocateCalls.end() && 83*09467b48Spatrick "Visited unexpected gcrelocate call"); 84*09467b48Spatrick PendingGCRelocateCalls.erase(I); 85*09467b48Spatrick } 86*09467b48Spatrick 87*09467b48Spatrick // TODO: Should add consistency tracking to ensure we encounter 88*09467b48Spatrick // expected gc_result calls too. 89*09467b48Spatrick 90*09467b48Spatrick /// Get a stack slot we can use to store an value of type ValueType. This 91*09467b48Spatrick /// will hopefully be a recylced slot from another statepoint. 92*09467b48Spatrick SDValue allocateStackSlot(EVT ValueType, SelectionDAGBuilder &Builder); 93*09467b48Spatrick 94*09467b48Spatrick void reserveStackSlot(int Offset) { 95*09467b48Spatrick assert(Offset >= 0 && Offset < (int)AllocatedStackSlots.size() && 96*09467b48Spatrick "out of bounds"); 97*09467b48Spatrick assert(!AllocatedStackSlots.test(Offset) && "already reserved!"); 98*09467b48Spatrick assert(NextSlotToAllocate <= (unsigned)Offset && "consistency!"); 99*09467b48Spatrick AllocatedStackSlots.set(Offset); 100*09467b48Spatrick } 101*09467b48Spatrick 102*09467b48Spatrick bool isStackSlotAllocated(int Offset) { 103*09467b48Spatrick assert(Offset >= 0 && Offset < (int)AllocatedStackSlots.size() && 104*09467b48Spatrick "out of bounds"); 105*09467b48Spatrick return AllocatedStackSlots.test(Offset); 106*09467b48Spatrick } 107*09467b48Spatrick 108*09467b48Spatrick private: 109*09467b48Spatrick /// Maps pre-relocation value (gc pointer directly incoming into statepoint) 110*09467b48Spatrick /// into it's location (currently only stack slots) 111*09467b48Spatrick DenseMap<SDValue, SDValue> Locations; 112*09467b48Spatrick 113*09467b48Spatrick /// A boolean indicator for each slot listed in the FunctionInfo as to 114*09467b48Spatrick /// whether it has been used in the current statepoint. Since we try to 115*09467b48Spatrick /// preserve stack slots across safepoints, there can be gaps in which 116*09467b48Spatrick /// slots have been allocated. 117*09467b48Spatrick SmallBitVector AllocatedStackSlots; 118*09467b48Spatrick 119*09467b48Spatrick /// Points just beyond the last slot known to have been allocated 120*09467b48Spatrick unsigned NextSlotToAllocate = 0; 121*09467b48Spatrick 122*09467b48Spatrick /// Keep track of pending gcrelocate calls for consistency check 123*09467b48Spatrick SmallVector<const CallInst *, 10> PendingGCRelocateCalls; 124*09467b48Spatrick }; 125*09467b48Spatrick 126*09467b48Spatrick } // end namespace llvm 127*09467b48Spatrick 128*09467b48Spatrick #endif // LLVM_LIB_CODEGEN_SELECTIONDAG_STATEPOINTLOWERING_H 129