blob: 9338bdc55fd962c3a4be99700db241eb8122b146 [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//===----------------------------------------------------------------------===//
9//
Jim Stichnothd97c7df2014-06-04 11:57:08 -070010// This file implements the Operand class and its target-independent
11// subclasses, primarily for the methods of the Variable class.
Jim Stichnothf7c9a142014-04-29 10:52:43 -070012//
13//===----------------------------------------------------------------------===//
14
15#include "IceCfg.h"
Jim Stichnoth144cdce2014-09-22 16:02:59 -070016#include "IceCfgNode.h"
Jim Stichnothf7c9a142014-04-29 10:52:43 -070017#include "IceInst.h"
18#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070019#include "IceTargetLowering.h" // dumping stack/frame pointer register
Jim Stichnothf7c9a142014-04-29 10:52:43 -070020
21namespace Ice {
22
Jim Stichnothd2cb4362014-11-20 11:24:42 -080023bool operator==(const RelocatableTuple &A, const RelocatableTuple &B) {
24 return A.Offset == B.Offset && A.Name == B.Name;
Jim Stichnothf7c9a142014-04-29 10:52:43 -070025}
26
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070027bool operator<(const RegWeight &A, const RegWeight &B) {
28 return A.getWeight() < B.getWeight();
29}
30bool operator<=(const RegWeight &A, const RegWeight &B) { return !(B < A); }
31bool operator==(const RegWeight &A, const RegWeight &B) {
32 return !(B < A) && !(A < B);
33}
34
Jim Stichnothd97c7df2014-06-04 11:57:08 -070035void LiveRange::addSegment(InstNumberT Start, InstNumberT End) {
Jim Stichnothe5b73e62014-12-15 09:58:51 -080036 if (!Range.empty()) {
37 // Check for merge opportunity.
38 InstNumberT CurrentEnd = Range.back().second;
39 assert(Start >= CurrentEnd);
40 if (Start == CurrentEnd) {
41 Range.back().second = End;
42 return;
43 }
Jim Stichnothd97c7df2014-06-04 11:57:08 -070044 }
45 Range.push_back(RangeElementType(Start, End));
Jim Stichnothd97c7df2014-06-04 11:57:08 -070046}
47
48// Returns true if this live range ends before Other's live range
49// starts. This means that the highest instruction number in this
50// live range is less than or equal to the lowest instruction number
51// of the Other live range.
52bool LiveRange::endsBefore(const LiveRange &Other) const {
53 // Neither range should be empty, but let's be graceful.
54 if (Range.empty() || Other.Range.empty())
55 return true;
56 InstNumberT MyEnd = (*Range.rbegin()).second;
57 InstNumberT OtherStart = (*Other.Range.begin()).first;
58 return MyEnd <= OtherStart;
59}
60
61// Returns true if there is any overlap between the two live ranges.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070062bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
Jim Stichnothd97c7df2014-06-04 11:57:08 -070063 // Do a two-finger walk through the two sorted lists of segments.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070064 auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
65 I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
66 auto E1 = Range.end(), E2 = Other.Range.end();
Jim Stichnothd97c7df2014-06-04 11:57:08 -070067 while (I1 != E1 && I2 != E2) {
68 if (I1->second <= I2->first) {
69 ++I1;
70 continue;
71 }
72 if (I2->second <= I1->first) {
73 ++I2;
74 continue;
75 }
76 return true;
77 }
78 return false;
79}
80
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070081bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
Jim Stichnothc4554d72014-09-30 16:49:38 -070082 bool Result = false;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070083 for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
84 I != E; ++I) {
85 if (OtherBegin < I->first) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070086 Result = false;
87 break;
88 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070089 if (OtherBegin < I->second) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070090 Result = true;
91 break;
92 }
93 }
94#if 0
95 // An equivalent but less inefficient implementation:
Jim Stichnothd97c7df2014-06-04 11:57:08 -070096 LiveRange Temp;
97 Temp.addSegment(OtherBegin, OtherBegin + 1);
Jim Stichnothc4554d72014-09-30 16:49:38 -070098 bool Validation = overlaps(Temp);
99 assert(Result == Validation);
100#endif
101 return Result;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700102}
103
104// Returns true if the live range contains the given instruction
105// number. This is only used for validating the live range
Jim Stichnoth47752552014-10-13 17:15:08 -0700106// calculation. The IsDest argument indicates whether the Variable
107// being tested is used in the Dest position (as opposed to a Src
108// position).
109bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700110 for (const RangeElementType &I : Range) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700111 if (I.first <= Value &&
112 (Value < I.second || (!IsDest && Value == I.second)))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700113 return true;
114 }
115 return false;
116}
117
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700118void LiveRange::trim(InstNumberT Lower) {
119 while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
120 ++TrimmedBegin;
121}
122
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800123IceString Variable::getName(const Cfg *Func) const {
124 if (Func && NameIndex >= 0)
125 return Func->getIdentifierName(NameIndex);
Jim Stichnoth088b2be2014-10-23 12:02:08 -0700126 return "__" + std::to_string(getIndex());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700127}
128
Jim Stichnoth31c95592014-12-19 12:51:35 -0800129Variable *Variable::asType(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700130 // Note: This returns a Variable, even if the "this" object is a
131 // subclass of Variable.
Jim Stichnoth31c95592014-12-19 12:51:35 -0800132 if (!ALLOW_DUMP || getType() == Ty)
133 return this;
134 Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
135 Variable(kVariable, Ty, Number);
136 V->NameIndex = NameIndex;
137 V->RegNum = RegNum;
138 V->StackOffset = StackOffset;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700139 return V;
140}
141
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700142void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
143 const CfgNode *Node, bool IsFromDef,
144 bool IsImplicit) {
145 (void)TrackingKind;
Jim Stichnoth47752552014-10-13 17:15:08 -0700146 if (MultiBlock == MBS_MultiBlock)
147 return;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700148 // TODO(stichnot): If the use occurs as a source operand in the
149 // first instruction of the block, and its definition is in this
150 // block's only predecessor, we might consider not marking this as a
151 // separate use. This may also apply if it's the first instruction
152 // of the block that actually uses a Variable.
153 assert(Node);
154 bool MakeMulti = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700155 if (IsImplicit)
156 MakeMulti = true;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700157 // A phi source variable conservatively needs to be marked as
158 // multi-block, even if its definition is in the same block. This
159 // is because there can be additional control flow before branching
160 // back to this node, and the variable is live throughout those
161 // nodes.
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700162 if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr))
163 MakeMulti = true;
164
165 if (!MakeMulti) {
166 switch (MultiBlock) {
167 case MBS_Unknown:
168 MultiBlock = MBS_SingleBlock;
169 SingleUseNode = Node;
170 break;
171 case MBS_SingleBlock:
172 if (SingleUseNode != Node)
173 MakeMulti = true;
174 break;
175 case MBS_MultiBlock:
176 break;
177 }
178 }
179
180 if (MakeMulti) {
181 MultiBlock = MBS_MultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800182 SingleUseNode = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700183 }
184}
185
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700186void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
187 const CfgNode *Node) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700188 // TODO(stichnot): If the definition occurs in the last instruction
189 // of the block, consider not marking this as a separate use. But
190 // be careful not to omit all uses of the variable if markDef() and
191 // markUse() both use this optimization.
Jim Stichnothad403532014-09-25 12:44:17 -0700192 assert(Node);
Jim Stichnothdd842db2015-01-27 12:53:53 -0800193// Verify that instructions are added in increasing order.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700194#ifndef NDEBUG
195 if (TrackingKind == VMK_All) {
196 const Inst *LastInstruction =
197 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
Jim Stichnothae953202014-12-20 06:17:49 -0800198 assert(LastInstruction == nullptr ||
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700199 Instr->getNumber() >= LastInstruction->getNumber());
200 }
201#endif
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700202 const bool IsFromDef = true;
203 const bool IsImplicit = false;
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700204 markUse(TrackingKind, Instr, Node, IsFromDef, IsImplicit);
205 if (TrackingKind == VMK_Uses)
206 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800207 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700208 FirstOrSingleDefinition = Instr;
209 else if (TrackingKind == VMK_All)
210 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700211 switch (MultiDef) {
212 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800213 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700214 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700215 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700216 break;
217 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700218 assert(SingleDefNode);
219 if (Node == SingleDefNode) {
220 MultiDef = MDS_MultiDefSingleBlock;
221 } else {
222 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800223 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700224 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700225 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700226 case MDS_MultiDefSingleBlock:
227 assert(SingleDefNode);
228 if (Node != SingleDefNode) {
229 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800230 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700231 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700232 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700233 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800234 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700235 break;
236 }
237}
238
239const Inst *VariableTracking::getFirstDefinition() const {
240 switch (MultiDef) {
241 case MDS_Unknown:
242 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800243 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700244 case MDS_SingleDef:
245 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700246 assert(FirstOrSingleDefinition);
247 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700248 }
Jim Stichnothae953202014-12-20 06:17:49 -0800249 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700250}
251
252const Inst *VariableTracking::getSingleDefinition() const {
253 switch (MultiDef) {
254 case MDS_Unknown:
255 case MDS_MultiDefMultiBlock:
256 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800257 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700258 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700259 assert(FirstOrSingleDefinition);
260 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700261 }
Jim Stichnothae953202014-12-20 06:17:49 -0800262 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700263}
264
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700265void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700266 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700267 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700268 Metadata.clear();
269 Metadata.resize(Func->getNumVariables());
270
271 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700272 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnothae953202014-12-20 06:17:49 -0800273 const Inst *NoInst = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700274 const CfgNode *EntryNode = Func->getEntryNode();
275 const bool IsFromDef = false;
276 const bool IsImplicit = true;
Jim Stichnothdd842db2015-01-27 12:53:53 -0800277 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsFromDef,
278 IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700279 }
280
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700281 for (CfgNode *Node : Func->getNodes())
282 addNode(Node);
283}
284
285void VariablesMetadata::addNode(CfgNode *Node) {
286 if (Func->getNumVariables() >= Metadata.size())
287 Metadata.resize(Func->getNumVariables());
288
Jim Stichnoth29841e82014-12-23 12:26:24 -0800289 for (Inst &I : Node->getPhis()) {
290 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700291 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800292 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700293 SizeT DestNum = Dest->getIndex();
294 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800295 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700296 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800297 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
298 if (const Variable *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700299 SizeT VarNum = Var->getIndex();
300 assert(VarNum < Metadata.size());
301 const bool IsFromDef = false;
302 const bool IsImplicit = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800303 Metadata[VarNum].markUse(Kind, &I, Node, IsFromDef, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700304 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700305 }
306 }
307
Jim Stichnoth29841e82014-12-23 12:26:24 -0800308 for (Inst &I : Node->getInsts()) {
309 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700310 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800311 // Note: The implicit definitions (and uses) from InstFakeKill are
312 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800313 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700314 SizeT DestNum = Dest->getIndex();
315 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800316 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700317 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800318 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
319 Operand *Src = I.getSrc(SrcNum);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700320 SizeT NumVars = Src->getNumVars();
321 for (SizeT J = 0; J < NumVars; ++J) {
322 const Variable *Var = Src->getVar(J);
323 SizeT VarNum = Var->getIndex();
324 assert(VarNum < Metadata.size());
325 const bool IsFromDef = false;
326 const bool IsImplicit = false;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800327 Metadata[VarNum].markUse(Kind, &I, Node, IsFromDef, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700328 }
329 }
330 }
331}
332
333bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700334 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700335 if (Var->getIsArg())
336 return false;
337 if (!isTracked(Var))
338 return true; // conservative answer
339 SizeT VarNum = Var->getIndex();
340 // Conservatively return true if the state is unknown.
341 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
342}
343
344bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700345 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700346 return true;
Jim Stichnothad403532014-09-25 12:44:17 -0700347 if (!isTracked(Var))
348 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700349 SizeT VarNum = Var->getIndex();
350 // Conservatively return true if the state is unknown.
351 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
352}
353
Jim Stichnothad403532014-09-25 12:44:17 -0700354const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700355 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700356 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800357 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700358 SizeT VarNum = Var->getIndex();
Jim Stichnothad403532014-09-25 12:44:17 -0700359 return Metadata[VarNum].getFirstDefinition();
360}
361
362const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700363 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700364 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800365 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700366 SizeT VarNum = Var->getIndex();
367 return Metadata[VarNum].getSingleDefinition();
368}
369
370const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700371VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
372 assert(Kind == VMK_All);
Jim Stichnothad403532014-09-25 12:44:17 -0700373 if (!isTracked(Var))
374 return NoDefinitions;
375 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700376 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700377}
378
379const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
380 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800381 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700382 SizeT VarNum = Var->getIndex();
383 return Metadata[VarNum].getNode();
384}
385
Jim Stichnothad403532014-09-25 12:44:17 -0700386const InstDefList VariablesMetadata::NoDefinitions;
387
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700388// ======================== dump routines ======================== //
389
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700390void Variable::emit(const Cfg *Func) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800391 if (ALLOW_DUMP)
392 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700393}
394
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700395void Variable::dump(const Cfg *Func, Ostream &Str) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800396 if (!ALLOW_DUMP)
397 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800398 if (Func == nullptr) {
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800399 Str << "%" << getName(Func);
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700400 return;
401 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800402 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700403 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800404 Str << "%" << getName(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700405 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800406 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700407 Str << ":";
408 Str << Func->getTarget()->getRegName(RegNum, getType());
409 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800410 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700411 Str << ":";
Jim Stichnothdd842db2015-01-27 12:53:53 -0800412 Str << "["
413 << Func->getTarget()->getRegName(
414 Func->getTarget()->getFrameOrStackReg(), IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700415 int32_t Offset = getStackOffset();
416 if (Offset) {
417 if (Offset > 0)
418 Str << "+";
419 Str << Offset;
420 }
421 Str << "]";
422 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700423}
424
Jim Stichnothbca2f652014-11-01 10:13:54 -0700425void ConstantRelocatable::emitWithoutDollar(GlobalContext *Ctx) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800426 if (!ALLOW_DUMP)
427 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700428 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700429 if (SuppressMangling)
430 Str << Name;
431 else
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700432 Str << Ctx->mangleName(Name);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700433 if (Offset) {
434 if (Offset > 0)
435 Str << "+";
436 Str << Offset;
437 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700438}
439
Jim Stichnothbca2f652014-11-01 10:13:54 -0700440void ConstantRelocatable::emit(GlobalContext *Ctx) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800441 if (!ALLOW_DUMP)
442 return;
Jim Stichnothbca2f652014-11-01 10:13:54 -0700443 Ostream &Str = Ctx->getStrEmit();
444 Str << "$";
445 emitWithoutDollar(Ctx);
446}
447
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700448void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800449 if (!ALLOW_DUMP)
450 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700451 Str << "@";
452 if (Func && !SuppressMangling) {
453 Str << Func->getContext()->mangleName(Name);
454 } else {
455 Str << Name;
456 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700457 if (Offset)
458 Str << "+" << Offset;
459}
460
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700461void LiveRange::dump(Ostream &Str) const {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800462 if (!ALLOW_DUMP)
463 return;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700464 Str << "(weight=" << Weight << ") ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700465 bool First = true;
466 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700467 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700468 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700469 First = false;
470 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700471 }
472}
473
474Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800475 if (!ALLOW_DUMP)
476 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700477 L.dump(Str);
478 return Str;
479}
480
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700481Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800482 if (!ALLOW_DUMP)
483 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700484 if (W.getWeight() == RegWeight::Inf)
485 Str << "Inf";
486 else
487 Str << W.getWeight();
488 return Str;
489}
490
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700491} // end of namespace Ice