xref: /aosp_15_r20/external/swiftshader/third_party/subzero/src/IceOperand.cpp (revision 03ce13f70fcc45d86ee91b7ee4cab1936a95046e)
1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceOperand.cpp - High-level operand implementation -----===//
2*03ce13f7SAndroid Build Coastguard Worker //
3*03ce13f7SAndroid Build Coastguard Worker //                        The Subzero Code Generator
4*03ce13f7SAndroid Build Coastguard Worker //
5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*03ce13f7SAndroid Build Coastguard Worker //
8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*03ce13f7SAndroid Build Coastguard Worker ///
10*03ce13f7SAndroid Build Coastguard Worker /// \file
11*03ce13f7SAndroid Build Coastguard Worker /// \brief Implements the Operand class and its target-independent subclasses,
12*03ce13f7SAndroid Build Coastguard Worker /// primarily for the methods of the Variable class.
13*03ce13f7SAndroid Build Coastguard Worker ///
14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
15*03ce13f7SAndroid Build Coastguard Worker 
16*03ce13f7SAndroid Build Coastguard Worker #include "IceOperand.h"
17*03ce13f7SAndroid Build Coastguard Worker 
18*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h"
19*03ce13f7SAndroid Build Coastguard Worker #include "IceCfgNode.h"
20*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.h"
21*03ce13f7SAndroid Build Coastguard Worker #include "IceInstVarIter.h"
22*03ce13f7SAndroid Build Coastguard Worker #include "IceMemory.h"
23*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLowering.h" // dumping stack/frame pointer register
24*03ce13f7SAndroid Build Coastguard Worker 
25*03ce13f7SAndroid Build Coastguard Worker namespace Ice {
26*03ce13f7SAndroid Build Coastguard Worker 
initShouldBePooled()27*03ce13f7SAndroid Build Coastguard Worker void Constant::initShouldBePooled() {
28*03ce13f7SAndroid Build Coastguard Worker   ShouldBePooled = TargetLowering::shouldBePooled(this);
29*03ce13f7SAndroid Build Coastguard Worker }
30*03ce13f7SAndroid Build Coastguard Worker 
operator ==(const RelocatableTuple & A,const RelocatableTuple & B)31*03ce13f7SAndroid Build Coastguard Worker bool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
32*03ce13f7SAndroid Build Coastguard Worker   // A and B are the same if:
33*03ce13f7SAndroid Build Coastguard Worker   //   (1) they have the same name; and
34*03ce13f7SAndroid Build Coastguard Worker   //   (2) they have the same offset.
35*03ce13f7SAndroid Build Coastguard Worker   //
36*03ce13f7SAndroid Build Coastguard Worker   // (1) is trivial to check, but (2) requires some care.
37*03ce13f7SAndroid Build Coastguard Worker   //
38*03ce13f7SAndroid Build Coastguard Worker   // For (2):
39*03ce13f7SAndroid Build Coastguard Worker   //  if A and B have known offsets (i.e., no symbolic references), then
40*03ce13f7SAndroid Build Coastguard Worker   //     A == B -> A.Offset == B.Offset.
41*03ce13f7SAndroid Build Coastguard Worker   //  else each element i in A.OffsetExpr[i] must be the same (or have the same
42*03ce13f7SAndroid Build Coastguard Worker   //    value) as B.OffsetExpr[i].
43*03ce13f7SAndroid Build Coastguard Worker   if (A.Name != B.Name) {
44*03ce13f7SAndroid Build Coastguard Worker     return false;
45*03ce13f7SAndroid Build Coastguard Worker   }
46*03ce13f7SAndroid Build Coastguard Worker 
47*03ce13f7SAndroid Build Coastguard Worker   bool BothHaveKnownOffsets = true;
48*03ce13f7SAndroid Build Coastguard Worker   RelocOffsetT OffsetA = A.Offset;
49*03ce13f7SAndroid Build Coastguard Worker   RelocOffsetT OffsetB = B.Offset;
50*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0; i < A.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
51*03ce13f7SAndroid Build Coastguard Worker     BothHaveKnownOffsets = A.OffsetExpr[i]->hasOffset();
52*03ce13f7SAndroid Build Coastguard Worker     if (BothHaveKnownOffsets) {
53*03ce13f7SAndroid Build Coastguard Worker       OffsetA += A.OffsetExpr[i]->getOffset();
54*03ce13f7SAndroid Build Coastguard Worker     }
55*03ce13f7SAndroid Build Coastguard Worker   }
56*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0; i < B.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
57*03ce13f7SAndroid Build Coastguard Worker     BothHaveKnownOffsets = B.OffsetExpr[i]->hasOffset();
58*03ce13f7SAndroid Build Coastguard Worker     if (BothHaveKnownOffsets) {
59*03ce13f7SAndroid Build Coastguard Worker       OffsetB += B.OffsetExpr[i]->getOffset();
60*03ce13f7SAndroid Build Coastguard Worker     }
61*03ce13f7SAndroid Build Coastguard Worker   }
62*03ce13f7SAndroid Build Coastguard Worker   if (BothHaveKnownOffsets) {
63*03ce13f7SAndroid Build Coastguard Worker     // Both have known offsets (i.e., no unresolved symbolic references), so
64*03ce13f7SAndroid Build Coastguard Worker     // A == B -> A.Offset == B.Offset.
65*03ce13f7SAndroid Build Coastguard Worker     return OffsetA == OffsetB;
66*03ce13f7SAndroid Build Coastguard Worker   }
67*03ce13f7SAndroid Build Coastguard Worker 
68*03ce13f7SAndroid Build Coastguard Worker   // Otherwise, A and B are not the same if their OffsetExpr's have different
69*03ce13f7SAndroid Build Coastguard Worker   // sizes.
70*03ce13f7SAndroid Build Coastguard Worker   if (A.OffsetExpr.size() != B.OffsetExpr.size()) {
71*03ce13f7SAndroid Build Coastguard Worker     return false;
72*03ce13f7SAndroid Build Coastguard Worker   }
73*03ce13f7SAndroid Build Coastguard Worker 
74*03ce13f7SAndroid Build Coastguard Worker   // If the OffsetExprs' sizes are the same, then
75*03ce13f7SAndroid Build Coastguard Worker   // for each i in OffsetExprSize:
76*03ce13f7SAndroid Build Coastguard Worker   for (SizeT i = 0; i < A.OffsetExpr.size(); ++i) {
77*03ce13f7SAndroid Build Coastguard Worker     const auto *const RelocOffsetA = A.OffsetExpr[i];
78*03ce13f7SAndroid Build Coastguard Worker     const auto *const RelocOffsetB = B.OffsetExpr[i];
79*03ce13f7SAndroid Build Coastguard Worker     if (RelocOffsetA->hasOffset() && RelocOffsetB->hasOffset()) {
80*03ce13f7SAndroid Build Coastguard Worker       // A.OffsetExpr[i].Offset == B.OffsetExpr[i].Offset iff they are both
81*03ce13f7SAndroid Build Coastguard Worker       // defined;
82*03ce13f7SAndroid Build Coastguard Worker       if (RelocOffsetA->getOffset() != RelocOffsetB->getOffset()) {
83*03ce13f7SAndroid Build Coastguard Worker         return false;
84*03ce13f7SAndroid Build Coastguard Worker       }
85*03ce13f7SAndroid Build Coastguard Worker     } else if (RelocOffsetA != RelocOffsetB) {
86*03ce13f7SAndroid Build Coastguard Worker       // or, if they are undefined, then the RelocOffsets must be the same.
87*03ce13f7SAndroid Build Coastguard Worker       return false;
88*03ce13f7SAndroid Build Coastguard Worker     }
89*03ce13f7SAndroid Build Coastguard Worker   }
90*03ce13f7SAndroid Build Coastguard Worker 
91*03ce13f7SAndroid Build Coastguard Worker   return true;
92*03ce13f7SAndroid Build Coastguard Worker }
93*03ce13f7SAndroid Build Coastguard Worker 
94*03ce13f7SAndroid Build Coastguard Worker RegNumT::BaseType RegNumT::Limit = 0;
95*03ce13f7SAndroid Build Coastguard Worker 
operator <(const RegWeight & A,const RegWeight & B)96*03ce13f7SAndroid Build Coastguard Worker bool operator<(const RegWeight &A, const RegWeight &B) {
97*03ce13f7SAndroid Build Coastguard Worker   return A.getWeight() < B.getWeight();
98*03ce13f7SAndroid Build Coastguard Worker }
operator <=(const RegWeight & A,const RegWeight & B)99*03ce13f7SAndroid Build Coastguard Worker bool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
operator ==(const RegWeight & A,const RegWeight & B)100*03ce13f7SAndroid Build Coastguard Worker bool operator==(const RegWeight &A, const RegWeight &B) {
101*03ce13f7SAndroid Build Coastguard Worker   return !(B < A) && !(A < B);
102*03ce13f7SAndroid Build Coastguard Worker }
103*03ce13f7SAndroid Build Coastguard Worker 
addSegment(InstNumberT Start,InstNumberT End,CfgNode * Node)104*03ce13f7SAndroid Build Coastguard Worker void LiveRange::addSegment(InstNumberT Start, InstNumberT End, CfgNode *Node) {
105*03ce13f7SAndroid Build Coastguard Worker   if (getFlags().getSplitGlobalVars()) {
106*03ce13f7SAndroid Build Coastguard Worker     // Disable merging to make sure a live range 'segment' has a single node.
107*03ce13f7SAndroid Build Coastguard Worker     // Might be possible to enable when the target segment has the same node.
108*03ce13f7SAndroid Build Coastguard Worker     assert(NodeMap.find(Start) == NodeMap.end());
109*03ce13f7SAndroid Build Coastguard Worker     NodeMap[Start] = Node;
110*03ce13f7SAndroid Build Coastguard Worker   } else {
111*03ce13f7SAndroid Build Coastguard Worker     if (!Range.empty()) {
112*03ce13f7SAndroid Build Coastguard Worker       // Check for merge opportunity.
113*03ce13f7SAndroid Build Coastguard Worker       InstNumberT CurrentEnd = Range.back().second;
114*03ce13f7SAndroid Build Coastguard Worker       assert(Start >= CurrentEnd);
115*03ce13f7SAndroid Build Coastguard Worker       if (Start == CurrentEnd) {
116*03ce13f7SAndroid Build Coastguard Worker         Range.back().second = End;
117*03ce13f7SAndroid Build Coastguard Worker         return;
118*03ce13f7SAndroid Build Coastguard Worker       }
119*03ce13f7SAndroid Build Coastguard Worker     }
120*03ce13f7SAndroid Build Coastguard Worker   }
121*03ce13f7SAndroid Build Coastguard Worker   Range.push_back(RangeElementType(Start, End));
122*03ce13f7SAndroid Build Coastguard Worker }
123*03ce13f7SAndroid Build Coastguard Worker 
124*03ce13f7SAndroid Build Coastguard Worker // Returns true if this live range ends before Other's live range starts. This
125*03ce13f7SAndroid Build Coastguard Worker // means that the highest instruction number in this live range is less than or
126*03ce13f7SAndroid Build Coastguard Worker // equal to the lowest instruction number of the Other live range.
endsBefore(const LiveRange & Other) const127*03ce13f7SAndroid Build Coastguard Worker bool LiveRange::endsBefore(const LiveRange &Other) const {
128*03ce13f7SAndroid Build Coastguard Worker   // Neither range should be empty, but let's be graceful.
129*03ce13f7SAndroid Build Coastguard Worker   if (Range.empty() || Other.Range.empty())
130*03ce13f7SAndroid Build Coastguard Worker     return true;
131*03ce13f7SAndroid Build Coastguard Worker   InstNumberT MyEnd = (*Range.rbegin()).second;
132*03ce13f7SAndroid Build Coastguard Worker   InstNumberT OtherStart = (*Other.Range.begin()).first;
133*03ce13f7SAndroid Build Coastguard Worker   return MyEnd <= OtherStart;
134*03ce13f7SAndroid Build Coastguard Worker }
135*03ce13f7SAndroid Build Coastguard Worker 
136*03ce13f7SAndroid Build Coastguard Worker // Returns true if there is any overlap between the two live ranges.
overlaps(const LiveRange & Other,bool UseTrimmed) const137*03ce13f7SAndroid Build Coastguard Worker bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
138*03ce13f7SAndroid Build Coastguard Worker   // Do a two-finger walk through the two sorted lists of segments.
139*03ce13f7SAndroid Build Coastguard Worker   auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
140*03ce13f7SAndroid Build Coastguard Worker        I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
141*03ce13f7SAndroid Build Coastguard Worker   auto E1 = Range.end(), E2 = Other.Range.end();
142*03ce13f7SAndroid Build Coastguard Worker   while (I1 != E1 && I2 != E2) {
143*03ce13f7SAndroid Build Coastguard Worker     if (I1->second <= I2->first) {
144*03ce13f7SAndroid Build Coastguard Worker       ++I1;
145*03ce13f7SAndroid Build Coastguard Worker       continue;
146*03ce13f7SAndroid Build Coastguard Worker     }
147*03ce13f7SAndroid Build Coastguard Worker     if (I2->second <= I1->first) {
148*03ce13f7SAndroid Build Coastguard Worker       ++I2;
149*03ce13f7SAndroid Build Coastguard Worker       continue;
150*03ce13f7SAndroid Build Coastguard Worker     }
151*03ce13f7SAndroid Build Coastguard Worker     return true;
152*03ce13f7SAndroid Build Coastguard Worker   }
153*03ce13f7SAndroid Build Coastguard Worker   return false;
154*03ce13f7SAndroid Build Coastguard Worker }
155*03ce13f7SAndroid Build Coastguard Worker 
overlapsInst(InstNumberT OtherBegin,bool UseTrimmed) const156*03ce13f7SAndroid Build Coastguard Worker bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
157*03ce13f7SAndroid Build Coastguard Worker   bool Result = false;
158*03ce13f7SAndroid Build Coastguard Worker   for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
159*03ce13f7SAndroid Build Coastguard Worker        I != E; ++I) {
160*03ce13f7SAndroid Build Coastguard Worker     if (OtherBegin < I->first) {
161*03ce13f7SAndroid Build Coastguard Worker       Result = false;
162*03ce13f7SAndroid Build Coastguard Worker       break;
163*03ce13f7SAndroid Build Coastguard Worker     }
164*03ce13f7SAndroid Build Coastguard Worker     if (OtherBegin < I->second) {
165*03ce13f7SAndroid Build Coastguard Worker       Result = true;
166*03ce13f7SAndroid Build Coastguard Worker       break;
167*03ce13f7SAndroid Build Coastguard Worker     }
168*03ce13f7SAndroid Build Coastguard Worker   }
169*03ce13f7SAndroid Build Coastguard Worker   // This is an equivalent but less inefficient implementation. It's expensive
170*03ce13f7SAndroid Build Coastguard Worker   // enough that we wouldn't want to run it under any build, but it could be
171*03ce13f7SAndroid Build Coastguard Worker   // enabled if e.g. the LiveRange implementation changes and extra testing is
172*03ce13f7SAndroid Build Coastguard Worker   // needed.
173*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::extraValidation()) {
174*03ce13f7SAndroid Build Coastguard Worker     LiveRange Temp;
175*03ce13f7SAndroid Build Coastguard Worker     Temp.addSegment(OtherBegin, OtherBegin + 1);
176*03ce13f7SAndroid Build Coastguard Worker     bool Validation = overlaps(Temp);
177*03ce13f7SAndroid Build Coastguard Worker     (void)Validation;
178*03ce13f7SAndroid Build Coastguard Worker     assert(Result == Validation);
179*03ce13f7SAndroid Build Coastguard Worker   }
180*03ce13f7SAndroid Build Coastguard Worker   return Result;
181*03ce13f7SAndroid Build Coastguard Worker }
182*03ce13f7SAndroid Build Coastguard Worker 
183*03ce13f7SAndroid Build Coastguard Worker // Returns true if the live range contains the given instruction number. This
184*03ce13f7SAndroid Build Coastguard Worker // is only used for validating the live range calculation. The IsDest argument
185*03ce13f7SAndroid Build Coastguard Worker // indicates whether the Variable being tested is used in the Dest position (as
186*03ce13f7SAndroid Build Coastguard Worker // opposed to a Src position).
containsValue(InstNumberT Value,bool IsDest) const187*03ce13f7SAndroid Build Coastguard Worker bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
188*03ce13f7SAndroid Build Coastguard Worker   for (const RangeElementType &I : Range) {
189*03ce13f7SAndroid Build Coastguard Worker     if (I.first <= Value &&
190*03ce13f7SAndroid Build Coastguard Worker         (Value < I.second || (!IsDest && Value == I.second)))
191*03ce13f7SAndroid Build Coastguard Worker       return true;
192*03ce13f7SAndroid Build Coastguard Worker   }
193*03ce13f7SAndroid Build Coastguard Worker   return false;
194*03ce13f7SAndroid Build Coastguard Worker }
195*03ce13f7SAndroid Build Coastguard Worker 
trim(InstNumberT Lower)196*03ce13f7SAndroid Build Coastguard Worker void LiveRange::trim(InstNumberT Lower) {
197*03ce13f7SAndroid Build Coastguard Worker   while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
198*03ce13f7SAndroid Build Coastguard Worker     ++TrimmedBegin;
199*03ce13f7SAndroid Build Coastguard Worker }
200*03ce13f7SAndroid Build Coastguard Worker 
asType(const Cfg * Func,Type Ty,RegNumT NewRegNum) const201*03ce13f7SAndroid Build Coastguard Worker const Variable *Variable::asType(const Cfg *Func, Type Ty,
202*03ce13f7SAndroid Build Coastguard Worker                                  RegNumT NewRegNum) const {
203*03ce13f7SAndroid Build Coastguard Worker   // Note: This returns a Variable, even if the "this" object is a subclass of
204*03ce13f7SAndroid Build Coastguard Worker   // Variable.
205*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump() || getType() == Ty)
206*03ce13f7SAndroid Build Coastguard Worker     return this;
207*03ce13f7SAndroid Build Coastguard Worker   static constexpr SizeT One = 1;
208*03ce13f7SAndroid Build Coastguard Worker   auto *V = new (CfgLocalAllocator<Variable>().allocate(One))
209*03ce13f7SAndroid Build Coastguard Worker       Variable(Func, kVariable, Ty, Number);
210*03ce13f7SAndroid Build Coastguard Worker   V->Name = Name;
211*03ce13f7SAndroid Build Coastguard Worker   V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
212*03ce13f7SAndroid Build Coastguard Worker   V->StackOffset = StackOffset;
213*03ce13f7SAndroid Build Coastguard Worker   V->LinkedTo = LinkedTo;
214*03ce13f7SAndroid Build Coastguard Worker   return V;
215*03ce13f7SAndroid Build Coastguard Worker }
216*03ce13f7SAndroid Build Coastguard Worker 
getWeight(const Cfg * Func) const217*03ce13f7SAndroid Build Coastguard Worker RegWeight Variable::getWeight(const Cfg *Func) const {
218*03ce13f7SAndroid Build Coastguard Worker   if (mustHaveReg())
219*03ce13f7SAndroid Build Coastguard Worker     return RegWeight(RegWeight::Inf);
220*03ce13f7SAndroid Build Coastguard Worker   if (mustNotHaveReg())
221*03ce13f7SAndroid Build Coastguard Worker     return RegWeight(RegWeight::Zero);
222*03ce13f7SAndroid Build Coastguard Worker   return Func->getVMetadata()->getUseWeight(this);
223*03ce13f7SAndroid Build Coastguard Worker }
224*03ce13f7SAndroid Build Coastguard Worker 
225*03ce13f7SAndroid Build Coastguard Worker int32_t
getRematerializableOffset(const::Ice::TargetLowering * Target)226*03ce13f7SAndroid Build Coastguard Worker Variable::getRematerializableOffset(const ::Ice::TargetLowering *Target) {
227*03ce13f7SAndroid Build Coastguard Worker   int32_t Disp = getStackOffset();
228*03ce13f7SAndroid Build Coastguard Worker   const auto RegNum = getRegNum();
229*03ce13f7SAndroid Build Coastguard Worker   if (RegNum == Target->getFrameReg()) {
230*03ce13f7SAndroid Build Coastguard Worker     Disp += Target->getFrameFixedAllocaOffset();
231*03ce13f7SAndroid Build Coastguard Worker   } else if (RegNum != Target->getStackReg()) {
232*03ce13f7SAndroid Build Coastguard Worker     llvm::report_fatal_error("Unexpected rematerializable register type");
233*03ce13f7SAndroid Build Coastguard Worker   }
234*03ce13f7SAndroid Build Coastguard Worker   return Disp;
235*03ce13f7SAndroid Build Coastguard Worker }
markUse(MetadataKind TrackingKind,const Inst * Instr,CfgNode * Node,bool IsImplicit)236*03ce13f7SAndroid Build Coastguard Worker void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
237*03ce13f7SAndroid Build Coastguard Worker                                CfgNode *Node, bool IsImplicit) {
238*03ce13f7SAndroid Build Coastguard Worker   (void)TrackingKind;
239*03ce13f7SAndroid Build Coastguard Worker 
240*03ce13f7SAndroid Build Coastguard Worker   // Increment the use weight depending on the loop nest depth. The weight is
241*03ce13f7SAndroid Build Coastguard Worker   // exponential in the nest depth as inner loops are expected to be executed
242*03ce13f7SAndroid Build Coastguard Worker   // an exponentially greater number of times.
243*03ce13f7SAndroid Build Coastguard Worker   constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
244*03ce13f7SAndroid Build Coastguard Worker   constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
245*03ce13f7SAndroid Build Coastguard Worker   constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
246*03ce13f7SAndroid Build Coastguard Worker   const uint32_t LoopNestDepth =
247*03ce13f7SAndroid Build Coastguard Worker       std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
248*03ce13f7SAndroid Build Coastguard Worker   const uint32_t ThisUseWeight = uint32_t(1)
249*03ce13f7SAndroid Build Coastguard Worker                                  << LoopNestDepth * LogLoopTripCountEstimate;
250*03ce13f7SAndroid Build Coastguard Worker   UseWeight.addWeight(ThisUseWeight);
251*03ce13f7SAndroid Build Coastguard Worker 
252*03ce13f7SAndroid Build Coastguard Worker   if (MultiBlock == MBS_MultiBlock)
253*03ce13f7SAndroid Build Coastguard Worker     return;
254*03ce13f7SAndroid Build Coastguard Worker   // TODO(stichnot): If the use occurs as a source operand in the first
255*03ce13f7SAndroid Build Coastguard Worker   // instruction of the block, and its definition is in this block's only
256*03ce13f7SAndroid Build Coastguard Worker   // predecessor, we might consider not marking this as a separate use. This
257*03ce13f7SAndroid Build Coastguard Worker   // may also apply if it's the first instruction of the block that actually
258*03ce13f7SAndroid Build Coastguard Worker   // uses a Variable.
259*03ce13f7SAndroid Build Coastguard Worker   assert(Node);
260*03ce13f7SAndroid Build Coastguard Worker   bool MakeMulti = false;
261*03ce13f7SAndroid Build Coastguard Worker   if (IsImplicit)
262*03ce13f7SAndroid Build Coastguard Worker     MakeMulti = true;
263*03ce13f7SAndroid Build Coastguard Worker   // A phi source variable conservatively needs to be marked as multi-block,
264*03ce13f7SAndroid Build Coastguard Worker   // even if its definition is in the same block. This is because there can be
265*03ce13f7SAndroid Build Coastguard Worker   // additional control flow before branching back to this node, and the
266*03ce13f7SAndroid Build Coastguard Worker   // variable is live throughout those nodes.
267*03ce13f7SAndroid Build Coastguard Worker   if (Instr && llvm::isa<InstPhi>(Instr))
268*03ce13f7SAndroid Build Coastguard Worker     MakeMulti = true;
269*03ce13f7SAndroid Build Coastguard Worker 
270*03ce13f7SAndroid Build Coastguard Worker   if (!MakeMulti) {
271*03ce13f7SAndroid Build Coastguard Worker     switch (MultiBlock) {
272*03ce13f7SAndroid Build Coastguard Worker     case MBS_Unknown:
273*03ce13f7SAndroid Build Coastguard Worker     case MBS_NoUses:
274*03ce13f7SAndroid Build Coastguard Worker       MultiBlock = MBS_SingleBlock;
275*03ce13f7SAndroid Build Coastguard Worker       SingleUseNode = Node;
276*03ce13f7SAndroid Build Coastguard Worker       break;
277*03ce13f7SAndroid Build Coastguard Worker     case MBS_SingleBlock:
278*03ce13f7SAndroid Build Coastguard Worker       if (SingleUseNode != Node)
279*03ce13f7SAndroid Build Coastguard Worker         MakeMulti = true;
280*03ce13f7SAndroid Build Coastguard Worker       break;
281*03ce13f7SAndroid Build Coastguard Worker     case MBS_MultiBlock:
282*03ce13f7SAndroid Build Coastguard Worker       break;
283*03ce13f7SAndroid Build Coastguard Worker     }
284*03ce13f7SAndroid Build Coastguard Worker   }
285*03ce13f7SAndroid Build Coastguard Worker 
286*03ce13f7SAndroid Build Coastguard Worker   if (MakeMulti) {
287*03ce13f7SAndroid Build Coastguard Worker     MultiBlock = MBS_MultiBlock;
288*03ce13f7SAndroid Build Coastguard Worker     SingleUseNode = nullptr;
289*03ce13f7SAndroid Build Coastguard Worker   }
290*03ce13f7SAndroid Build Coastguard Worker }
291*03ce13f7SAndroid Build Coastguard Worker 
markDef(MetadataKind TrackingKind,const Inst * Instr,CfgNode * Node)292*03ce13f7SAndroid Build Coastguard Worker void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
293*03ce13f7SAndroid Build Coastguard Worker                                CfgNode *Node) {
294*03ce13f7SAndroid Build Coastguard Worker   // TODO(stichnot): If the definition occurs in the last instruction of the
295*03ce13f7SAndroid Build Coastguard Worker   // block, consider not marking this as a separate use. But be careful not to
296*03ce13f7SAndroid Build Coastguard Worker   // omit all uses of the variable if markDef() and markUse() both use this
297*03ce13f7SAndroid Build Coastguard Worker   // optimization.
298*03ce13f7SAndroid Build Coastguard Worker   assert(Node);
299*03ce13f7SAndroid Build Coastguard Worker   // Verify that instructions are added in increasing order.
300*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::asserts()) {
301*03ce13f7SAndroid Build Coastguard Worker     if (TrackingKind == VMK_All) {
302*03ce13f7SAndroid Build Coastguard Worker       const Inst *LastInstruction =
303*03ce13f7SAndroid Build Coastguard Worker           Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
304*03ce13f7SAndroid Build Coastguard Worker       (void)LastInstruction;
305*03ce13f7SAndroid Build Coastguard Worker       assert(LastInstruction == nullptr ||
306*03ce13f7SAndroid Build Coastguard Worker              Instr->getNumber() >= LastInstruction->getNumber());
307*03ce13f7SAndroid Build Coastguard Worker     }
308*03ce13f7SAndroid Build Coastguard Worker   }
309*03ce13f7SAndroid Build Coastguard Worker   constexpr bool IsImplicit = false;
310*03ce13f7SAndroid Build Coastguard Worker   markUse(TrackingKind, Instr, Node, IsImplicit);
311*03ce13f7SAndroid Build Coastguard Worker   if (TrackingKind == VMK_Uses)
312*03ce13f7SAndroid Build Coastguard Worker     return;
313*03ce13f7SAndroid Build Coastguard Worker   if (FirstOrSingleDefinition == nullptr)
314*03ce13f7SAndroid Build Coastguard Worker     FirstOrSingleDefinition = Instr;
315*03ce13f7SAndroid Build Coastguard Worker   else if (TrackingKind == VMK_All)
316*03ce13f7SAndroid Build Coastguard Worker     Definitions.push_back(Instr);
317*03ce13f7SAndroid Build Coastguard Worker   switch (MultiDef) {
318*03ce13f7SAndroid Build Coastguard Worker   case MDS_Unknown:
319*03ce13f7SAndroid Build Coastguard Worker     assert(SingleDefNode == nullptr);
320*03ce13f7SAndroid Build Coastguard Worker     MultiDef = MDS_SingleDef;
321*03ce13f7SAndroid Build Coastguard Worker     SingleDefNode = Node;
322*03ce13f7SAndroid Build Coastguard Worker     break;
323*03ce13f7SAndroid Build Coastguard Worker   case MDS_SingleDef:
324*03ce13f7SAndroid Build Coastguard Worker     assert(SingleDefNode);
325*03ce13f7SAndroid Build Coastguard Worker     if (Node == SingleDefNode) {
326*03ce13f7SAndroid Build Coastguard Worker       MultiDef = MDS_MultiDefSingleBlock;
327*03ce13f7SAndroid Build Coastguard Worker     } else {
328*03ce13f7SAndroid Build Coastguard Worker       MultiDef = MDS_MultiDefMultiBlock;
329*03ce13f7SAndroid Build Coastguard Worker       SingleDefNode = nullptr;
330*03ce13f7SAndroid Build Coastguard Worker     }
331*03ce13f7SAndroid Build Coastguard Worker     break;
332*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefSingleBlock:
333*03ce13f7SAndroid Build Coastguard Worker     assert(SingleDefNode);
334*03ce13f7SAndroid Build Coastguard Worker     if (Node != SingleDefNode) {
335*03ce13f7SAndroid Build Coastguard Worker       MultiDef = MDS_MultiDefMultiBlock;
336*03ce13f7SAndroid Build Coastguard Worker       SingleDefNode = nullptr;
337*03ce13f7SAndroid Build Coastguard Worker     }
338*03ce13f7SAndroid Build Coastguard Worker     break;
339*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefMultiBlock:
340*03ce13f7SAndroid Build Coastguard Worker     assert(SingleDefNode == nullptr);
341*03ce13f7SAndroid Build Coastguard Worker     break;
342*03ce13f7SAndroid Build Coastguard Worker   }
343*03ce13f7SAndroid Build Coastguard Worker }
344*03ce13f7SAndroid Build Coastguard Worker 
getFirstDefinitionSingleBlock() const345*03ce13f7SAndroid Build Coastguard Worker const Inst *VariableTracking::getFirstDefinitionSingleBlock() const {
346*03ce13f7SAndroid Build Coastguard Worker   switch (MultiDef) {
347*03ce13f7SAndroid Build Coastguard Worker   case MDS_Unknown:
348*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefMultiBlock:
349*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
350*03ce13f7SAndroid Build Coastguard Worker   case MDS_SingleDef:
351*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefSingleBlock:
352*03ce13f7SAndroid Build Coastguard Worker     assert(FirstOrSingleDefinition);
353*03ce13f7SAndroid Build Coastguard Worker     return FirstOrSingleDefinition;
354*03ce13f7SAndroid Build Coastguard Worker   }
355*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
356*03ce13f7SAndroid Build Coastguard Worker }
357*03ce13f7SAndroid Build Coastguard Worker 
getSingleDefinition() const358*03ce13f7SAndroid Build Coastguard Worker const Inst *VariableTracking::getSingleDefinition() const {
359*03ce13f7SAndroid Build Coastguard Worker   switch (MultiDef) {
360*03ce13f7SAndroid Build Coastguard Worker   case MDS_Unknown:
361*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefMultiBlock:
362*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefSingleBlock:
363*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
364*03ce13f7SAndroid Build Coastguard Worker   case MDS_SingleDef:
365*03ce13f7SAndroid Build Coastguard Worker     assert(FirstOrSingleDefinition);
366*03ce13f7SAndroid Build Coastguard Worker     return FirstOrSingleDefinition;
367*03ce13f7SAndroid Build Coastguard Worker   }
368*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
369*03ce13f7SAndroid Build Coastguard Worker }
370*03ce13f7SAndroid Build Coastguard Worker 
getFirstDefinition() const371*03ce13f7SAndroid Build Coastguard Worker const Inst *VariableTracking::getFirstDefinition() const {
372*03ce13f7SAndroid Build Coastguard Worker   switch (MultiDef) {
373*03ce13f7SAndroid Build Coastguard Worker   case MDS_Unknown:
374*03ce13f7SAndroid Build Coastguard Worker     return nullptr;
375*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefMultiBlock:
376*03ce13f7SAndroid Build Coastguard Worker   case MDS_SingleDef:
377*03ce13f7SAndroid Build Coastguard Worker   case MDS_MultiDefSingleBlock:
378*03ce13f7SAndroid Build Coastguard Worker     assert(FirstOrSingleDefinition);
379*03ce13f7SAndroid Build Coastguard Worker     return FirstOrSingleDefinition;
380*03ce13f7SAndroid Build Coastguard Worker   }
381*03ce13f7SAndroid Build Coastguard Worker   return nullptr;
382*03ce13f7SAndroid Build Coastguard Worker }
383*03ce13f7SAndroid Build Coastguard Worker 
init(MetadataKind TrackingKind)384*03ce13f7SAndroid Build Coastguard Worker void VariablesMetadata::init(MetadataKind TrackingKind) {
385*03ce13f7SAndroid Build Coastguard Worker   TimerMarker T(TimerStack::TT_vmetadata, Func);
386*03ce13f7SAndroid Build Coastguard Worker   Kind = TrackingKind;
387*03ce13f7SAndroid Build Coastguard Worker   Metadata.clear();
388*03ce13f7SAndroid Build Coastguard Worker   Metadata.resize(Func->getNumVariables(), VariableTracking::MBS_NoUses);
389*03ce13f7SAndroid Build Coastguard Worker 
390*03ce13f7SAndroid Build Coastguard Worker   // Mark implicit args as being used in the entry node.
391*03ce13f7SAndroid Build Coastguard Worker   for (Variable *Var : Func->getImplicitArgs()) {
392*03ce13f7SAndroid Build Coastguard Worker     constexpr Inst *NoInst = nullptr;
393*03ce13f7SAndroid Build Coastguard Worker     CfgNode *EntryNode = Func->getEntryNode();
394*03ce13f7SAndroid Build Coastguard Worker     constexpr bool IsImplicit = true;
395*03ce13f7SAndroid Build Coastguard Worker     Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
396*03ce13f7SAndroid Build Coastguard Worker   }
397*03ce13f7SAndroid Build Coastguard Worker 
398*03ce13f7SAndroid Build Coastguard Worker   for (CfgNode *Node : Func->getNodes())
399*03ce13f7SAndroid Build Coastguard Worker     addNode(Node);
400*03ce13f7SAndroid Build Coastguard Worker }
401*03ce13f7SAndroid Build Coastguard Worker 
addNode(CfgNode * Node)402*03ce13f7SAndroid Build Coastguard Worker void VariablesMetadata::addNode(CfgNode *Node) {
403*03ce13f7SAndroid Build Coastguard Worker   if (Func->getNumVariables() > Metadata.size())
404*03ce13f7SAndroid Build Coastguard Worker     Metadata.resize(Func->getNumVariables());
405*03ce13f7SAndroid Build Coastguard Worker 
406*03ce13f7SAndroid Build Coastguard Worker   for (Inst &I : Node->getPhis()) {
407*03ce13f7SAndroid Build Coastguard Worker     if (I.isDeleted())
408*03ce13f7SAndroid Build Coastguard Worker       continue;
409*03ce13f7SAndroid Build Coastguard Worker     if (Variable *Dest = I.getDest()) {
410*03ce13f7SAndroid Build Coastguard Worker       SizeT DestNum = Dest->getIndex();
411*03ce13f7SAndroid Build Coastguard Worker       assert(DestNum < Metadata.size());
412*03ce13f7SAndroid Build Coastguard Worker       Metadata[DestNum].markDef(Kind, &I, Node);
413*03ce13f7SAndroid Build Coastguard Worker     }
414*03ce13f7SAndroid Build Coastguard Worker     for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
415*03ce13f7SAndroid Build Coastguard Worker       if (auto *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
416*03ce13f7SAndroid Build Coastguard Worker         SizeT VarNum = Var->getIndex();
417*03ce13f7SAndroid Build Coastguard Worker         assert(VarNum < Metadata.size());
418*03ce13f7SAndroid Build Coastguard Worker         constexpr bool IsImplicit = false;
419*03ce13f7SAndroid Build Coastguard Worker         Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
420*03ce13f7SAndroid Build Coastguard Worker       }
421*03ce13f7SAndroid Build Coastguard Worker     }
422*03ce13f7SAndroid Build Coastguard Worker   }
423*03ce13f7SAndroid Build Coastguard Worker 
424*03ce13f7SAndroid Build Coastguard Worker   for (Inst &I : Node->getInsts()) {
425*03ce13f7SAndroid Build Coastguard Worker     if (I.isDeleted())
426*03ce13f7SAndroid Build Coastguard Worker       continue;
427*03ce13f7SAndroid Build Coastguard Worker     // Note: The implicit definitions (and uses) from InstFakeKill are
428*03ce13f7SAndroid Build Coastguard Worker     // deliberately ignored.
429*03ce13f7SAndroid Build Coastguard Worker     if (Variable *Dest = I.getDest()) {
430*03ce13f7SAndroid Build Coastguard Worker       SizeT DestNum = Dest->getIndex();
431*03ce13f7SAndroid Build Coastguard Worker       assert(DestNum < Metadata.size());
432*03ce13f7SAndroid Build Coastguard Worker       Metadata[DestNum].markDef(Kind, &I, Node);
433*03ce13f7SAndroid Build Coastguard Worker     }
434*03ce13f7SAndroid Build Coastguard Worker     FOREACH_VAR_IN_INST(Var, I) {
435*03ce13f7SAndroid Build Coastguard Worker       SizeT VarNum = Var->getIndex();
436*03ce13f7SAndroid Build Coastguard Worker       assert(VarNum < Metadata.size());
437*03ce13f7SAndroid Build Coastguard Worker       constexpr bool IsImplicit = false;
438*03ce13f7SAndroid Build Coastguard Worker       Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
439*03ce13f7SAndroid Build Coastguard Worker     }
440*03ce13f7SAndroid Build Coastguard Worker   }
441*03ce13f7SAndroid Build Coastguard Worker }
442*03ce13f7SAndroid Build Coastguard Worker 
isMultiDef(const Variable * Var) const443*03ce13f7SAndroid Build Coastguard Worker bool VariablesMetadata::isMultiDef(const Variable *Var) const {
444*03ce13f7SAndroid Build Coastguard Worker   assert(Kind != VMK_Uses);
445*03ce13f7SAndroid Build Coastguard Worker   if (Var->getIsArg())
446*03ce13f7SAndroid Build Coastguard Worker     return false;
447*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
448*03ce13f7SAndroid Build Coastguard Worker     return true; // conservative answer
449*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
450*03ce13f7SAndroid Build Coastguard Worker   // Conservatively return true if the state is unknown.
451*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
452*03ce13f7SAndroid Build Coastguard Worker }
453*03ce13f7SAndroid Build Coastguard Worker 
isMultiBlock(const Variable * Var) const454*03ce13f7SAndroid Build Coastguard Worker bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
455*03ce13f7SAndroid Build Coastguard Worker   if (Var->getIsArg())
456*03ce13f7SAndroid Build Coastguard Worker     return true;
457*03ce13f7SAndroid Build Coastguard Worker   if (Var->isRematerializable())
458*03ce13f7SAndroid Build Coastguard Worker     return false;
459*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
460*03ce13f7SAndroid Build Coastguard Worker     return true; // conservative answer
461*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
462*03ce13f7SAndroid Build Coastguard Worker   switch (Metadata[VarNum].getMultiBlock()) {
463*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_NoUses:
464*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_SingleBlock:
465*03ce13f7SAndroid Build Coastguard Worker     return false;
466*03ce13f7SAndroid Build Coastguard Worker   // Conservatively return true if the state is unknown.
467*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_Unknown:
468*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_MultiBlock:
469*03ce13f7SAndroid Build Coastguard Worker     return true;
470*03ce13f7SAndroid Build Coastguard Worker   }
471*03ce13f7SAndroid Build Coastguard Worker   assert(0);
472*03ce13f7SAndroid Build Coastguard Worker   return true;
473*03ce13f7SAndroid Build Coastguard Worker }
474*03ce13f7SAndroid Build Coastguard Worker 
isSingleBlock(const Variable * Var) const475*03ce13f7SAndroid Build Coastguard Worker bool VariablesMetadata::isSingleBlock(const Variable *Var) const {
476*03ce13f7SAndroid Build Coastguard Worker   if (Var->getIsArg())
477*03ce13f7SAndroid Build Coastguard Worker     return false;
478*03ce13f7SAndroid Build Coastguard Worker   if (Var->isRematerializable())
479*03ce13f7SAndroid Build Coastguard Worker     return false;
480*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
481*03ce13f7SAndroid Build Coastguard Worker     return false; // conservative answer
482*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
483*03ce13f7SAndroid Build Coastguard Worker   switch (Metadata[VarNum].getMultiBlock()) {
484*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_SingleBlock:
485*03ce13f7SAndroid Build Coastguard Worker     return true;
486*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_Unknown:
487*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_NoUses:
488*03ce13f7SAndroid Build Coastguard Worker   case VariableTracking::MBS_MultiBlock:
489*03ce13f7SAndroid Build Coastguard Worker     return false;
490*03ce13f7SAndroid Build Coastguard Worker   }
491*03ce13f7SAndroid Build Coastguard Worker   assert(0);
492*03ce13f7SAndroid Build Coastguard Worker   return false;
493*03ce13f7SAndroid Build Coastguard Worker }
494*03ce13f7SAndroid Build Coastguard Worker 
495*03ce13f7SAndroid Build Coastguard Worker const Inst *
getFirstDefinitionSingleBlock(const Variable * Var) const496*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata::getFirstDefinitionSingleBlock(const Variable *Var) const {
497*03ce13f7SAndroid Build Coastguard Worker   assert(Kind != VMK_Uses);
498*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
499*03ce13f7SAndroid Build Coastguard Worker     return nullptr; // conservative answer
500*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
501*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getFirstDefinitionSingleBlock();
502*03ce13f7SAndroid Build Coastguard Worker }
503*03ce13f7SAndroid Build Coastguard Worker 
getSingleDefinition(const Variable * Var) const504*03ce13f7SAndroid Build Coastguard Worker const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
505*03ce13f7SAndroid Build Coastguard Worker   assert(Kind != VMK_Uses);
506*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
507*03ce13f7SAndroid Build Coastguard Worker     return nullptr; // conservative answer
508*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
509*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getSingleDefinition();
510*03ce13f7SAndroid Build Coastguard Worker }
511*03ce13f7SAndroid Build Coastguard Worker 
getFirstDefinition(const Variable * Var) const512*03ce13f7SAndroid Build Coastguard Worker const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
513*03ce13f7SAndroid Build Coastguard Worker   assert(Kind != VMK_Uses);
514*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
515*03ce13f7SAndroid Build Coastguard Worker     return nullptr; // conservative answer
516*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
517*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getFirstDefinition();
518*03ce13f7SAndroid Build Coastguard Worker }
519*03ce13f7SAndroid Build Coastguard Worker 
520*03ce13f7SAndroid Build Coastguard Worker const InstDefList &
getLatterDefinitions(const Variable * Var) const521*03ce13f7SAndroid Build Coastguard Worker VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
522*03ce13f7SAndroid Build Coastguard Worker   assert(Kind == VMK_All);
523*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var)) {
524*03ce13f7SAndroid Build Coastguard Worker     // NoDefinitions has to be initialized after we've had a chance to set the
525*03ce13f7SAndroid Build Coastguard Worker     // CfgAllocator, so it can't be a static global object. Also, while C++11
526*03ce13f7SAndroid Build Coastguard Worker     // guarantees the initialization of static local objects to be thread-safe,
527*03ce13f7SAndroid Build Coastguard Worker     // we use a pointer to it so we can avoid frequent  mutex locking overhead.
528*03ce13f7SAndroid Build Coastguard Worker     if (NoDefinitions == nullptr) {
529*03ce13f7SAndroid Build Coastguard Worker       static const InstDefList NoDefinitionsInstance;
530*03ce13f7SAndroid Build Coastguard Worker       NoDefinitions = &NoDefinitionsInstance;
531*03ce13f7SAndroid Build Coastguard Worker     }
532*03ce13f7SAndroid Build Coastguard Worker     return *NoDefinitions;
533*03ce13f7SAndroid Build Coastguard Worker   }
534*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
535*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getLatterDefinitions();
536*03ce13f7SAndroid Build Coastguard Worker }
537*03ce13f7SAndroid Build Coastguard Worker 
getLocalUseNode(const Variable * Var) const538*03ce13f7SAndroid Build Coastguard Worker CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
539*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
540*03ce13f7SAndroid Build Coastguard Worker     return nullptr; // conservative answer
541*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
542*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getNode();
543*03ce13f7SAndroid Build Coastguard Worker }
544*03ce13f7SAndroid Build Coastguard Worker 
getUseWeight(const Variable * Var) const545*03ce13f7SAndroid Build Coastguard Worker RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
546*03ce13f7SAndroid Build Coastguard Worker   if (!isTracked(Var))
547*03ce13f7SAndroid Build Coastguard Worker     return RegWeight(1); // conservative answer
548*03ce13f7SAndroid Build Coastguard Worker   SizeT VarNum = Var->getIndex();
549*03ce13f7SAndroid Build Coastguard Worker   return Metadata[VarNum].getUseWeight();
550*03ce13f7SAndroid Build Coastguard Worker }
551*03ce13f7SAndroid Build Coastguard Worker 
552*03ce13f7SAndroid Build Coastguard Worker const InstDefList *VariablesMetadata::NoDefinitions = nullptr;
553*03ce13f7SAndroid Build Coastguard Worker 
554*03ce13f7SAndroid Build Coastguard Worker // ======================== dump routines ======================== //
555*03ce13f7SAndroid Build Coastguard Worker 
emit(const Cfg * Func) const556*03ce13f7SAndroid Build Coastguard Worker void Variable::emit(const Cfg *Func) const {
557*03ce13f7SAndroid Build Coastguard Worker   if (BuildDefs::dump())
558*03ce13f7SAndroid Build Coastguard Worker     Func->getTarget()->emitVariable(this);
559*03ce13f7SAndroid Build Coastguard Worker }
560*03ce13f7SAndroid Build Coastguard Worker 
dump(const Cfg * Func,Ostream & Str) const561*03ce13f7SAndroid Build Coastguard Worker void Variable::dump(const Cfg *Func, Ostream &Str) const {
562*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
563*03ce13f7SAndroid Build Coastguard Worker     return;
564*03ce13f7SAndroid Build Coastguard Worker   if (Func == nullptr) {
565*03ce13f7SAndroid Build Coastguard Worker     Str << "%" << getName();
566*03ce13f7SAndroid Build Coastguard Worker     return;
567*03ce13f7SAndroid Build Coastguard Worker   }
568*03ce13f7SAndroid Build Coastguard Worker   if (Func->isVerbose(IceV_RegOrigins) ||
569*03ce13f7SAndroid Build Coastguard Worker       (!hasReg() && !Func->getTarget()->hasComputedFrame())) {
570*03ce13f7SAndroid Build Coastguard Worker     Str << "%" << getName();
571*03ce13f7SAndroid Build Coastguard Worker     for (Variable *Link = getLinkedTo(); Link != nullptr;
572*03ce13f7SAndroid Build Coastguard Worker          Link = Link->getLinkedTo()) {
573*03ce13f7SAndroid Build Coastguard Worker       Str << ":%" << Link->getName();
574*03ce13f7SAndroid Build Coastguard Worker     }
575*03ce13f7SAndroid Build Coastguard Worker   }
576*03ce13f7SAndroid Build Coastguard Worker   if (hasReg()) {
577*03ce13f7SAndroid Build Coastguard Worker     if (Func->isVerbose(IceV_RegOrigins))
578*03ce13f7SAndroid Build Coastguard Worker       Str << ":";
579*03ce13f7SAndroid Build Coastguard Worker     Str << Func->getTarget()->getRegName(RegNum, getType());
580*03ce13f7SAndroid Build Coastguard Worker   } else if (Func->getTarget()->hasComputedFrame()) {
581*03ce13f7SAndroid Build Coastguard Worker     if (Func->isVerbose(IceV_RegOrigins))
582*03ce13f7SAndroid Build Coastguard Worker       Str << ":";
583*03ce13f7SAndroid Build Coastguard Worker     const auto BaseRegisterNumber =
584*03ce13f7SAndroid Build Coastguard Worker         hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
585*03ce13f7SAndroid Build Coastguard Worker     Str << "["
586*03ce13f7SAndroid Build Coastguard Worker         << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
587*03ce13f7SAndroid Build Coastguard Worker     if (hasKnownStackOffset()) {
588*03ce13f7SAndroid Build Coastguard Worker       int32_t Offset = getStackOffset();
589*03ce13f7SAndroid Build Coastguard Worker       if (Offset) {
590*03ce13f7SAndroid Build Coastguard Worker         if (Offset > 0)
591*03ce13f7SAndroid Build Coastguard Worker           Str << "+";
592*03ce13f7SAndroid Build Coastguard Worker         Str << Offset;
593*03ce13f7SAndroid Build Coastguard Worker       }
594*03ce13f7SAndroid Build Coastguard Worker     }
595*03ce13f7SAndroid Build Coastguard Worker     Str << "]";
596*03ce13f7SAndroid Build Coastguard Worker   }
597*03ce13f7SAndroid Build Coastguard Worker }
598*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const599*03ce13f7SAndroid Build Coastguard Worker template <> void ConstantInteger32::emit(TargetLowering *Target) const {
600*03ce13f7SAndroid Build Coastguard Worker   Target->emit(this);
601*03ce13f7SAndroid Build Coastguard Worker }
602*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const603*03ce13f7SAndroid Build Coastguard Worker template <> void ConstantInteger64::emit(TargetLowering *Target) const {
604*03ce13f7SAndroid Build Coastguard Worker   Target->emit(this);
605*03ce13f7SAndroid Build Coastguard Worker }
606*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const607*03ce13f7SAndroid Build Coastguard Worker template <> void ConstantFloat::emit(TargetLowering *Target) const {
608*03ce13f7SAndroid Build Coastguard Worker   Target->emit(this);
609*03ce13f7SAndroid Build Coastguard Worker }
610*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const611*03ce13f7SAndroid Build Coastguard Worker template <> void ConstantDouble::emit(TargetLowering *Target) const {
612*03ce13f7SAndroid Build Coastguard Worker   Target->emit(this);
613*03ce13f7SAndroid Build Coastguard Worker }
614*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const615*03ce13f7SAndroid Build Coastguard Worker void ConstantRelocatable::emit(TargetLowering *Target) const {
616*03ce13f7SAndroid Build Coastguard Worker   Target->emit(this);
617*03ce13f7SAndroid Build Coastguard Worker }
618*03ce13f7SAndroid Build Coastguard Worker 
emitWithoutPrefix(const TargetLowering * Target,const char * Suffix) const619*03ce13f7SAndroid Build Coastguard Worker void ConstantRelocatable::emitWithoutPrefix(const TargetLowering *Target,
620*03ce13f7SAndroid Build Coastguard Worker                                             const char *Suffix) const {
621*03ce13f7SAndroid Build Coastguard Worker   Target->emitWithoutPrefix(this, Suffix);
622*03ce13f7SAndroid Build Coastguard Worker }
623*03ce13f7SAndroid Build Coastguard Worker 
dump(const Cfg *,Ostream & Str) const624*03ce13f7SAndroid Build Coastguard Worker void ConstantRelocatable::dump(const Cfg *, Ostream &Str) const {
625*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
626*03ce13f7SAndroid Build Coastguard Worker     return;
627*03ce13f7SAndroid Build Coastguard Worker   if (!EmitString.empty()) {
628*03ce13f7SAndroid Build Coastguard Worker     Str << EmitString;
629*03ce13f7SAndroid Build Coastguard Worker     return;
630*03ce13f7SAndroid Build Coastguard Worker   }
631*03ce13f7SAndroid Build Coastguard Worker   Str << "@" << (Name.hasStdString() ? Name.toString() : "<Unnamed>");
632*03ce13f7SAndroid Build Coastguard Worker   const RelocOffsetT Offset = getOffset();
633*03ce13f7SAndroid Build Coastguard Worker   if (Offset) {
634*03ce13f7SAndroid Build Coastguard Worker     if (Offset >= 0) {
635*03ce13f7SAndroid Build Coastguard Worker       Str << "+";
636*03ce13f7SAndroid Build Coastguard Worker     }
637*03ce13f7SAndroid Build Coastguard Worker     Str << Offset;
638*03ce13f7SAndroid Build Coastguard Worker   }
639*03ce13f7SAndroid Build Coastguard Worker }
640*03ce13f7SAndroid Build Coastguard Worker 
emit(TargetLowering * Target) const641*03ce13f7SAndroid Build Coastguard Worker void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
642*03ce13f7SAndroid Build Coastguard Worker 
dump(Ostream & Str) const643*03ce13f7SAndroid Build Coastguard Worker void LiveRange::dump(Ostream &Str) const {
644*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
645*03ce13f7SAndroid Build Coastguard Worker     return;
646*03ce13f7SAndroid Build Coastguard Worker   bool First = true;
647*03ce13f7SAndroid Build Coastguard Worker   for (const RangeElementType &I : Range) {
648*03ce13f7SAndroid Build Coastguard Worker     if (!First)
649*03ce13f7SAndroid Build Coastguard Worker       Str << ", ";
650*03ce13f7SAndroid Build Coastguard Worker     First = false;
651*03ce13f7SAndroid Build Coastguard Worker     Str << "[" << I.first << ":" << I.second << ")";
652*03ce13f7SAndroid Build Coastguard Worker   }
653*03ce13f7SAndroid Build Coastguard Worker }
654*03ce13f7SAndroid Build Coastguard Worker 
operator <<(Ostream & Str,const LiveRange & L)655*03ce13f7SAndroid Build Coastguard Worker Ostream &operator<<(Ostream &Str, const LiveRange &L) {
656*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
657*03ce13f7SAndroid Build Coastguard Worker     return Str;
658*03ce13f7SAndroid Build Coastguard Worker   L.dump(Str);
659*03ce13f7SAndroid Build Coastguard Worker   return Str;
660*03ce13f7SAndroid Build Coastguard Worker }
661*03ce13f7SAndroid Build Coastguard Worker 
operator <<(Ostream & Str,const RegWeight & W)662*03ce13f7SAndroid Build Coastguard Worker Ostream &operator<<(Ostream &Str, const RegWeight &W) {
663*03ce13f7SAndroid Build Coastguard Worker   if (!BuildDefs::dump())
664*03ce13f7SAndroid Build Coastguard Worker     return Str;
665*03ce13f7SAndroid Build Coastguard Worker   if (W.getWeight() == RegWeight::Inf)
666*03ce13f7SAndroid Build Coastguard Worker     Str << "Inf";
667*03ce13f7SAndroid Build Coastguard Worker   else
668*03ce13f7SAndroid Build Coastguard Worker     Str << W.getWeight();
669*03ce13f7SAndroid Build Coastguard Worker   return Str;
670*03ce13f7SAndroid Build Coastguard Worker }
671*03ce13f7SAndroid Build Coastguard Worker 
672*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice
673