blob: 043583eb1b3dddd8db89b113be3d6849822da5ee [file] [log] [blame]
Jim Stichnothf7c9a142014-04-29 10:52:43 -07001//===- subzero/src/IceOperand.cpp - High-level operand implementation -----===//
2//
3// The Subzero Code Generator
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Andrew Scull9612d322015-07-06 14:53:25 -07009///
10/// \file
Jim Stichnoth92a6e5b2015-12-02 16:52:44 -080011/// \brief Implements the Operand class and its target-independent subclasses,
12/// primarily for the methods of the Variable class.
Andrew Scull9612d322015-07-06 14:53:25 -070013///
Jim Stichnothf7c9a142014-04-29 10:52:43 -070014//===----------------------------------------------------------------------===//
15
John Porto67f8de92015-06-25 10:14:17 -070016#include "IceOperand.h"
17
Jim Stichnothf7c9a142014-04-29 10:52:43 -070018#include "IceCfg.h"
Jim Stichnoth144cdce2014-09-22 16:02:59 -070019#include "IceCfgNode.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070020#include "IceInst.h"
John Portoec3f5652015-08-31 15:07:09 -070021#include "IceInstVarIter.h"
John Portoe82b5602016-02-24 15:58:55 -080022#include "IceMemory.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070023#include "IceTargetLowering.h" // dumping stack/frame pointer register
Jim Stichnothf7c9a142014-04-29 10:52:43 -070024
25namespace Ice {
26
Jim Stichnoth467ffe52016-03-29 15:01:06 -070027void Constant::initShouldBePooled() {
28 ShouldBePooled = TargetLowering::shouldBePooled(this);
29}
30
Jim Stichnothd2cb4362014-11-20 11:24:42 -080031bool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
John Porto27fddcc2016-02-02 15:06:09 -080032 // A and B are the same if:
33 // (1) they have the same name; and
34 // (2) they have the same offset.
35 //
36 // (1) is trivial to check, but (2) requires some care.
37 //
38 // For (2):
39 // if A and B have known offsets (i.e., no symbolic references), then
40 // A == B -> A.Offset == B.Offset.
41 // else each element i in A.OffsetExpr[i] must be the same (or have the same
42 // value) as B.OffsetExpr[i].
43 if (A.Name != B.Name) {
44 return false;
45 }
46
47 bool BothHaveKnownOffsets = true;
John Portoe82b5602016-02-24 15:58:55 -080048 RelocOffsetT OffsetA = A.Offset;
49 RelocOffsetT OffsetB = B.Offset;
John Porto27fddcc2016-02-02 15:06:09 -080050 for (SizeT i = 0; i < A.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
51 BothHaveKnownOffsets = A.OffsetExpr[i]->hasOffset();
52 if (BothHaveKnownOffsets) {
53 OffsetA += A.OffsetExpr[i]->getOffset();
54 }
55 }
56 for (SizeT i = 0; i < B.OffsetExpr.size() && BothHaveKnownOffsets; ++i) {
57 BothHaveKnownOffsets = B.OffsetExpr[i]->hasOffset();
58 if (BothHaveKnownOffsets) {
59 OffsetB += B.OffsetExpr[i]->getOffset();
60 }
61 }
62 if (BothHaveKnownOffsets) {
63 // Both have known offsets (i.e., no unresolved symbolic references), so
64 // A == B -> A.Offset == B.Offset.
65 return OffsetA == OffsetB;
66 }
67
68 // Otherwise, A and B are not the same if their OffsetExpr's have different
69 // sizes.
70 if (A.OffsetExpr.size() != B.OffsetExpr.size()) {
71 return false;
72 }
73
74 // If the OffsetExprs' sizes are the same, then
75 // for each i in OffsetExprSize:
76 for (SizeT i = 0; i < A.OffsetExpr.size(); ++i) {
77 const auto *const RelocOffsetA = A.OffsetExpr[i];
78 const auto *const RelocOffsetB = B.OffsetExpr[i];
79 if (RelocOffsetA->hasOffset() && RelocOffsetB->hasOffset()) {
80 // A.OffsetExpr[i].Offset == B.OffsetExpr[i].Offset iff they are both
81 // defined;
82 if (RelocOffsetA->getOffset() != RelocOffsetB->getOffset()) {
83 return false;
84 }
85 } else if (RelocOffsetA != RelocOffsetB) {
86 // or, if they are undefined, then the RelocOffsets must be the same.
87 return false;
88 }
89 }
90
91 return true;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070092}
93
Jim Stichnoth8aa39662016-02-10 11:20:30 -080094RegNumT::BaseType RegNumT::Limit = 0;
95
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070096bool operator<(const RegWeight &A, const RegWeight &B) {
97 return A.getWeight() < B.getWeight();
98}
99bool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
100bool operator==(const RegWeight &A, const RegWeight &B) {
101 return !(B < A) && !(A < B);
102}
103
Manasij Mukherjee7cd926d2016-08-04 12:33:23 -0700104void LiveRange::addSegment(InstNumberT Start, InstNumberT End, CfgNode *Node) {
105 if (getFlags().getSplitGlobalVars()) {
106 // Disable merging to make sure a live range 'segment' has a single node.
107 // Might be possible to enable when the target segment has the same node.
108 assert(NodeMap.find(Start) == NodeMap.end());
109 NodeMap[Start] = Node;
110 } else {
111 if (!Range.empty()) {
112 // Check for merge opportunity.
113 InstNumberT CurrentEnd = Range.back().second;
114 assert(Start >= CurrentEnd);
115 if (Start == CurrentEnd) {
116 Range.back().second = End;
117 return;
118 }
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800119 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700120 }
121 Range.push_back(RangeElementType(Start, End));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700122}
123
Andrew Scull57e12682015-09-16 11:30:19 -0700124// Returns true if this live range ends before Other's live range starts. This
125// means that the highest instruction number in this live range is less than or
126// equal to the lowest instruction number of the Other live range.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700127bool LiveRange::endsBefore(const LiveRange &Other) const {
128 // Neither range should be empty, but let's be graceful.
129 if (Range.empty() || Other.Range.empty())
130 return true;
131 InstNumberT MyEnd = (*Range.rbegin()).second;
132 InstNumberT OtherStart = (*Other.Range.begin()).first;
133 return MyEnd <= OtherStart;
134}
135
136// Returns true if there is any overlap between the two live ranges.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700137bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700138 // Do a two-finger walk through the two sorted lists of segments.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700139 auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
140 I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
141 auto E1 = Range.end(), E2 = Other.Range.end();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700142 while (I1 != E1 && I2 != E2) {
143 if (I1->second <= I2->first) {
144 ++I1;
145 continue;
146 }
147 if (I2->second <= I1->first) {
148 ++I2;
149 continue;
150 }
151 return true;
152 }
153 return false;
154}
155
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700156bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700157 bool Result = false;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700158 for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
159 I != E; ++I) {
160 if (OtherBegin < I->first) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700161 Result = false;
162 break;
163 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700164 if (OtherBegin < I->second) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700165 Result = true;
166 break;
167 }
168 }
Andrew Scull57e12682015-09-16 11:30:19 -0700169 // This is an equivalent but less inefficient implementation. It's expensive
170 // enough that we wouldn't want to run it under any build, but it could be
171 // enabled if e.g. the LiveRange implementation changes and extra testing is
172 // needed.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700173 if (BuildDefs::extraValidation()) {
174 LiveRange Temp;
175 Temp.addSegment(OtherBegin, OtherBegin + 1);
176 bool Validation = overlaps(Temp);
177 (void)Validation;
178 assert(Result == Validation);
179 }
Jim Stichnothc4554d72014-09-30 16:49:38 -0700180 return Result;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700181}
182
Andrew Scull57e12682015-09-16 11:30:19 -0700183// Returns true if the live range contains the given instruction number. This
184// is only used for validating the live range calculation. The IsDest argument
185// indicates whether the Variable being tested is used in the Dest position (as
186// opposed to a Src position).
Jim Stichnoth47752552014-10-13 17:15:08 -0700187bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700188 for (const RangeElementType &I : Range) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700189 if (I.first <= Value &&
190 (Value < I.second || (!IsDest && Value == I.second)))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700191 return true;
192 }
193 return false;
194}
195
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700196void LiveRange::trim(InstNumberT Lower) {
197 while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
198 ++TrimmedBegin;
199}
200
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700201const Variable *Variable::asType(const Cfg *Func, Type Ty,
202 RegNumT NewRegNum) const {
Andrew Scull57e12682015-09-16 11:30:19 -0700203 // Note: This returns a Variable, even if the "this" object is a subclass of
204 // Variable.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700205 if (!BuildDefs::dump() || getType() == Ty)
Jim Stichnoth31c95592014-12-19 12:51:35 -0800206 return this;
John Portoe82b5602016-02-24 15:58:55 -0800207 static constexpr SizeT One = 1;
Jim Stichnothe343e062016-06-28 21:40:33 -0700208 auto *V = new (CfgLocalAllocator<Variable>().allocate(One))
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700209 Variable(Func, kVariable, Ty, Number);
210 V->Name = Name;
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800211 V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800212 V->StackOffset = StackOffset;
Jim Stichnothe343e062016-06-28 21:40:33 -0700213 V->LinkedTo = LinkedTo;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700214 return V;
215}
216
Andrew Scull11c9a322015-08-28 14:24:14 -0700217RegWeight Variable::getWeight(const Cfg *Func) const {
Jim Stichnothb9a84722016-08-01 13:18:36 -0700218 if (mustHaveReg())
219 return RegWeight(RegWeight::Inf);
220 if (mustNotHaveReg())
221 return RegWeight(RegWeight::Zero);
222 return Func->getVMetadata()->getUseWeight(this);
Andrew Scull11c9a322015-08-28 14:24:14 -0700223}
224
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700225void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700226 CfgNode *Node, bool IsImplicit) {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700227 (void)TrackingKind;
Andrew Scull11c9a322015-08-28 14:24:14 -0700228
Andrew Scullaa6c1092015-09-03 17:50:30 -0700229 // Increment the use weight depending on the loop nest depth. The weight is
230 // exponential in the nest depth as inner loops are expected to be executed
231 // an exponentially greater number of times.
232 constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
233 constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
234 constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
235 const uint32_t LoopNestDepth =
236 std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
237 const uint32_t ThisUseWeight = uint32_t(1)
238 << LoopNestDepth * LogLoopTripCountEstimate;
239 UseWeight.addWeight(ThisUseWeight);
Andrew Scull11c9a322015-08-28 14:24:14 -0700240
Jim Stichnoth47752552014-10-13 17:15:08 -0700241 if (MultiBlock == MBS_MultiBlock)
242 return;
Andrew Scull57e12682015-09-16 11:30:19 -0700243 // TODO(stichnot): If the use occurs as a source operand in the first
244 // instruction of the block, and its definition is in this block's only
245 // predecessor, we might consider not marking this as a separate use. This
246 // may also apply if it's the first instruction of the block that actually
247 // uses a Variable.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700248 assert(Node);
249 bool MakeMulti = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700250 if (IsImplicit)
251 MakeMulti = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700252 // A phi source variable conservatively needs to be marked as multi-block,
253 // even if its definition is in the same block. This is because there can be
254 // additional control flow before branching back to this node, and the
255 // variable is live throughout those nodes.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700256 if (Instr && llvm::isa<InstPhi>(Instr))
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700257 MakeMulti = true;
258
259 if (!MakeMulti) {
260 switch (MultiBlock) {
261 case MBS_Unknown:
Jim Stichnothcc89c952016-03-31 11:55:23 -0700262 case MBS_NoUses:
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700263 MultiBlock = MBS_SingleBlock;
264 SingleUseNode = Node;
265 break;
266 case MBS_SingleBlock:
267 if (SingleUseNode != Node)
268 MakeMulti = true;
269 break;
270 case MBS_MultiBlock:
271 break;
272 }
273 }
274
275 if (MakeMulti) {
276 MultiBlock = MBS_MultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800277 SingleUseNode = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700278 }
279}
280
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700281void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700282 CfgNode *Node) {
Andrew Scull57e12682015-09-16 11:30:19 -0700283 // TODO(stichnot): If the definition occurs in the last instruction of the
284 // block, consider not marking this as a separate use. But be careful not to
285 // omit all uses of the variable if markDef() and markUse() both use this
286 // optimization.
Jim Stichnothad403532014-09-25 12:44:17 -0700287 assert(Node);
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700288 // Verify that instructions are added in increasing order.
289 if (BuildDefs::asserts()) {
290 if (TrackingKind == VMK_All) {
291 const Inst *LastInstruction =
292 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
293 (void)LastInstruction;
294 assert(LastInstruction == nullptr ||
295 Instr->getNumber() >= LastInstruction->getNumber());
296 }
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700297 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700298 constexpr bool IsImplicit = false;
299 markUse(TrackingKind, Instr, Node, IsImplicit);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700300 if (TrackingKind == VMK_Uses)
301 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800302 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700303 FirstOrSingleDefinition = Instr;
304 else if (TrackingKind == VMK_All)
305 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700306 switch (MultiDef) {
307 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800308 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700309 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700310 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700311 break;
312 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700313 assert(SingleDefNode);
314 if (Node == SingleDefNode) {
315 MultiDef = MDS_MultiDefSingleBlock;
316 } else {
317 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800318 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700319 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700320 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700321 case MDS_MultiDefSingleBlock:
322 assert(SingleDefNode);
323 if (Node != SingleDefNode) {
324 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800325 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700326 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700327 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700328 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800329 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700330 break;
331 }
332}
333
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700334const Inst *VariableTracking::getFirstDefinitionSingleBlock() const {
Jim Stichnothad403532014-09-25 12:44:17 -0700335 switch (MultiDef) {
336 case MDS_Unknown:
337 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800338 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700339 case MDS_SingleDef:
340 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700341 assert(FirstOrSingleDefinition);
342 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700343 }
Jim Stichnothae953202014-12-20 06:17:49 -0800344 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700345}
346
347const Inst *VariableTracking::getSingleDefinition() const {
348 switch (MultiDef) {
349 case MDS_Unknown:
350 case MDS_MultiDefMultiBlock:
351 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800352 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700353 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700354 assert(FirstOrSingleDefinition);
355 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700356 }
Jim Stichnothae953202014-12-20 06:17:49 -0800357 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700358}
359
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700360const Inst *VariableTracking::getFirstDefinition() const {
361 switch (MultiDef) {
362 case MDS_Unknown:
363 return nullptr;
364 case MDS_MultiDefMultiBlock:
365 case MDS_SingleDef:
366 case MDS_MultiDefSingleBlock:
367 assert(FirstOrSingleDefinition);
368 return FirstOrSingleDefinition;
369 }
370 return nullptr;
371}
372
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700373void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700374 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700375 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700376 Metadata.clear();
Jim Stichnothcc89c952016-03-31 11:55:23 -0700377 Metadata.resize(Func->getNumVariables(), VariableTracking::MBS_NoUses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700378
379 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700380 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700381 constexpr Inst *NoInst = nullptr;
382 CfgNode *EntryNode = Func->getEntryNode();
383 constexpr bool IsImplicit = true;
384 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700385 }
386
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700387 for (CfgNode *Node : Func->getNodes())
388 addNode(Node);
389}
390
391void VariablesMetadata::addNode(CfgNode *Node) {
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700392 if (Func->getNumVariables() > Metadata.size())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700393 Metadata.resize(Func->getNumVariables());
394
Jim Stichnoth29841e82014-12-23 12:26:24 -0800395 for (Inst &I : Node->getPhis()) {
396 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700397 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800398 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700399 SizeT DestNum = Dest->getIndex();
400 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800401 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700402 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800403 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800404 if (auto *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700405 SizeT VarNum = Var->getIndex();
406 assert(VarNum < Metadata.size());
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700407 constexpr bool IsImplicit = false;
408 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700409 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700410 }
411 }
412
Jim Stichnoth29841e82014-12-23 12:26:24 -0800413 for (Inst &I : Node->getInsts()) {
414 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700415 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800416 // Note: The implicit definitions (and uses) from InstFakeKill are
417 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800418 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700419 SizeT DestNum = Dest->getIndex();
420 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800421 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700422 }
John Portoec3f5652015-08-31 15:07:09 -0700423 FOREACH_VAR_IN_INST(Var, I) {
424 SizeT VarNum = Var->getIndex();
425 assert(VarNum < Metadata.size());
426 constexpr bool IsImplicit = false;
427 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700428 }
429 }
430}
431
432bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700433 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700434 if (Var->getIsArg())
435 return false;
436 if (!isTracked(Var))
437 return true; // conservative answer
438 SizeT VarNum = Var->getIndex();
439 // Conservatively return true if the state is unknown.
440 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
441}
442
443bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700444 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700445 return true;
Jim Stichnothcc89c952016-03-31 11:55:23 -0700446 if (Var->isRematerializable())
447 return false;
Jim Stichnothad403532014-09-25 12:44:17 -0700448 if (!isTracked(Var))
449 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700450 SizeT VarNum = Var->getIndex();
Jim Stichnothcc89c952016-03-31 11:55:23 -0700451 switch (Metadata[VarNum].getMultiBlock()) {
452 case VariableTracking::MBS_NoUses:
453 case VariableTracking::MBS_SingleBlock:
454 return false;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700455 // Conservatively return true if the state is unknown.
Jim Stichnothcc89c952016-03-31 11:55:23 -0700456 case VariableTracking::MBS_Unknown:
457 case VariableTracking::MBS_MultiBlock:
458 return true;
459 }
460 assert(0);
461 return true;
462}
463
464bool VariablesMetadata::isSingleBlock(const Variable *Var) const {
465 if (Var->getIsArg())
466 return false;
467 if (Var->isRematerializable())
468 return false;
469 if (!isTracked(Var))
470 return false; // conservative answer
471 SizeT VarNum = Var->getIndex();
472 switch (Metadata[VarNum].getMultiBlock()) {
473 case VariableTracking::MBS_SingleBlock:
474 return true;
475 case VariableTracking::MBS_Unknown:
476 case VariableTracking::MBS_NoUses:
477 case VariableTracking::MBS_MultiBlock:
478 return false;
479 }
480 assert(0);
481 return false;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700482}
483
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700484const Inst *
485VariablesMetadata::getFirstDefinitionSingleBlock(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700486 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700487 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800488 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700489 SizeT VarNum = Var->getIndex();
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700490 return Metadata[VarNum].getFirstDefinitionSingleBlock();
Jim Stichnothad403532014-09-25 12:44:17 -0700491}
492
493const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700494 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700495 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800496 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700497 SizeT VarNum = Var->getIndex();
498 return Metadata[VarNum].getSingleDefinition();
499}
500
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700501const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
502 assert(Kind != VMK_Uses);
503 if (!isTracked(Var))
504 return nullptr; // conservative answer
505 SizeT VarNum = Var->getIndex();
506 return Metadata[VarNum].getFirstDefinition();
507}
508
Jim Stichnothad403532014-09-25 12:44:17 -0700509const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700510VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
511 assert(Kind == VMK_All);
Nicolas Capens86e5d882016-09-08 12:47:42 -0400512 if (!isTracked(Var)) {
513 // NoDefinitions has to be initialized after we've had a chance to set the
514 // CfgAllocator, so it can't be a static global object. Also, while C++11
515 // guarantees the initialization of static local objects to be thread-safe,
516 // we use a pointer to it so we can avoid frequent mutex locking overhead.
517 if (NoDefinitions == nullptr) {
518 static const InstDefList NoDefinitionsInstance;
519 NoDefinitions = &NoDefinitionsInstance;
520 }
521 return *NoDefinitions;
522 }
Jim Stichnothad403532014-09-25 12:44:17 -0700523 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700524 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700525}
526
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700527CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700528 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800529 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700530 SizeT VarNum = Var->getIndex();
531 return Metadata[VarNum].getNode();
532}
533
Andrew Scullaa6c1092015-09-03 17:50:30 -0700534RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
Andrew Scull11c9a322015-08-28 14:24:14 -0700535 if (!isTracked(Var))
Andrew Scullaa6c1092015-09-03 17:50:30 -0700536 return RegWeight(1); // conservative answer
Andrew Scull11c9a322015-08-28 14:24:14 -0700537 SizeT VarNum = Var->getIndex();
538 return Metadata[VarNum].getUseWeight();
539}
540
Nicolas Capens86e5d882016-09-08 12:47:42 -0400541const InstDefList *VariablesMetadata::NoDefinitions = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700542
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700543// ======================== dump routines ======================== //
544
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700545void Variable::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700546 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800547 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700548}
549
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700550void Variable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700551 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800552 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800553 if (Func == nullptr) {
Jim Stichnotha91c3412016-04-05 15:31:43 -0700554 Str << "%" << getName();
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700555 return;
556 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800557 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnothe343e062016-06-28 21:40:33 -0700558 (!hasReg() && !Func->getTarget()->hasComputedFrame())) {
Jim Stichnotha91c3412016-04-05 15:31:43 -0700559 Str << "%" << getName();
Jim Stichnothb9a84722016-08-01 13:18:36 -0700560 for (Variable *Link = getLinkedTo(); Link != nullptr;
561 Link = Link->getLinkedTo()) {
562 Str << ":%" << Link->getName();
563 }
Jim Stichnothe343e062016-06-28 21:40:33 -0700564 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700565 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800566 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700567 Str << ":";
568 Str << Func->getTarget()->getRegName(RegNum, getType());
569 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800570 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700571 Str << ":";
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800572 const auto BaseRegisterNumber =
573 hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
Jim Stichnothdd842db2015-01-27 12:53:53 -0800574 Str << "["
Jan Voung28068ad2015-07-31 12:58:46 -0700575 << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
Jim Stichnothb9a84722016-08-01 13:18:36 -0700576 if (hasKnownStackOffset()) {
Jim Stichnothfe62f0a2016-07-10 05:13:18 -0700577 int32_t Offset = getStackOffset();
578 if (Offset) {
579 if (Offset > 0)
580 Str << "+";
581 Str << Offset;
582 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700583 }
584 Str << "]";
585 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700586}
587
Jan Voung76bb0be2015-05-14 09:26:19 -0700588template <> void ConstantInteger32::emit(TargetLowering *Target) const {
589 Target->emit(this);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700590}
591
Jan Voung76bb0be2015-05-14 09:26:19 -0700592template <> void ConstantInteger64::emit(TargetLowering *Target) const {
593 Target->emit(this);
594}
595
596template <> void ConstantFloat::emit(TargetLowering *Target) const {
597 Target->emit(this);
598}
599
600template <> void ConstantDouble::emit(TargetLowering *Target) const {
601 Target->emit(this);
602}
603
604void ConstantRelocatable::emit(TargetLowering *Target) const {
605 Target->emit(this);
606}
607
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800608void ConstantRelocatable::emitWithoutPrefix(const TargetLowering *Target,
609 const char *Suffix) const {
610 Target->emitWithoutPrefix(this, Suffix);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700611}
612
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800613void ConstantRelocatable::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700614 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800615 return;
John Portodc619252016-02-10 15:57:16 -0800616 if (!EmitString.empty()) {
617 Str << EmitString;
618 return;
619 }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800620 Str << "@" << Name;
John Porto27fddcc2016-02-02 15:06:09 -0800621 const RelocOffsetT Offset = getOffset();
622 if (Offset) {
623 if (Offset >= 0) {
624 Str << "+";
625 }
626 Str << Offset;
627 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700628}
629
Jan Voung76bb0be2015-05-14 09:26:19 -0700630void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
631
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700632void LiveRange::dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700633 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800634 return;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700635 bool First = true;
636 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700637 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700638 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700639 First = false;
640 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700641 }
642}
643
644Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700645 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800646 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700647 L.dump(Str);
648 return Str;
649}
650
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700651Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700652 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800653 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700654 if (W.getWeight() == RegWeight::Inf)
655 Str << "Inf";
656 else
657 Str << W.getWeight();
658 return Str;
659}
660
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700661} // end of namespace Ice