blob: 870ca175523ad20fc4ea9fb28b47b7a0526d6c5a [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
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700104void LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -0800105 if (!Range.empty()) {
106 // Check for merge opportunity.
107 InstNumberT CurrentEnd = Range.back().second;
108 assert(Start >= CurrentEnd);
109 if (Start == CurrentEnd) {
110 Range.back().second = End;
111 return;
112 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700113 }
114 Range.push_back(RangeElementType(Start, End));
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700115}
116
Andrew Scull57e12682015-09-16 11:30:19 -0700117// Returns true if this live range ends before Other's live range starts. This
118// means that the highest instruction number in this live range is less than or
119// equal to the lowest instruction number of the Other live range.
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700120bool LiveRange::endsBefore(const LiveRange &Other) const {
121 // Neither range should be empty, but let's be graceful.
122 if (Range.empty() || Other.Range.empty())
123 return true;
124 InstNumberT MyEnd = (*Range.rbegin()).second;
125 InstNumberT OtherStart = (*Other.Range.begin()).first;
126 return MyEnd <= OtherStart;
127}
128
129// Returns true if there is any overlap between the two live ranges.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700130bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700131 // Do a two-finger walk through the two sorted lists of segments.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700132 auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
133 I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
134 auto E1 = Range.end(), E2 = Other.Range.end();
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700135 while (I1 != E1 && I2 != E2) {
136 if (I1->second <= I2->first) {
137 ++I1;
138 continue;
139 }
140 if (I2->second <= I1->first) {
141 ++I2;
142 continue;
143 }
144 return true;
145 }
146 return false;
147}
148
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700149bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700150 bool Result = false;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700151 for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
152 I != E; ++I) {
153 if (OtherBegin < I->first) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700154 Result = false;
155 break;
156 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700157 if (OtherBegin < I->second) {
Jim Stichnothc4554d72014-09-30 16:49:38 -0700158 Result = true;
159 break;
160 }
161 }
Andrew Scull57e12682015-09-16 11:30:19 -0700162 // This is an equivalent but less inefficient implementation. It's expensive
163 // enough that we wouldn't want to run it under any build, but it could be
164 // enabled if e.g. the LiveRange implementation changes and extra testing is
165 // needed.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700166 if (BuildDefs::extraValidation()) {
167 LiveRange Temp;
168 Temp.addSegment(OtherBegin, OtherBegin + 1);
169 bool Validation = overlaps(Temp);
170 (void)Validation;
171 assert(Result == Validation);
172 }
Jim Stichnothc4554d72014-09-30 16:49:38 -0700173 return Result;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700174}
175
Andrew Scull57e12682015-09-16 11:30:19 -0700176// Returns true if the live range contains the given instruction number. This
177// is only used for validating the live range calculation. The IsDest argument
178// indicates whether the Variable being tested is used in the Dest position (as
179// opposed to a Src position).
Jim Stichnoth47752552014-10-13 17:15:08 -0700180bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700181 for (const RangeElementType &I : Range) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700182 if (I.first <= Value &&
183 (Value < I.second || (!IsDest && Value == I.second)))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700184 return true;
185 }
186 return false;
187}
188
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700189void LiveRange::trim(InstNumberT Lower) {
190 while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
191 ++TrimmedBegin;
192}
193
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700194std::string Variable::getName(const Cfg *Func) const {
195 if (Func == nullptr)
196 return "__" + std::to_string(getIndex());
197 return Name.toString();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700198}
199
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700200const Variable *Variable::asType(const Cfg *Func, Type Ty,
201 RegNumT NewRegNum) const {
Andrew Scull57e12682015-09-16 11:30:19 -0700202 // Note: This returns a Variable, even if the "this" object is a subclass of
203 // Variable.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700204 if (!BuildDefs::dump() || getType() == Ty)
Jim Stichnoth31c95592014-12-19 12:51:35 -0800205 return this;
John Portoe82b5602016-02-24 15:58:55 -0800206 static constexpr SizeT One = 1;
207 Variable *V = new (CfgLocalAllocator<Variable>().allocate(One))
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700208 Variable(Func, kVariable, Ty, Number);
209 V->Name = Name;
Reed Kotler5fa0a5f2016-02-15 20:01:24 -0800210 V->RegNum = NewRegNum.hasValue() ? NewRegNum : RegNum;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800211 V->StackOffset = StackOffset;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700212 return V;
213}
214
Andrew Scull11c9a322015-08-28 14:24:14 -0700215RegWeight Variable::getWeight(const Cfg *Func) const {
216 VariablesMetadata *VMetadata = Func->getVMetadata();
Andrew Scullaa6c1092015-09-03 17:50:30 -0700217 return mustHaveReg() ? RegWeight(RegWeight::Inf)
218 : mustNotHaveReg() ? RegWeight(RegWeight::Zero)
219 : VMetadata->getUseWeight(this);
Andrew Scull11c9a322015-08-28 14:24:14 -0700220}
221
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700222void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700223 CfgNode *Node, bool IsImplicit) {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700224 (void)TrackingKind;
Andrew Scull11c9a322015-08-28 14:24:14 -0700225
Andrew Scullaa6c1092015-09-03 17:50:30 -0700226 // Increment the use weight depending on the loop nest depth. The weight is
227 // exponential in the nest depth as inner loops are expected to be executed
228 // an exponentially greater number of times.
229 constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
230 constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
231 constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
232 const uint32_t LoopNestDepth =
233 std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
234 const uint32_t ThisUseWeight = uint32_t(1)
235 << LoopNestDepth * LogLoopTripCountEstimate;
236 UseWeight.addWeight(ThisUseWeight);
Andrew Scull11c9a322015-08-28 14:24:14 -0700237
Jim Stichnoth47752552014-10-13 17:15:08 -0700238 if (MultiBlock == MBS_MultiBlock)
239 return;
Andrew Scull57e12682015-09-16 11:30:19 -0700240 // TODO(stichnot): If the use occurs as a source operand in the first
241 // instruction of the block, and its definition is in this block's only
242 // predecessor, we might consider not marking this as a separate use. This
243 // may also apply if it's the first instruction of the block that actually
244 // uses a Variable.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700245 assert(Node);
246 bool MakeMulti = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700247 if (IsImplicit)
248 MakeMulti = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700249 // A phi source variable conservatively needs to be marked as multi-block,
250 // even if its definition is in the same block. This is because there can be
251 // additional control flow before branching back to this node, and the
252 // variable is live throughout those nodes.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700253 if (Instr && llvm::isa<InstPhi>(Instr))
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700254 MakeMulti = true;
255
256 if (!MakeMulti) {
257 switch (MultiBlock) {
258 case MBS_Unknown:
259 MultiBlock = MBS_SingleBlock;
260 SingleUseNode = Node;
261 break;
262 case MBS_SingleBlock:
263 if (SingleUseNode != Node)
264 MakeMulti = true;
265 break;
266 case MBS_MultiBlock:
267 break;
268 }
269 }
270
271 if (MakeMulti) {
272 MultiBlock = MBS_MultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800273 SingleUseNode = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700274 }
275}
276
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700277void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700278 CfgNode *Node) {
Andrew Scull57e12682015-09-16 11:30:19 -0700279 // TODO(stichnot): If the definition occurs in the last instruction of the
280 // block, consider not marking this as a separate use. But be careful not to
281 // omit all uses of the variable if markDef() and markUse() both use this
282 // optimization.
Jim Stichnothad403532014-09-25 12:44:17 -0700283 assert(Node);
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700284 // Verify that instructions are added in increasing order.
285 if (BuildDefs::asserts()) {
286 if (TrackingKind == VMK_All) {
287 const Inst *LastInstruction =
288 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
289 (void)LastInstruction;
290 assert(LastInstruction == nullptr ||
291 Instr->getNumber() >= LastInstruction->getNumber());
292 }
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700293 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700294 constexpr bool IsImplicit = false;
295 markUse(TrackingKind, Instr, Node, IsImplicit);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700296 if (TrackingKind == VMK_Uses)
297 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800298 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700299 FirstOrSingleDefinition = Instr;
300 else if (TrackingKind == VMK_All)
301 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700302 switch (MultiDef) {
303 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800304 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700305 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700306 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700307 break;
308 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700309 assert(SingleDefNode);
310 if (Node == SingleDefNode) {
311 MultiDef = MDS_MultiDefSingleBlock;
312 } else {
313 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800314 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700315 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700316 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700317 case MDS_MultiDefSingleBlock:
318 assert(SingleDefNode);
319 if (Node != SingleDefNode) {
320 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800321 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700322 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700323 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700324 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800325 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700326 break;
327 }
328}
329
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700330const Inst *VariableTracking::getFirstDefinitionSingleBlock() const {
Jim Stichnothad403532014-09-25 12:44:17 -0700331 switch (MultiDef) {
332 case MDS_Unknown:
333 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800334 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700335 case MDS_SingleDef:
336 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700337 assert(FirstOrSingleDefinition);
338 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700339 }
Jim Stichnothae953202014-12-20 06:17:49 -0800340 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700341}
342
343const Inst *VariableTracking::getSingleDefinition() const {
344 switch (MultiDef) {
345 case MDS_Unknown:
346 case MDS_MultiDefMultiBlock:
347 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800348 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700349 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700350 assert(FirstOrSingleDefinition);
351 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700352 }
Jim Stichnothae953202014-12-20 06:17:49 -0800353 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700354}
355
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700356const Inst *VariableTracking::getFirstDefinition() const {
357 switch (MultiDef) {
358 case MDS_Unknown:
359 return nullptr;
360 case MDS_MultiDefMultiBlock:
361 case MDS_SingleDef:
362 case MDS_MultiDefSingleBlock:
363 assert(FirstOrSingleDefinition);
364 return FirstOrSingleDefinition;
365 }
366 return nullptr;
367}
368
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700369void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700370 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700371 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700372 Metadata.clear();
373 Metadata.resize(Func->getNumVariables());
374
375 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700376 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700377 constexpr Inst *NoInst = nullptr;
378 CfgNode *EntryNode = Func->getEntryNode();
379 constexpr bool IsImplicit = true;
380 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700381 }
382
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700383 for (CfgNode *Node : Func->getNodes())
384 addNode(Node);
385}
386
387void VariablesMetadata::addNode(CfgNode *Node) {
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700388 if (Func->getNumVariables() > Metadata.size())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700389 Metadata.resize(Func->getNumVariables());
390
Jim Stichnoth29841e82014-12-23 12:26:24 -0800391 for (Inst &I : Node->getPhis()) {
392 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700393 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800394 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700395 SizeT DestNum = Dest->getIndex();
396 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800397 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700398 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800399 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
Jim Stichnoth54f3d512015-12-11 09:53:00 -0800400 if (auto *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700401 SizeT VarNum = Var->getIndex();
402 assert(VarNum < Metadata.size());
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700403 constexpr bool IsImplicit = false;
404 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700405 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700406 }
407 }
408
Jim Stichnoth29841e82014-12-23 12:26:24 -0800409 for (Inst &I : Node->getInsts()) {
410 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700411 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800412 // Note: The implicit definitions (and uses) from InstFakeKill are
413 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800414 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700415 SizeT DestNum = Dest->getIndex();
416 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800417 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700418 }
John Portoec3f5652015-08-31 15:07:09 -0700419 FOREACH_VAR_IN_INST(Var, I) {
420 SizeT VarNum = Var->getIndex();
421 assert(VarNum < Metadata.size());
422 constexpr bool IsImplicit = false;
423 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700424 }
425 }
426}
427
428bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700429 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700430 if (Var->getIsArg())
431 return false;
432 if (!isTracked(Var))
433 return true; // conservative answer
434 SizeT VarNum = Var->getIndex();
435 // Conservatively return true if the state is unknown.
436 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
437}
438
439bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700440 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700441 return true;
Jim Stichnothad403532014-09-25 12:44:17 -0700442 if (!isTracked(Var))
443 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700444 SizeT VarNum = Var->getIndex();
445 // Conservatively return true if the state is unknown.
446 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
447}
448
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700449const Inst *
450VariablesMetadata::getFirstDefinitionSingleBlock(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700451 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700452 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800453 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700454 SizeT VarNum = Var->getIndex();
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700455 return Metadata[VarNum].getFirstDefinitionSingleBlock();
Jim Stichnothad403532014-09-25 12:44:17 -0700456}
457
458const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700459 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700460 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800461 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700462 SizeT VarNum = Var->getIndex();
463 return Metadata[VarNum].getSingleDefinition();
464}
465
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700466const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
467 assert(Kind != VMK_Uses);
468 if (!isTracked(Var))
469 return nullptr; // conservative answer
470 SizeT VarNum = Var->getIndex();
471 return Metadata[VarNum].getFirstDefinition();
472}
473
Jim Stichnothad403532014-09-25 12:44:17 -0700474const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700475VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
476 assert(Kind == VMK_All);
Jim Stichnothad403532014-09-25 12:44:17 -0700477 if (!isTracked(Var))
478 return NoDefinitions;
479 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700480 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700481}
482
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700483CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700484 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800485 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700486 SizeT VarNum = Var->getIndex();
487 return Metadata[VarNum].getNode();
488}
489
Andrew Scullaa6c1092015-09-03 17:50:30 -0700490RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
Andrew Scull11c9a322015-08-28 14:24:14 -0700491 if (!isTracked(Var))
Andrew Scullaa6c1092015-09-03 17:50:30 -0700492 return RegWeight(1); // conservative answer
Andrew Scull11c9a322015-08-28 14:24:14 -0700493 SizeT VarNum = Var->getIndex();
494 return Metadata[VarNum].getUseWeight();
495}
496
Jim Stichnothad403532014-09-25 12:44:17 -0700497const InstDefList VariablesMetadata::NoDefinitions;
498
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700499// ======================== dump routines ======================== //
500
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700501void Variable::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700502 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800503 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700504}
505
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700506void Variable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700507 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800508 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800509 if (Func == nullptr) {
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800510 Str << "%" << getName(Func);
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700511 return;
512 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800513 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700514 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800515 Str << "%" << getName(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700516 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800517 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700518 Str << ":";
519 Str << Func->getTarget()->getRegName(RegNum, getType());
520 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800521 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700522 Str << ":";
Jim Stichnoth8aa39662016-02-10 11:20:30 -0800523 const auto BaseRegisterNumber =
524 hasReg() ? getBaseRegNum() : Func->getTarget()->getFrameOrStackReg();
Jim Stichnothdd842db2015-01-27 12:53:53 -0800525 Str << "["
Jan Voung28068ad2015-07-31 12:58:46 -0700526 << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700527 int32_t Offset = getStackOffset();
528 if (Offset) {
529 if (Offset > 0)
530 Str << "+";
531 Str << Offset;
532 }
533 Str << "]";
534 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700535}
536
Jan Voung76bb0be2015-05-14 09:26:19 -0700537template <> void ConstantInteger32::emit(TargetLowering *Target) const {
538 Target->emit(this);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700539}
540
Jan Voung76bb0be2015-05-14 09:26:19 -0700541template <> void ConstantInteger64::emit(TargetLowering *Target) const {
542 Target->emit(this);
543}
544
545template <> void ConstantFloat::emit(TargetLowering *Target) const {
546 Target->emit(this);
547}
548
549template <> void ConstantDouble::emit(TargetLowering *Target) const {
550 Target->emit(this);
551}
552
553void ConstantRelocatable::emit(TargetLowering *Target) const {
554 Target->emit(this);
555}
556
Jim Stichnoth8ff4b282016-01-04 15:39:06 -0800557void ConstantRelocatable::emitWithoutPrefix(const TargetLowering *Target,
558 const char *Suffix) const {
559 Target->emitWithoutPrefix(this, Suffix);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700560}
561
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800562void ConstantRelocatable::dump(const Cfg *, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700563 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800564 return;
John Portodc619252016-02-10 15:57:16 -0800565 if (!EmitString.empty()) {
566 Str << EmitString;
567 return;
568 }
Jim Stichnoth98ba0062016-03-07 09:26:22 -0800569 Str << "@" << Name;
John Porto27fddcc2016-02-02 15:06:09 -0800570 const RelocOffsetT Offset = getOffset();
571 if (Offset) {
572 if (Offset >= 0) {
573 Str << "+";
574 }
575 Str << Offset;
576 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700577}
578
Jan Voung76bb0be2015-05-14 09:26:19 -0700579void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
580
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700581void LiveRange::dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700582 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800583 return;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700584 bool First = true;
585 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700586 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700587 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700588 First = false;
589 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700590 }
591}
592
593Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700594 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800595 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700596 L.dump(Str);
597 return Str;
598}
599
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700600Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700601 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800602 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700603 if (W.getWeight() == RegWeight::Inf)
604 Str << "Inf";
605 else
606 Str << W.getWeight();
607 return Str;
608}
609
Qining Lu253dc8a2015-06-22 10:10:23 -0700610// =========== Immediate Randomization and Pooling routines ==============
611// Specialization of the template member function for ConstantInteger32
Andrew Scull57e12682015-09-16 11:30:19 -0700612// TODO(stichnot): try to move this specialization into a target-specific file.
Jim Stichnoth467ffe52016-03-29 15:01:06 -0700613template <> bool ConstantInteger32::shouldBeRandomizedOrPooled() const {
614 uint32_t Threshold =
615 GlobalContext::getFlags().getRandomizeAndPoolImmediatesThreshold();
616 if (GlobalContext::getFlags().getRandomizeAndPoolImmediatesOption() ==
617 RPI_None)
Qining Lu253dc8a2015-06-22 10:10:23 -0700618 return false;
619 if (getType() != IceType_i32 && getType() != IceType_i16 &&
620 getType() != IceType_i8)
621 return false;
622 // The Following checks if the signed representation of Value is between
623 // -Threshold/2 and +Threshold/2
624 bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
625 return largerThanThreshold;
626}
627
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700628} // end of namespace Ice