blob: b46c7f5142b79402eb05a9a1da765ef9e716f179 [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"
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 Stichnoth5bff61c2015-10-28 09:26:00 -0700134const Variable *Variable::asType(Type Ty, int32_t NewRegNum) const {
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;
Jim Stichnoth5bff61c2015-10-28 09:26:00 -0700142 V->RegNum = NewRegNum == NoRegister ? RegNum : NewRegNum;
Jim Stichnoth31c95592014-12-19 12:51:35 -0800143 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 Stichnoth48e3ae52015-10-01 13:33:35 -0700216 // Verify that instructions are added in increasing order.
217 if (BuildDefs::asserts()) {
218 if (TrackingKind == VMK_All) {
219 const Inst *LastInstruction =
220 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back();
221 (void)LastInstruction;
222 assert(LastInstruction == nullptr ||
223 Instr->getNumber() >= LastInstruction->getNumber());
224 }
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700225 }
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700226 constexpr bool IsImplicit = false;
227 markUse(TrackingKind, Instr, Node, IsImplicit);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700228 if (TrackingKind == VMK_Uses)
229 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800230 if (FirstOrSingleDefinition == nullptr)
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700231 FirstOrSingleDefinition = Instr;
232 else if (TrackingKind == VMK_All)
233 Definitions.push_back(Instr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700234 switch (MultiDef) {
235 case MDS_Unknown:
Jim Stichnothae953202014-12-20 06:17:49 -0800236 assert(SingleDefNode == nullptr);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700237 MultiDef = MDS_SingleDef;
Jim Stichnothad403532014-09-25 12:44:17 -0700238 SingleDefNode = Node;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700239 break;
240 case MDS_SingleDef:
Jim Stichnothad403532014-09-25 12:44:17 -0700241 assert(SingleDefNode);
242 if (Node == SingleDefNode) {
243 MultiDef = MDS_MultiDefSingleBlock;
244 } else {
245 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800246 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700247 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700248 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700249 case MDS_MultiDefSingleBlock:
250 assert(SingleDefNode);
251 if (Node != SingleDefNode) {
252 MultiDef = MDS_MultiDefMultiBlock;
Jim Stichnothae953202014-12-20 06:17:49 -0800253 SingleDefNode = nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700254 }
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700255 break;
Jim Stichnothad403532014-09-25 12:44:17 -0700256 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800257 assert(SingleDefNode == nullptr);
Jim Stichnothad403532014-09-25 12:44:17 -0700258 break;
259 }
260}
261
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700262const Inst *VariableTracking::getFirstDefinitionSingleBlock() const {
Jim Stichnothad403532014-09-25 12:44:17 -0700263 switch (MultiDef) {
264 case MDS_Unknown:
265 case MDS_MultiDefMultiBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800266 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700267 case MDS_SingleDef:
268 case MDS_MultiDefSingleBlock:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700269 assert(FirstOrSingleDefinition);
270 return FirstOrSingleDefinition;
Jim Stichnothad403532014-09-25 12:44:17 -0700271 }
Jim Stichnothae953202014-12-20 06:17:49 -0800272 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700273}
274
275const Inst *VariableTracking::getSingleDefinition() const {
276 switch (MultiDef) {
277 case MDS_Unknown:
278 case MDS_MultiDefMultiBlock:
279 case MDS_MultiDefSingleBlock:
Jim Stichnothae953202014-12-20 06:17:49 -0800280 return nullptr;
Jim Stichnothad403532014-09-25 12:44:17 -0700281 case MDS_SingleDef:
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700282 assert(FirstOrSingleDefinition);
283 return FirstOrSingleDefinition;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700284 }
Jim Stichnothae953202014-12-20 06:17:49 -0800285 return nullptr;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700286}
287
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700288const Inst *VariableTracking::getFirstDefinition() const {
289 switch (MultiDef) {
290 case MDS_Unknown:
291 return nullptr;
292 case MDS_MultiDefMultiBlock:
293 case MDS_SingleDef:
294 case MDS_MultiDefSingleBlock:
295 assert(FirstOrSingleDefinition);
296 return FirstOrSingleDefinition;
297 }
298 return nullptr;
299}
300
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700301void VariablesMetadata::init(MetadataKind TrackingKind) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700302 TimerMarker T(TimerStack::TT_vmetadata, Func);
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700303 Kind = TrackingKind;
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700304 Metadata.clear();
305 Metadata.resize(Func->getNumVariables());
306
307 // Mark implicit args as being used in the entry node.
Jim Stichnothf44f3712014-10-01 14:05:51 -0700308 for (Variable *Var : Func->getImplicitArgs()) {
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700309 constexpr Inst *NoInst = nullptr;
310 CfgNode *EntryNode = Func->getEntryNode();
311 constexpr bool IsImplicit = true;
312 Metadata[Var->getIndex()].markUse(Kind, NoInst, EntryNode, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700313 }
314
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700315 for (CfgNode *Node : Func->getNodes())
316 addNode(Node);
317}
318
319void VariablesMetadata::addNode(CfgNode *Node) {
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700320 if (Func->getNumVariables() > Metadata.size())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700321 Metadata.resize(Func->getNumVariables());
322
Jim Stichnoth29841e82014-12-23 12:26:24 -0800323 for (Inst &I : Node->getPhis()) {
324 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700325 continue;
Jim Stichnoth29841e82014-12-23 12:26:24 -0800326 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700327 SizeT DestNum = Dest->getIndex();
328 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800329 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700330 }
Jim Stichnoth29841e82014-12-23 12:26:24 -0800331 for (SizeT SrcNum = 0; SrcNum < I.getSrcSize(); ++SrcNum) {
332 if (const Variable *Var = llvm::dyn_cast<Variable>(I.getSrc(SrcNum))) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700333 SizeT VarNum = Var->getIndex();
334 assert(VarNum < Metadata.size());
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700335 constexpr bool IsImplicit = false;
336 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnothad403532014-09-25 12:44:17 -0700337 }
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700338 }
339 }
340
Jim Stichnoth29841e82014-12-23 12:26:24 -0800341 for (Inst &I : Node->getInsts()) {
342 if (I.isDeleted())
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700343 continue;
Jim Stichnothbb8b6242014-11-04 09:10:01 -0800344 // Note: The implicit definitions (and uses) from InstFakeKill are
345 // deliberately ignored.
Jim Stichnoth29841e82014-12-23 12:26:24 -0800346 if (Variable *Dest = I.getDest()) {
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700347 SizeT DestNum = Dest->getIndex();
348 assert(DestNum < Metadata.size());
Jim Stichnoth29841e82014-12-23 12:26:24 -0800349 Metadata[DestNum].markDef(Kind, &I, Node);
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700350 }
John Portoec3f5652015-08-31 15:07:09 -0700351 FOREACH_VAR_IN_INST(Var, I) {
352 SizeT VarNum = Var->getIndex();
353 assert(VarNum < Metadata.size());
354 constexpr bool IsImplicit = false;
355 Metadata[VarNum].markUse(Kind, &I, Node, IsImplicit);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700356 }
357 }
358}
359
360bool VariablesMetadata::isMultiDef(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700361 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700362 if (Var->getIsArg())
363 return false;
364 if (!isTracked(Var))
365 return true; // conservative answer
366 SizeT VarNum = Var->getIndex();
367 // Conservatively return true if the state is unknown.
368 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
369}
370
371bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
Jim Stichnothad403532014-09-25 12:44:17 -0700372 if (Var->getIsArg())
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700373 return true;
Jim Stichnothad403532014-09-25 12:44:17 -0700374 if (!isTracked(Var))
375 return true; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700376 SizeT VarNum = Var->getIndex();
377 // Conservatively return true if the state is unknown.
378 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
379}
380
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700381const Inst *
382VariablesMetadata::getFirstDefinitionSingleBlock(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700383 assert(Kind != VMK_Uses);
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700384 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800385 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700386 SizeT VarNum = Var->getIndex();
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700387 return Metadata[VarNum].getFirstDefinitionSingleBlock();
Jim Stichnothad403532014-09-25 12:44:17 -0700388}
389
390const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const {
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700391 assert(Kind != VMK_Uses);
Jim Stichnothad403532014-09-25 12:44:17 -0700392 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800393 return nullptr; // conservative answer
Jim Stichnothad403532014-09-25 12:44:17 -0700394 SizeT VarNum = Var->getIndex();
395 return Metadata[VarNum].getSingleDefinition();
396}
397
Jim Stichnoth48e3ae52015-10-01 13:33:35 -0700398const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const {
399 assert(Kind != VMK_Uses);
400 if (!isTracked(Var))
401 return nullptr; // conservative answer
402 SizeT VarNum = Var->getIndex();
403 return Metadata[VarNum].getFirstDefinition();
404}
405
Jim Stichnothad403532014-09-25 12:44:17 -0700406const InstDefList &
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700407VariablesMetadata::getLatterDefinitions(const Variable *Var) const {
408 assert(Kind == VMK_All);
Jim Stichnothad403532014-09-25 12:44:17 -0700409 if (!isTracked(Var))
410 return NoDefinitions;
411 SizeT VarNum = Var->getIndex();
Jim Stichnoth877b04e2014-10-15 15:13:06 -0700412 return Metadata[VarNum].getLatterDefinitions();
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700413}
414
Jim Stichnotha3f57b92015-07-30 12:46:04 -0700415CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700416 if (!isTracked(Var))
Jim Stichnothae953202014-12-20 06:17:49 -0800417 return nullptr; // conservative answer
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700418 SizeT VarNum = Var->getIndex();
419 return Metadata[VarNum].getNode();
420}
421
Andrew Scullaa6c1092015-09-03 17:50:30 -0700422RegWeight VariablesMetadata::getUseWeight(const Variable *Var) const {
Andrew Scull11c9a322015-08-28 14:24:14 -0700423 if (!isTracked(Var))
Andrew Scullaa6c1092015-09-03 17:50:30 -0700424 return RegWeight(1); // conservative answer
Andrew Scull11c9a322015-08-28 14:24:14 -0700425 SizeT VarNum = Var->getIndex();
426 return Metadata[VarNum].getUseWeight();
427}
428
Jim Stichnothad403532014-09-25 12:44:17 -0700429const InstDefList VariablesMetadata::NoDefinitions;
430
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700431// ======================== dump routines ======================== //
432
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700433void Variable::emit(const Cfg *Func) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700434 if (BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800435 Func->getTarget()->emitVariable(this);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700436}
437
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700438void Variable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700439 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800440 return;
Jim Stichnothae953202014-12-20 06:17:49 -0800441 if (Func == nullptr) {
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800442 Str << "%" << getName(Func);
Jim Stichnoth2e8bfbb2014-09-16 10:16:00 -0700443 return;
444 }
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800445 if (Func->isVerbose(IceV_RegOrigins) ||
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700446 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
Jim Stichnoth9a04c072014-12-11 15:51:42 -0800447 Str << "%" << getName(Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700448 if (hasReg()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800449 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700450 Str << ":";
451 Str << Func->getTarget()->getRegName(RegNum, getType());
452 } else if (Func->getTarget()->hasComputedFrame()) {
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800453 if (Func->isVerbose(IceV_RegOrigins))
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700454 Str << ":";
Jan Voung28068ad2015-07-31 12:58:46 -0700455 int32_t BaseRegisterNumber = getBaseRegNum();
456 if (BaseRegisterNumber == NoRegister)
457 BaseRegisterNumber = Func->getTarget()->getFrameOrStackReg();
Jim Stichnothdd842db2015-01-27 12:53:53 -0800458 Str << "["
Jan Voung28068ad2015-07-31 12:58:46 -0700459 << Func->getTarget()->getRegName(BaseRegisterNumber, IceType_i32);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700460 int32_t Offset = getStackOffset();
461 if (Offset) {
462 if (Offset > 0)
463 Str << "+";
464 Str << Offset;
465 }
466 Str << "]";
467 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700468}
469
Jan Voung76bb0be2015-05-14 09:26:19 -0700470template <> void ConstantInteger32::emit(TargetLowering *Target) const {
471 Target->emit(this);
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700472}
473
Jan Voung76bb0be2015-05-14 09:26:19 -0700474template <> void ConstantInteger64::emit(TargetLowering *Target) const {
475 Target->emit(this);
476}
477
478template <> void ConstantFloat::emit(TargetLowering *Target) const {
479 Target->emit(this);
480}
481
482template <> void ConstantDouble::emit(TargetLowering *Target) const {
483 Target->emit(this);
484}
485
486void ConstantRelocatable::emit(TargetLowering *Target) const {
487 Target->emit(this);
488}
489
David Sehr2f3b8ec2015-11-16 16:51:39 -0800490void ConstantRelocatable::emitWithoutPrefix(
491 const TargetLowering *Target) const {
Jan Voung76bb0be2015-05-14 09:26:19 -0700492 Target->emitWithoutPrefix(this);
Jim Stichnothbca2f652014-11-01 10:13:54 -0700493}
494
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700495void ConstantRelocatable::dump(const Cfg *Func, Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700496 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800497 return;
Karl Schimpfdf6f9d12014-10-20 14:09:00 -0700498 Str << "@";
499 if (Func && !SuppressMangling) {
500 Str << Func->getContext()->mangleName(Name);
501 } else {
502 Str << Name;
503 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700504 if (Offset)
505 Str << "+" << Offset;
506}
507
Jan Voung76bb0be2015-05-14 09:26:19 -0700508void ConstantUndef::emit(TargetLowering *Target) const { Target->emit(this); }
509
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700510void LiveRange::dump(Ostream &Str) const {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700511 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800512 return;
Jim Stichnothf44f3712014-10-01 14:05:51 -0700513 bool First = true;
514 for (const RangeElementType &I : Range) {
Jim Stichnoth8363a062014-10-07 10:02:38 -0700515 if (!First)
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700516 Str << ", ";
Jim Stichnothf44f3712014-10-01 14:05:51 -0700517 First = false;
518 Str << "[" << I.first << ":" << I.second << ")";
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700519 }
520}
521
522Ostream &operator<<(Ostream &Str, const LiveRange &L) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700523 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800524 return Str;
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700525 L.dump(Str);
526 return Str;
527}
528
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700529Ostream &operator<<(Ostream &Str, const RegWeight &W) {
Jim Stichnoth20b71f52015-06-24 15:52:24 -0700530 if (!BuildDefs::dump())
Karl Schimpfb6c96af2014-11-17 10:58:39 -0800531 return Str;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700532 if (W.getWeight() == RegWeight::Inf)
533 Str << "Inf";
534 else
535 Str << W.getWeight();
536 return Str;
537}
538
Qining Lu253dc8a2015-06-22 10:10:23 -0700539// =========== Immediate Randomization and Pooling routines ==============
540// Specialization of the template member function for ConstantInteger32
Andrew Scull57e12682015-09-16 11:30:19 -0700541// TODO(stichnot): try to move this specialization into a target-specific file.
Qining Lu253dc8a2015-06-22 10:10:23 -0700542template <>
543bool ConstantInteger32::shouldBeRandomizedOrPooled(const GlobalContext *Ctx) {
544 uint32_t Threshold = Ctx->getFlags().getRandomizeAndPoolImmediatesThreshold();
545 if (Ctx->getFlags().getRandomizeAndPoolImmediatesOption() == RPI_None)
546 return false;
547 if (getType() != IceType_i32 && getType() != IceType_i16 &&
548 getType() != IceType_i8)
549 return false;
550 // The Following checks if the signed representation of Value is between
551 // -Threshold/2 and +Threshold/2
552 bool largerThanThreshold = Threshold / 2 + Value >= Threshold;
553 return largerThanThreshold;
554}
555
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700556} // end of namespace Ice