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