blob: 02e85c76854df1ade16f3f62de2a317209822e19 [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"
16#include "IceInst.h"
17#include "IceOperand.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070018#include "IceTargetLowering.h" // dumping stack/frame pointer register
Jim Stichnothf7c9a142014-04-29 10:52:43 -070019
20namespace Ice {
21
22bool operator<(const RelocatableTuple &A, const RelocatableTuple &B) {
23 if (A.Offset != B.Offset)
24 return A.Offset < B.Offset;
25 if (A.SuppressMangling != B.SuppressMangling)
26 return A.SuppressMangling < B.SuppressMangling;
27 return A.Name < B.Name;
28}
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) {
39#ifdef USE_SET
40 RangeElementType Element(Start, End);
41 RangeType::iterator Next = Range.lower_bound(Element);
42 assert(Next == Range.upper_bound(Element)); // Element not already present
43
44 // Beginning of code that merges contiguous segments. TODO: change
45 // "if(true)" to "if(false)" to see if this extra optimization code
46 // gives any performance gain, or is just destabilizing.
47 if (true) {
48 RangeType::iterator FirstDelete = Next;
49 RangeType::iterator Prev = Next;
50 bool hasPrev = (Next != Range.begin());
51 bool hasNext = (Next != Range.end());
52 if (hasPrev)
53 --Prev;
54 // See if Element and Next should be joined.
55 if (hasNext && End == Next->first) {
56 Element.second = Next->second;
57 ++Next;
58 }
59 // See if Prev and Element should be joined.
60 if (hasPrev && Prev->second == Start) {
61 Element.first = Prev->first;
62 FirstDelete = Prev;
63 }
64 Range.erase(FirstDelete, Next);
65 }
66 // End of code that merges contiguous segments.
67
68 Range.insert(Next, Element);
69#else
70 if (Range.empty()) {
71 Range.push_back(RangeElementType(Start, End));
72 return;
73 }
74 // Special case for faking in-arg liveness.
75 if (End < Range.front().first) {
76 assert(Start < 0);
77 Range.push_front(RangeElementType(Start, End));
78 return;
79 }
80 InstNumberT CurrentEnd = Range.back().second;
81 assert(Start >= CurrentEnd);
82 // Check for merge opportunity.
83 if (Start == CurrentEnd) {
84 Range.back().second = End;
85 return;
86 }
87 Range.push_back(RangeElementType(Start, End));
88#endif
89}
90
91// Returns true if this live range ends before Other's live range
92// starts. This means that the highest instruction number in this
93// live range is less than or equal to the lowest instruction number
94// of the Other live range.
95bool LiveRange::endsBefore(const LiveRange &Other) const {
96 // Neither range should be empty, but let's be graceful.
97 if (Range.empty() || Other.Range.empty())
98 return true;
99 InstNumberT MyEnd = (*Range.rbegin()).second;
100 InstNumberT OtherStart = (*Other.Range.begin()).first;
101 return MyEnd <= OtherStart;
102}
103
104// Returns true if there is any overlap between the two live ranges.
105bool LiveRange::overlaps(const LiveRange &Other) const {
106 // Do a two-finger walk through the two sorted lists of segments.
107 RangeType::const_iterator I1 = Range.begin(), I2 = Other.Range.begin();
108 RangeType::const_iterator E1 = Range.end(), E2 = Other.Range.end();
109 while (I1 != E1 && I2 != E2) {
110 if (I1->second <= I2->first) {
111 ++I1;
112 continue;
113 }
114 if (I2->second <= I1->first) {
115 ++I2;
116 continue;
117 }
118 return true;
119 }
120 return false;
121}
122
123bool LiveRange::overlaps(InstNumberT OtherBegin) const {
124 LiveRange Temp;
125 Temp.addSegment(OtherBegin, OtherBegin + 1);
126 return overlaps(Temp);
127}
128
129// Returns true if the live range contains the given instruction
130// number. This is only used for validating the live range
131// calculation.
132bool LiveRange::containsValue(InstNumberT Value) const {
133 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E;
134 ++I) {
135 if (I->first <= Value && Value <= I->second)
136 return true;
137 }
138 return false;
139}
140
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700141void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
142 if (DefNode == NULL)
143 return;
144 if (llvm::isa<InstPhi>(Inst) || Node != DefNode)
145 DefNode = NULL;
146}
147
148void Variable::setDefinition(Inst *Inst, const CfgNode *Node) {
149 if (DefNode == NULL)
150 return;
151 // Can first check preexisting DefInst if we care about multi-def vars.
152 DefInst = Inst;
153 if (Node != DefNode)
154 DefNode = NULL;
155}
156
157void Variable::replaceDefinition(Inst *Inst, const CfgNode *Node) {
158 DefInst = NULL;
159 setDefinition(Inst, Node);
160}
161
162void Variable::setIsArg(Cfg *Func) {
163 IsArgument = true;
164 if (DefNode == NULL)
165 return;
166 CfgNode *Entry = Func->getEntryNode();
167 if (DefNode == Entry)
168 return;
169 DefNode = NULL;
170}
171
172IceString Variable::getName() const {
173 if (!Name.empty())
174 return Name;
175 char buf[30];
176 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex());
177 return buf;
178}
179
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700180Variable Variable::asType(Type Ty) {
181 Variable V(Ty, DefNode, Number, Name);
182 V.RegNum = RegNum;
183 V.StackOffset = StackOffset;
184 return V;
185}
186
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700187// ======================== dump routines ======================== //
188
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700189void Variable::emit(const Cfg *Func) const {
190 Func->getTarget()->emitVariable(this, Func);
191}
192
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700193void Variable::dump(const Cfg *Func) const {
194 Ostream &Str = Func->getContext()->getStrDump();
195 const CfgNode *CurrentNode = Func->getCurrentNode();
196 (void)CurrentNode; // used only in assert()
197 assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700198 if (Func->getContext()->isVerbose(IceV_RegOrigins) ||
199 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
200 Str << "%" << getName();
201 if (hasReg()) {
202 if (Func->getContext()->isVerbose(IceV_RegOrigins))
203 Str << ":";
204 Str << Func->getTarget()->getRegName(RegNum, getType());
205 } else if (Func->getTarget()->hasComputedFrame()) {
206 if (Func->getContext()->isVerbose(IceV_RegOrigins))
207 Str << ":";
208 Str << "[" << Func->getTarget()->getRegName(
209 Func->getTarget()->getFrameOrStackReg(), IceType_i32);
210 int32_t Offset = getStackOffset();
211 if (Offset) {
212 if (Offset > 0)
213 Str << "+";
214 Str << Offset;
215 }
216 Str << "]";
217 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700218}
219
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700220void ConstantRelocatable::emit(GlobalContext *Ctx) const {
221 Ostream &Str = Ctx->getStrEmit();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700222 if (SuppressMangling)
223 Str << Name;
224 else
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700225 Str << Ctx->mangleName(Name);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700226 if (Offset) {
227 if (Offset > 0)
228 Str << "+";
229 Str << Offset;
230 }
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700231}
232
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700233void ConstantRelocatable::dump(GlobalContext *Ctx) const {
234 Ostream &Str = Ctx->getStrDump();
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700235 Str << "@" << Name;
236 if (Offset)
237 Str << "+" << Offset;
238}
239
Jim Stichnothd97c7df2014-06-04 11:57:08 -0700240void LiveRange::dump(Ostream &Str) const {
241 Str << "(weight=" << Weight << ") ";
242 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E;
243 ++I) {
244 if (I != Range.begin())
245 Str << ", ";
246 Str << "[" << (*I).first << ":" << (*I).second << ")";
247 }
248}
249
250Ostream &operator<<(Ostream &Str, const LiveRange &L) {
251 L.dump(Str);
252 return Str;
253}
254
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700255Ostream &operator<<(Ostream &Str, const RegWeight &W) {
256 if (W.getWeight() == RegWeight::Inf)
257 Str << "Inf";
258 else
259 Str << W.getWeight();
260 return Str;
261}
262
Jim Stichnothf7c9a142014-04-29 10:52:43 -0700263} // end of namespace Ice