blob: 125c6925307465a811253e374b6c6350f2c9f408 [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
11/// This file implements the Operand class and its target-independent
12/// subclasses, primarily for the methods of the Variable class.
13///
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"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070022#include "IceTargetLowering.h" // dumping stack/frame pointer register
Jim Stichnothf7c9a142014-04-29 10:52:43 -070023
24namespace Ice {
25
Jim Stichnothd2cb4362014-11-20 11:24:42 -080026bool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
27 return A.Offset == B.Offset && A.Name == B.Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070028}
29
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070030bool operator<(const RegWeight &A, const RegWeight &B) {
31 return A.getWeight() < B.getWeight();
32}
33bool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
34bool operator==(const RegWeight &A, const RegWeight &B) {
35 return !(B < A) && !(A < B);
36}
37
Jim Stichnothd97c7df2014-06-04 11:57:08 -070038void LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -080039 if (!Range.empty()) {
40 // Check for merge opportunity.
41 InstNumberT CurrentEnd = Range.back().second;
42 assert(Start >= CurrentEnd);
43 if (Start == CurrentEnd) {
44 Range.back().second = End;
45 return;
46 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070047 }
48 Range.push_back(RangeElementType(Start, End));
Jim Stichnothd97c7df2014-06-04 11:57:08 -070049}
50
Andrew Scull57e12682015-09-16 11:30:19 -070051// Returns true if this live range ends before Other's live range starts. This
52// means that the highest instruction number in this live range is less than or
53// equal to the lowest instruction number of the Other live range.
Jim Stichnothd97c7df2014-06-04 11:57:08 -070054bool LiveRange::endsBefore(const LiveRange &Other) const {
55 // Neither range should be empty, but let's be graceful.
56 if (Range.empty() || Other.Range.empty())
57 return true;
58 InstNumberT MyEnd = (*Range.rbegin()).second;
59 InstNumberT OtherStart = (*Other.Range.begin()).first;
60 return MyEnd <= OtherStart;
61}
62
63// Returns true if there is any overlap between the two live ranges.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070064bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
Jim Stichnothd97c7df2014-06-04 11:57:08 -070065 // Do a two-finger walk through the two sorted lists of segments.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070066 auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
67 I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
68 auto E1 = Range.end(), E2 = Other.Range.end();
Jim Stichnothd97c7df2014-06-04 11:57:08 -070069 while (I1 != E1 && I2 != E2) {
70 if (I1->second <= I2->first) {
71 ++I1;
72 continue;
73 }
74 if (I2->second <= I1->first) {
75 ++I2;
76 continue;
77 }
78 return true;
79 }
80 return false;
81}
82
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070083bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
Jim Stichnothc4554d72014-09-30 16:49:38 -070084 bool Result = false;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070085 for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
86 I != E; ++I) {
87 if (OtherBegin < I->first) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070088 Result = false;
89 break;
90 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070091 if (OtherBegin < I->second) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070092 Result = true;
93 break;
94 }
95 }
Andrew Scull57e12682015-09-16 11:30:19 -070096 // This is an equivalent but less inefficient implementation. It's expensive
97 // enough that we wouldn't want to run it under any build, but it could be
98 // enabled if e.g. the LiveRange implementation changes and extra testing is
99 // needed.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700100 if (BuildDefs::extraValidation()) {
101 LiveRange Temp;
102 Temp.addSegment(OtherBegin, OtherBegin + 1);
103 bool Validation = overlaps(Temp);
104 (void)Validation;
105 assert(Result == Validation);
106 }
Jim Stichnothc4554d72014-09-30 16:49:38 -0700107 return Result;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700108}
109
Andrew Scull57e12682015-09-16 11:30:19 -0700110// Returns true if the live range contains the given instruction number. This
111// is only used for validating the live range calculation. The IsDest argument
112// indicates whether the Variable being tested is used in the Dest position (as
113// opposed to a Src position).
Jim Stichnoth47752552014-10-13 17:15:08 -0700114bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700115 for (const RangeElementType &I : Range) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700116 if (I.first <= Value &&
117 (Value < I.second || (!IsDest && Value == I.second)))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700118 return true;
119 }
120 return false;
121}
122
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700123void LiveRange::trim(InstNumberT Lower) {
124 while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
125 ++TrimmedBegin;
126}
127
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800128IceString Variable::getName(const Cfg *Func) const {
129 if (Func && NameIndex >= 0)
130 return Func->getIdentifierName(NameIndex);
Jim Stichnoth088b2be2014-10-23 12:02:08 -0700131 return "__" + std::to_string(getIndex());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700132}
133
Jim Stichnoth31c95592014-12-19 12:51:35 -0800134Variable *Variable::asType(Type Ty) {
Andrew Scull57e12682015-09-16 11:30:19 -0700135 // Note: This returns a Variable, even if the "this" object is a subclass of
136 // Variable.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700137 if (!BuildDefs::dump() || getType() == Ty)
Jim Stichnoth31c95592014-12-19 12:51:35 -0800138 return this;
139 Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
140 Variable(kVariable, Ty, Number);
141 V->NameIndex = NameIndex;
142 V->RegNum = RegNum;
143 V->StackOffset = StackOffset;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700144 return V;
145}
146
Andrew Scull11c9a322015-08-28 14:24:14 -0700147RegWeight Variable::getWeight(const Cfg *Func) const {
148 VariablesMetadata *VMetadata = Func->getVMetadata();
Andrew Scullaa6c1092015-09-03 17:50:30 -0700149 return mustHaveReg() ? RegWeight(RegWeight::Inf)
150 : mustNotHaveReg() ? RegWeight(RegWeight::Zero)
151 : VMetadata->getUseWeight(this);
Andrew Scull11c9a322015-08-28 14:24:14 -0700152}
153
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700154void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700155 CfgNode *Node, bool IsImplicit) {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700156 (void)TrackingKind;
Andrew Scull11c9a322015-08-28 14:24:14 -0700157
Andrew Scullaa6c1092015-09-03 17:50:30 -0700158 // Increment the use weight depending on the loop nest depth. The weight is
159 // exponential in the nest depth as inner loops are expected to be executed
160 // an exponentially greater number of times.
161 constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
162 constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
163 constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
164 const uint32_t LoopNestDepth =
165 std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
166 const uint32_t ThisUseWeight = uint32_t(1)
167 << LoopNestDepth * LogLoopTripCountEstimate;
168 UseWeight.addWeight(ThisUseWeight);
Andrew Scull11c9a322015-08-28 14:24:14 -0700169
Jim Stichnoth47752552014-10-13 17:15:08 -0700170 if (MultiBlock == MBS_MultiBlock)
171 return;
Andrew Scull57e12682015-09-16 11:30:19 -0700172 // TODO(stichnot): If the use occurs as a source operand in the first
173 // instruction of the block, and its definition is in this block's only
174 // predecessor, we might consider not marking this as a separate use. This
175 // may also apply if it's the first instruction of the block that actually
176 // uses a Variable.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700177 assert(Node);
178 bool MakeMulti = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700179 if (IsImplicit)
180 MakeMulti = true;
Andrew Scull57e12682015-09-16 11:30:19 -0700181 // A phi source variable conservatively needs to be marked as multi-block,
182 // even if its definition is in the same block. This is because there can be
183 // additional control flow before branching back to this node, and the
184 // variable is live throughout those nodes.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700185 if (Instr && llvm::isa<InstPhi>(Instr))
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700186 MakeMulti = true;
187
188 if (!MakeMulti) {
189 switch (MultiBlock) {
190 case MBS_Unknown:
191 MultiBlock = MBS_SingleBlock;
192 SingleUseNode = Node;
193 break;
194 case MBS_SingleBlock:
195 if (SingleUseNode != Node)
196 MakeMulti = true;
197 break;
198 case MBS_MultiBlock:
199 break;
200 }
201 }
202
203 if (MakeMulti) {
204 MultiBlock = MBS_MultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800205 SingleUseNode = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700206 }
207}
208
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700209void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700210 CfgNode *Node) {
Andrew Scull57e12682015-09-16 11:30:19 -0700211 // TODO(stichnot): If the definition occurs in the last instruction of the
212 // block, consider not marking this as a separate use. But be careful not to
213 // omit all uses of the variable if markDef() and markUse() both use this
214 // optimization.
Jim Stichnothad403532014-09-25 12:44:17 -0700215 assert(Node);
Jim Stichnothdd842db2015-01-27 12:53:53 -0800216// Verify that instructions are added in increasing order.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700217#ifndef NDEBUG
218 if (TrackingKind == VMK_All) {
219 const Inst *LastInstruction =
220 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
Jim Stichnothae953202014-12-20 06:17:49 -0800221 assert(LastInstruction == nullptr ||
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700222 Instr->getNumber() >= LastInstruction->getNumber());
223 }
224#endif
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700225 constexpr bool IsImplicit = false;
226 markUse(TrackingKind, Instr, Node, IsImplicit);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700227 if (TrackingKind == VMK_Uses)
228 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800229 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700230 FirstOrSingleDefinition = Instr;
231 else if (TrackingKind == VMK_All)
232 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700233 switch (MultiDef) {
234 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800235 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700236 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700237 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700238 break;
239 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700240 assert(SingleDefNode);
241 if (Node == SingleDefNode) {
242 MultiDef = MDS_MultiDefSingleBlock;
243 } else {
244 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800245 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700246 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700247 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700248 case MDS_MultiDefSingleBlock:
249 assert(SingleDefNode);
250 if (Node != SingleDefNode) {
251 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800252 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700253 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700254 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700255 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800256 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700257 break;
258 }
259}
260
261const Inst *VariableTracking::getFirstDefinition() const {
262 switch (MultiDef) {
263 case MDS_Unknown:
264 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800265 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700266 case MDS_SingleDef:
267 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700268 assert(FirstOrSingleDefinition);
269 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700270 }
Jim Stichnothae953202014-12-20 06:17:49 -0800271 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700272}
273
274const Inst *VariableTracking::getSingleDefinition() const {
275 switch (MultiDef) {
276 case MDS_Unknown:
277 case MDS_MultiDefMultiBlock:
278 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800279 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700280 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700281 assert(FirstOrSingleDefinition);
282 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700283 }
Jim Stichnothae953202014-12-20 06:17:49 -0800284 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700285}
286
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700287void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700288 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700289 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700290 Metadata.clear();
291 Metadata.resize(Func->getNumVariables());
292
293 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700294 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700295 constexpr Inst *NoInst = nullptr;
296 CfgNode *EntryNode = Func->getEntryNode();
297 constexpr bool IsImplicit = true;
298 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700299 }
300
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700301 for (CfgNode *Node : Func->getNodes())
302 addNode(Node);
303}
304
305void VariablesMetadata::addNode(CfgNode *Node) {
306 if (Func->getNumVariables() >= Metadata.size())
307 Metadata.resize(Func->getNumVariables());
308
Jim Stichnoth29841e82014-12-23 12:26:24 -0800309 for (Inst &I : Node->getPhis()) {
310 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700311 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800312 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700313 SizeT DestNum = Dest->getIndex();
314 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800315 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700316 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800317 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
318 if (const Variable *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700319 SizeT VarNum = Var->getIndex();
320 assert(VarNum < Metadata.size());
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700321 constexpr bool IsImplicit = false;
322 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700323 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700324 }
325 }
326
Jim Stichnoth29841e82014-12-23 12:26:24 -0800327 for (Inst &I : Node->getInsts()) {
328 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700329 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800330 // Note: The implicit definitions (and uses) from InstFakeKill are
331 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800332 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700333 SizeT DestNum = Dest->getIndex();
334 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800335 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700336 }
John Portoec3f5652015-08-31 15:07:09 -0700337 FOREACH_VAR_IN_INST(Var, I) {
338 SizeT VarNum = Var->getIndex();
339 assert(VarNum < Metadata.size());
340 constexpr bool IsImplicit = false;
341 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700342 }
343 }
344}
345
346bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700347 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700348 if (Var->getIsArg())
349 return false;
350 if (!isTracked(Var))
351 return true; // conservative answer
352 SizeT VarNum = Var->getIndex();
353 // Conservatively return true if the state is unknown.
354 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
355}
356
357bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700358 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700359 return true;
Jim Stichnothad403532014-09-25 12:44:17 -0700360 if (!isTracked(Var))
361 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700362 SizeT VarNum = Var->getIndex();
363 // Conservatively return true if the state is unknown.
364 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
365}
366
Jim Stichnothad403532014-09-25 12:44:17 -0700367const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700368 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700369 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800370 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700371 SizeT VarNum = Var->getIndex();
Jim Stichnothad403532014-09-25 12:44:17 -0700372 return Metadata[VarNum].getFirstDefinition();
373}
374
375const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700376 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700377 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800378 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700379 SizeT VarNum = Var->getIndex();
380 return Metadata[VarNum].getSingleDefinition();
381}
382
383const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700384VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
385 assert(Kind == VMK_All);
Jim Stichnothad403532014-09-25 12:44:17 -0700386 if (!isTracked(Var))
387 return NoDefinitions;
388 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700389 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700390}
391
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700392CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700393 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800394 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700395 SizeT VarNum = Var->getIndex();
396 return Metadata[VarNum].getNode();
397}
398
Andrew Scullaa6c1092015-09-03 17:50:30 -0700399RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
Andrew Scull11c9a322015-08-28 14:24:14 -0700400 if (!isTracked(Var))
Andrew Scullaa6c1092015-09-03 17:50:30 -0700401 return RegWeight(1); // conservative answer
Andrew Scull11c9a322015-08-28 14:24:14 -0700402 SizeT VarNum = Var->getIndex();
403 return Metadata[VarNum].getUseWeight();
404}
405
Jim Stichnothad403532014-09-25 12:44:17 -0700406const InstDefList VariablesMetadata::NoDefinitions;
407
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700408// ======================== dump routines ======================== //
409
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700410void Variable::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700411 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800412 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700413}
414
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700415void Variable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700416 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800417 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800418 if (Func == nullptr) {
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800419 Str << "%" << getName(Func);
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700420 return;
421 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800422 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700423 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800424 Str << "%" << getName(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700425 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800426 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700427 Str << ":";
428 Str << Func->getTarget()->getRegName(RegNum, getType());
429 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800430 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700431 Str << ":";
Jan Voung28068ad2015-07-31 12:58:46 -0700432 int32_t BaseRegisterNumber = getBaseRegNum();
433 if (BaseRegisterNumber == NoRegister)
434 BaseRegisterNumber = Func->getTarget()->getFrameOrStackReg();
Jim Stichnothdd842db2015-01-27 12:53:53 -0800435 Str << "["
Jan Voung28068ad2015-07-31 12:58:46 -0700436 << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700437 int32_t Offset = getStackOffset();
438 if (Offset) {
439 if (Offset > 0)
440 Str << "+";
441 Str << Offset;
442 }
443 Str << "]";
444 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700445}
446
Jan Voung76bb0be2015-05-14 09:26:19 -0700447template <> void ConstantInteger32::emit(TargetLowering *Target) const {
448 Target->emit(this);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700449}
450
Jan Voung76bb0be2015-05-14 09:26:19 -0700451template <> void ConstantInteger64::emit(TargetLowering *Target) const {
452 Target->emit(this);
453}
454
455template <> void ConstantFloat::emit(TargetLowering *Target) const {
456 Target->emit(this);
457}
458
459template <> void ConstantDouble::emit(TargetLowering *Target) const {
460 Target->emit(this);
461}
462
463void ConstantRelocatable::emit(TargetLowering *Target) const {
464 Target->emit(this);
465}
466
467void ConstantRelocatable::emitWithoutPrefix(TargetLowering *Target) const {
468 Target->emitWithoutPrefix(this);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700469}
470
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700471void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700472 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800473 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700474 Str << "@";
475 if (Func && !SuppressMangling) {
476 Str << Func->getContext()->mangleName(Name);
477 } else {
478 Str << Name;
479 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700480 if (Offset)
481 Str << "+" << Offset;
482}
483
Jan Voung76bb0be2015-05-14 09:26:19 -0700484void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
485
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700486void LiveRange::dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700487 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800488 return;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700489 bool First = true;
490 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700491 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700492 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700493 First = false;
494 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700495 }
496}
497
498Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700499 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800500 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700501 L.dump(Str);
502 return Str;
503}
504
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700505Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700506 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800507 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700508 if (W.getWeight() == RegWeight::Inf)
509 Str << "Inf";
510 else
511 Str << W.getWeight();
512 return Str;
513}
514
Qining Lu253dc8a2015-06-22 10:10:23 -0700515// =========== Immediate Randomization and Pooling routines ==============
516// Specialization of the template member function for ConstantInteger32
Andrew Scull57e12682015-09-16 11:30:19 -0700517// TODO(stichnot): try to move this specialization into a target-specific file.
Qining Lu253dc8a2015-06-22 10:10:23 -0700518template <>
519bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
520 uint32_t Threshold = Ctx->getFlags().getRandomizeAndPoolImmediatesThreshold();
521 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None)
522 return false;
523 if (getType() != IceType_i32 && getType() != IceType_i16 &&
524 getType() != IceType_i8)
525 return false;
526 // The Following checks if the signed representation of Value is between
527 // -Threshold/2 and +Threshold/2
528 bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
529 return largerThanThreshold;
530}
531
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700532} // end of namespace Ice