blob: 2013dcfa0c669d9a75507dda4c51a41f30c91785 [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
51// Returns true if this live range ends before Other's live range
52// starts. This means that the highest instruction number in this
53// live range is less than or equal to the lowest instruction number
54// of the Other live range.
55bool LiveRange::endsBefore(const LiveRange &Other) const {
56 // Neither range should be empty, but let's be graceful.
57 if (Range.empty() || Other.Range.empty())
58 return true;
59 InstNumberT MyEnd = (*Range.rbegin()).second;
60 InstNumberT OtherStart = (*Other.Range.begin()).first;
61 return MyEnd <= OtherStart;
62}
63
64// Returns true if there is any overlap between the two live ranges.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070065bool LiveRange::overlaps(const LiveRange &Other, bool UseTrimmed) const {
Jim Stichnothd97c7df2014-06-04 11:57:08 -070066 // Do a two-finger walk through the two sorted lists of segments.
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070067 auto I1 = (UseTrimmed ? TrimmedBegin : Range.begin()),
68 I2 = (UseTrimmed ? Other.TrimmedBegin : Other.Range.begin());
69 auto E1 = Range.end(), E2 = Other.Range.end();
Jim Stichnothd97c7df2014-06-04 11:57:08 -070070 while (I1 != E1 && I2 != E2) {
71 if (I1->second <= I2->first) {
72 ++I1;
73 continue;
74 }
75 if (I2->second <= I1->first) {
76 ++I2;
77 continue;
78 }
79 return true;
80 }
81 return false;
82}
83
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070084bool LiveRange::overlapsInst(InstNumberT OtherBegin, bool UseTrimmed) const {
Jim Stichnothc4554d72014-09-30 16:49:38 -070085 bool Result = false;
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070086 for (auto I = (UseTrimmed ? TrimmedBegin : Range.begin()), E = Range.end();
87 I != E; ++I) {
88 if (OtherBegin < I->first) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070089 Result = false;
90 break;
91 }
Jim Stichnoth037fa1d2014-10-07 11:09:33 -070092 if (OtherBegin < I->second) {
Jim Stichnothc4554d72014-09-30 16:49:38 -070093 Result = true;
94 break;
95 }
96 }
Jim Stichnoth20b71f52015-06-24 15:52:24 -070097 // This is an equivalent but less inefficient implementation. It's
98 // expensive enough that we wouldn't want to run it under any build,
99 // but it could be enabled if e.g. the LiveRange implementation
100 // changes and extra testing is needed.
101 if (BuildDefs::extraValidation()) {
102 LiveRange Temp;
103 Temp.addSegment(OtherBegin, OtherBegin + 1);
104 bool Validation = overlaps(Temp);
105 (void)Validation;
106 assert(Result == Validation);
107 }
Jim Stichnothc4554d72014-09-30 16:49:38 -0700108 return Result;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700109}
110
111// Returns true if the live range contains the given instruction
112// number. This is only used for validating the live range
Jim Stichnoth47752552014-10-13 17:15:08 -0700113// calculation. The IsDest argument indicates whether the Variable
114// being tested is used in the Dest position (as opposed to a Src
115// position).
116bool LiveRange::containsValue(InstNumberT Value, bool IsDest) const {
Jim Stichnothf44f3712014-10-01 14:05:51 -0700117 for (const RangeElementType &I : Range) {
Jim Stichnoth47752552014-10-13 17:15:08 -0700118 if (I.first <= Value &&
119 (Value < I.second || (!IsDest && Value == I.second)))
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700120 return true;
121 }
122 return false;
123}
124
Jim Stichnoth037fa1d2014-10-07 11:09:33 -0700125void LiveRange::trim(InstNumberT Lower) {
126 while (TrimmedBegin != Range.end() && TrimmedBegin->second <= Lower)
127 ++TrimmedBegin;
128}
129
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800130IceString Variable::getName(const Cfg *Func) const {
131 if (Func && NameIndex >= 0)
132 return Func->getIdentifierName(NameIndex);
Jim Stichnoth088b2be2014-10-23 12:02:08 -0700133 return "__" + std::to_string(getIndex());
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700134}
135
Jim Stichnoth31c95592014-12-19 12:51:35 -0800136Variable *Variable::asType(Type Ty) {
Jim Stichnoth800dab22014-09-20 12:25:02 -0700137 // Note: This returns a Variable, even if the "this" object is a
138 // subclass of Variable.
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700139 if (!BuildDefs::dump() || getType() == Ty)
Jim Stichnoth31c95592014-12-19 12:51:35 -0800140 return this;
141 Variable *V = new (getCurrentCfgAllocator()->Allocate<Variable>())
142 Variable(kVariable, Ty, Number);
143 V->NameIndex = NameIndex;
144 V->RegNum = RegNum;
145 V->StackOffset = StackOffset;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700146 return V;
147}
148
Andrew Scull11c9a322015-08-28 14:24:14 -0700149RegWeight Variable::getWeight(const Cfg *Func) const {
150 VariablesMetadata *VMetadata = Func->getVMetadata();
Andrew Scullaa6c1092015-09-03 17:50:30 -0700151 return mustHaveReg() ? RegWeight(RegWeight::Inf)
152 : mustNotHaveReg() ? RegWeight(RegWeight::Zero)
153 : VMetadata->getUseWeight(this);
Andrew Scull11c9a322015-08-28 14:24:14 -0700154}
155
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700156void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700157 CfgNode *Node, bool IsImplicit) {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700158 (void)TrackingKind;
Andrew Scull11c9a322015-08-28 14:24:14 -0700159
Andrew Scullaa6c1092015-09-03 17:50:30 -0700160 // Increment the use weight depending on the loop nest depth. The weight is
161 // exponential in the nest depth as inner loops are expected to be executed
162 // an exponentially greater number of times.
163 constexpr uint32_t LogLoopTripCountEstimate = 2; // 2^2 = 4
164 constexpr SizeT MaxShift = sizeof(uint32_t) * CHAR_BIT - 1;
165 constexpr SizeT MaxLoopNestDepth = MaxShift / LogLoopTripCountEstimate;
166 const uint32_t LoopNestDepth =
167 std::min(Node->getLoopNestDepth(), MaxLoopNestDepth);
168 const uint32_t ThisUseWeight = uint32_t(1)
169 << LoopNestDepth * LogLoopTripCountEstimate;
170 UseWeight.addWeight(ThisUseWeight);
Andrew Scull11c9a322015-08-28 14:24:14 -0700171
Jim Stichnoth47752552014-10-13 17:15:08 -0700172 if (MultiBlock == MBS_MultiBlock)
173 return;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700174 // TODO(stichnot): If the use occurs as a source operand in the
175 // first instruction of the block, and its definition is in this
176 // block's only predecessor, we might consider not marking this as a
177 // separate use. This may also apply if it's the first instruction
178 // of the block that actually uses a Variable.
179 assert(Node);
180 bool MakeMulti = false;
Jim Stichnothad403532014-09-25 12:44:17 -0700181 if (IsImplicit)
182 MakeMulti = true;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700183 // A phi source variable conservatively needs to be marked as
184 // multi-block, even if its definition is in the same block. This
185 // is because there can be additional control flow before branching
186 // back to this node, and the variable is live throughout those
187 // nodes.
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700188 if (Instr && llvm::isa<InstPhi>(Instr))
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700189 MakeMulti = true;
190
191 if (!MakeMulti) {
192 switch (MultiBlock) {
193 case MBS_Unknown:
194 MultiBlock = MBS_SingleBlock;
195 SingleUseNode = Node;
196 break;
197 case MBS_SingleBlock:
198 if (SingleUseNode != Node)
199 MakeMulti = true;
200 break;
201 case MBS_MultiBlock:
202 break;
203 }
204 }
205
206 if (MakeMulti) {
207 MultiBlock = MBS_MultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800208 SingleUseNode = nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700209 }
210}
211
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700212void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr,
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700213 CfgNode *Node) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700214 // TODO(stichnot): If the definition occurs in the last instruction
215 // of the block, consider not marking this as a separate use. But
216 // be careful not to omit all uses of the variable if markDef() and
217 // markUse() both use this optimization.
Jim Stichnothad403532014-09-25 12:44:17 -0700218 assert(Node);
Jim Stichnothdd842db2015-01-27 12:53:53 -0800219// Verify that instructions are added in increasing order.
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700220#ifndef NDEBUG
221 if (TrackingKind == VMK_All) {
222 const Inst *LastInstruction =
223 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
Jim Stichnothae953202014-12-20 06:17:49 -0800224 assert(LastInstruction == nullptr ||
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700225 Instr->getNumber() >= LastInstruction->getNumber());
226 }
227#endif
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700228 constexpr bool IsImplicit = false;
229 markUse(TrackingKind, Instr, Node, IsImplicit);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700230 if (TrackingKind == VMK_Uses)
231 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800232 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700233 FirstOrSingleDefinition = Instr;
234 else if (TrackingKind == VMK_All)
235 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700236 switch (MultiDef) {
237 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800238 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700239 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700240 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700241 break;
242 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700243 assert(SingleDefNode);
244 if (Node == SingleDefNode) {
245 MultiDef = MDS_MultiDefSingleBlock;
246 } else {
247 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800248 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700249 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700250 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700251 case MDS_MultiDefSingleBlock:
252 assert(SingleDefNode);
253 if (Node != SingleDefNode) {
254 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800255 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700256 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700257 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700258 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800259 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700260 break;
261 }
262}
263
264const Inst *VariableTracking::getFirstDefinition() const {
265 switch (MultiDef) {
266 case MDS_Unknown:
267 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800268 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700269 case MDS_SingleDef:
270 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700271 assert(FirstOrSingleDefinition);
272 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700273 }
Jim Stichnothae953202014-12-20 06:17:49 -0800274 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700275}
276
277const Inst *VariableTracking::getSingleDefinition() const {
278 switch (MultiDef) {
279 case MDS_Unknown:
280 case MDS_MultiDefMultiBlock:
281 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800282 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700283 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700284 assert(FirstOrSingleDefinition);
285 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700286 }
Jim Stichnothae953202014-12-20 06:17:49 -0800287 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700288}
289
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700290void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700291 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700292 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700293 Metadata.clear();
294 Metadata.resize(Func->getNumVariables());
295
296 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700297 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700298 constexpr Inst *NoInst = nullptr;
299 CfgNode *EntryNode = Func->getEntryNode();
300 constexpr bool IsImplicit = true;
301 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700302 }
303
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700304 for (CfgNode *Node : Func->getNodes())
305 addNode(Node);
306}
307
308void VariablesMetadata::addNode(CfgNode *Node) {
309 if (Func->getNumVariables() >= Metadata.size())
310 Metadata.resize(Func->getNumVariables());
311
Jim Stichnoth29841e82014-12-23 12:26:24 -0800312 for (Inst &I : Node->getPhis()) {
313 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700314 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800315 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700316 SizeT DestNum = Dest->getIndex();
317 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800318 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700319 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800320 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
321 if (const Variable *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700322 SizeT VarNum = Var->getIndex();
323 assert(VarNum < Metadata.size());
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700324 constexpr bool IsImplicit = false;
325 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700326 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700327 }
328 }
329
Jim Stichnoth29841e82014-12-23 12:26:24 -0800330 for (Inst &I : Node->getInsts()) {
331 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700332 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800333 // Note: The implicit definitions (and uses) from InstFakeKill are
334 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800335 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700336 SizeT DestNum = Dest->getIndex();
337 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800338 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700339 }
John Portoec3f5652015-08-31 15:07:09 -0700340 FOREACH_VAR_IN_INST(Var, I) {
341 SizeT VarNum = Var->getIndex();
342 assert(VarNum < Metadata.size());
343 constexpr bool IsImplicit = false;
344 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700345 }
346 }
347}
348
349bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700350 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700351 if (Var->getIsArg())
352 return false;
353 if (!isTracked(Var))
354 return true; // conservative answer
355 SizeT VarNum = Var->getIndex();
356 // Conservatively return true if the state is unknown.
357 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
358}
359
360bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700361 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700362 return true;
Jim Stichnothad403532014-09-25 12:44:17 -0700363 if (!isTracked(Var))
364 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700365 SizeT VarNum = Var->getIndex();
366 // Conservatively return true if the state is unknown.
367 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
368}
369
Jim Stichnothad403532014-09-25 12:44:17 -0700370const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700371 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700372 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800373 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700374 SizeT VarNum = Var->getIndex();
Jim Stichnothad403532014-09-25 12:44:17 -0700375 return Metadata[VarNum].getFirstDefinition();
376}
377
378const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700379 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700380 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800381 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700382 SizeT VarNum = Var->getIndex();
383 return Metadata[VarNum].getSingleDefinition();
384}
385
386const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700387VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
388 assert(Kind == VMK_All);
Jim Stichnothad403532014-09-25 12:44:17 -0700389 if (!isTracked(Var))
390 return NoDefinitions;
391 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700392 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700393}
394
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700395CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700396 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800397 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700398 SizeT VarNum = Var->getIndex();
399 return Metadata[VarNum].getNode();
400}
401
Andrew Scullaa6c1092015-09-03 17:50:30 -0700402RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
Andrew Scull11c9a322015-08-28 14:24:14 -0700403 if (!isTracked(Var))
Andrew Scullaa6c1092015-09-03 17:50:30 -0700404 return RegWeight(1); // conservative answer
Andrew Scull11c9a322015-08-28 14:24:14 -0700405 SizeT VarNum = Var->getIndex();
406 return Metadata[VarNum].getUseWeight();
407}
408
Jim Stichnothad403532014-09-25 12:44:17 -0700409const InstDefList VariablesMetadata::NoDefinitions;
410
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700411// ======================== dump routines ======================== //
412
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700413void Variable::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700414 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800415 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700416}
417
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700418void Variable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700419 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800420 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800421 if (Func == nullptr) {
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800422 Str << "%" << getName(Func);
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700423 return;
424 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800425 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700426 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800427 Str << "%" << getName(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700428 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800429 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700430 Str << ":";
431 Str << Func->getTarget()->getRegName(RegNum, getType());
432 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800433 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700434 Str << ":";
Jan Voung28068ad2015-07-31 12:58:46 -0700435 int32_t BaseRegisterNumber = getBaseRegNum();
436 if (BaseRegisterNumber == NoRegister)
437 BaseRegisterNumber = Func->getTarget()->getFrameOrStackReg();
Jim Stichnothdd842db2015-01-27 12:53:53 -0800438 Str << "["
Jan Voung28068ad2015-07-31 12:58:46 -0700439 << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700440 int32_t Offset = getStackOffset();
441 if (Offset) {
442 if (Offset > 0)
443 Str << "+";
444 Str << Offset;
445 }
446 Str << "]";
447 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700448}
449
Jan Voung76bb0be2015-05-14 09:26:19 -0700450template <> void ConstantInteger32::emit(TargetLowering *Target) const {
451 Target->emit(this);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700452}
453
Jan Voung76bb0be2015-05-14 09:26:19 -0700454template <> void ConstantInteger64::emit(TargetLowering *Target) const {
455 Target->emit(this);
456}
457
458template <> void ConstantFloat::emit(TargetLowering *Target) const {
459 Target->emit(this);
460}
461
462template <> void ConstantDouble::emit(TargetLowering *Target) const {
463 Target->emit(this);
464}
465
466void ConstantRelocatable::emit(TargetLowering *Target) const {
467 Target->emit(this);
468}
469
470void ConstantRelocatable::emitWithoutPrefix(TargetLowering *Target) const {
471 Target->emitWithoutPrefix(this);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700472}
473
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700474void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700475 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800476 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700477 Str << "@";
478 if (Func && !SuppressMangling) {
479 Str << Func->getContext()->mangleName(Name);
480 } else {
481 Str << Name;
482 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700483 if (Offset)
484 Str << "+" << Offset;
485}
486
Jan Voung76bb0be2015-05-14 09:26:19 -0700487void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
488
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700489void LiveRange::dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700490 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800491 return;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700492 bool First = true;
493 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700494 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700495 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700496 First = false;
497 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700498 }
499}
500
501Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700502 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800503 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700504 L.dump(Str);
505 return Str;
506}
507
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700508Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700509 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800510 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700511 if (W.getWeight() == RegWeight::Inf)
512 Str << "Inf";
513 else
514 Str << W.getWeight();
515 return Str;
516}
517
Qining Lu253dc8a2015-06-22 10:10:23 -0700518// =========== Immediate Randomization and Pooling routines ==============
519// Specialization of the template member function for ConstantInteger32
520// TODO(stichnot): try to move this specialization into a target-specific
521// file.
522template <>
523bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
524 uint32_t Threshold = Ctx->getFlags().getRandomizeAndPoolImmediatesThreshold();
525 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None)
526 return false;
527 if (getType() != IceType_i32 && getType() != IceType_i16 &&
528 getType() != IceType_i8)
529 return false;
530 // The Following checks if the signed representation of Value is between
531 // -Threshold/2 and +Threshold/2
532 bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
533 return largerThanThreshold;
534}
535
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700536} // end of namespace Ice