OLD | NEW |
---|---|
(Empty) | |
1 //===- subzero/src/IceInst.cpp - High-level instruction 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 // | |
10 // This file implements the Inst class, primarily the various | |
11 // subclass constructors and dump routines. | |
12 // | |
13 //===----------------------------------------------------------------------===// | |
14 | |
15 #include "IceCfg.h" | |
16 #include "IceCfgNode.h" | |
17 #include "IceInst.h" | |
18 #include "IceOperand.h" | |
19 | |
20 namespace Ice { | |
21 | |
22 Inst::Inst(IceCfg *Cfg, InstKind Kind, IceSize_t MaxSrcs, Variable *Dest) | |
23 : Kind(Kind), Number(Cfg->newInstNumber()), Deleted(false), | |
24 HasSideEffects(false), Dest(Dest), MaxSrcs(MaxSrcs), NumSrcs(0), | |
25 Srcs(Cfg->allocateArrayOf<Operand *>(MaxSrcs)) {} | |
26 | |
27 Inst::~Inst() { | |
28 #ifdef ICE_NO_ARENAS | |
29 for (IceSize_t i = 0; i < getSrcSize(); ++i) { | |
30 Operand *Src = getSrc(i); | |
31 if (Src && !Src->isPooled()) { | |
32 delete Src; | |
33 } | |
34 } | |
35 delete[] Srcs; | |
36 if (getDest() && !getDest()->isPooled()) { | |
37 delete getDest(); | |
38 } | |
JF
2014/04/23 03:51:28
Same thing on deletion, though it kind of seems li
Jim Stichnoth
2014/04/26 15:02:11
Done. And you're right, it was just wrong for the
| |
39 #endif // ICE_NO_ARENAS | |
40 } | |
41 | |
42 void Inst::updateVars(CfgNode *Node) { | |
43 if (Dest) | |
44 Dest->setDefinition(this, Node); | |
45 | |
46 IceSize_t VarIndex = 0; | |
47 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
48 Operand *Src = getSrc(I); | |
49 IceSize_t NumVars = Src->getNumVars(); | |
50 for (IceSize_t J = 0; J < NumVars; ++J, ++VarIndex) { | |
51 Variable *Var = Src->getVar(J); | |
52 Var->setUse(this, Node); | |
53 } | |
54 } | |
55 } | |
56 | |
57 InstAlloca::InstAlloca(IceCfg *Cfg, Operand *ByteCount, uint32_t Align, | |
58 Variable *Dest) | |
59 : Inst(Cfg, Inst::Alloca, 1, Dest), Align(Align) { | |
60 addSource(ByteCount); | |
61 } | |
62 | |
63 InstArithmetic::InstArithmetic(IceCfg *Cfg, OpKind Op, Variable *Dest, | |
64 Operand *Source1, Operand *Source2) | |
65 : Inst(Cfg, Inst::Arithmetic, 2, Dest), Op(Op) { | |
66 addSource(Source1); | |
67 addSource(Source2); | |
68 } | |
69 | |
70 bool InstArithmetic::isCommutative() const { | |
71 #define X(tag, str, commutative) \ | |
72 case tag: \ | |
73 return commutative; | |
74 | |
75 switch (getOp()) { ICEINSTARITHMETIC_TABLE } | |
JF
2014/04/23 03:51:28
Load from a static const bool table instead: show
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
76 #undef X | |
77 | |
78 assert(0); // should be unreachable | |
JF
2014/04/23 03:51:28
llvm_unreachable
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
79 return false; | |
80 } | |
81 | |
82 InstAssign::InstAssign(IceCfg *Cfg, Variable *Dest, Operand *Source) | |
83 : Inst(Cfg, Inst::Assign, 1, Dest) { | |
84 addSource(Source); | |
85 } | |
86 | |
87 // If TargetTrue==TargetFalse, we turn it into an unconditional | |
88 // branch. This ensures that, along with the 'switch' instruction | |
89 // semantics, there is at most one edge from one node to another. | |
90 InstBr::InstBr(IceCfg *Cfg, Operand *Source, CfgNode *TargetTrue, | |
91 CfgNode *TargetFalse) | |
92 : Inst(Cfg, Inst::Br, 1, NULL), TargetFalse(TargetFalse), | |
93 TargetTrue(TargetTrue) { | |
94 if (TargetTrue == TargetFalse) { | |
95 TargetTrue = NULL; // turn into unconditional version | |
96 } else { | |
97 addSource(Source); | |
98 } | |
99 } | |
100 | |
101 InstBr::InstBr(IceCfg *Cfg, CfgNode *Target) | |
102 : Inst(Cfg, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} | |
103 | |
104 NodeList InstBr::getTerminatorEdges() const { | |
105 NodeList OutEdges; | |
106 OutEdges.push_back(TargetFalse); | |
107 if (TargetTrue) | |
108 OutEdges.push_back(TargetTrue); | |
109 return OutEdges; | |
110 } | |
111 | |
112 InstCast::InstCast(IceCfg *Cfg, OpKind CastKind, Variable *Dest, | |
113 Operand *Source) | |
114 : Inst(Cfg, Inst::Cast, 1, Dest), CastKind(CastKind) { | |
115 addSource(Source); | |
116 } | |
117 | |
118 InstFcmp::InstFcmp(IceCfg *Cfg, FCond Condition, Variable *Dest, | |
119 Operand *Source1, Operand *Source2) | |
120 : Inst(Cfg, Inst::Fcmp, 2, Dest), Condition(Condition) { | |
121 addSource(Source1); | |
122 addSource(Source2); | |
123 } | |
124 | |
125 InstIcmp::InstIcmp(IceCfg *Cfg, ICond Condition, Variable *Dest, | |
126 Operand *Source1, Operand *Source2) | |
127 : Inst(Cfg, Inst::Icmp, 2, Dest), Condition(Condition) { | |
128 addSource(Source1); | |
129 addSource(Source2); | |
130 } | |
131 | |
132 InstLoad::InstLoad(IceCfg *Cfg, Variable *Dest, Operand *SourceAddr) | |
133 : Inst(Cfg, Inst::Load, 1, Dest) { | |
134 addSource(SourceAddr); | |
135 } | |
136 | |
137 InstPhi::InstPhi(IceCfg *Cfg, IceSize_t MaxSrcs, Variable *Dest) | |
138 : Inst(Cfg, Phi, MaxSrcs, Dest) { | |
139 Labels = Cfg->allocateArrayOf<CfgNode *>(MaxSrcs); | |
140 } | |
141 | |
142 // TODO: A Switch instruction (and maybe others) can add duplicate | |
143 // edges. We may want to de-dup Phis and validate consistency (i.e., | |
144 // the source operands are the same for duplicate edges), though it | |
145 // seems the current lowering code is OK with this situation. | |
146 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | |
147 Labels[getSrcSize()] = Label; | |
148 addSource(Source); | |
149 } | |
150 | |
151 InstRet::InstRet(IceCfg *Cfg, Operand *RetValue) | |
152 : Inst(Cfg, Ret, RetValue ? 1 : 0, NULL) { | |
153 if (RetValue) | |
154 addSource(RetValue); | |
155 } | |
156 | |
157 InstSelect::InstSelect(IceCfg *Cfg, Variable *Dest, Operand *Condition, | |
158 Operand *SourceTrue, Operand *SourceFalse) | |
159 : Inst(Cfg, Inst::Select, 3, Dest) { | |
160 assert(Condition->getType() == IceType_i1); | |
161 addSource(Condition); | |
162 addSource(SourceTrue); | |
163 addSource(SourceFalse); | |
164 } | |
165 | |
166 InstStore::InstStore(IceCfg *Cfg, Operand *Data, Operand *Addr) | |
167 : Inst(Cfg, Inst::Store, 2, NULL) { | |
168 addSource(Data); | |
169 addSource(Addr); | |
170 } | |
171 | |
172 InstSwitch::InstSwitch(IceCfg *Cfg, IceSize_t NumCases, Operand *Source, | |
173 CfgNode *LabelDefault) | |
174 : Inst(Cfg, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), | |
175 NumCases(NumCases) { | |
176 addSource(Source); | |
177 Values = Cfg->allocateArrayOf<uint64_t>(NumCases); | |
178 Labels = Cfg->allocateArrayOf<CfgNode *>(NumCases); | |
179 // Initialize in case buggy code doesn't set all entries | |
180 for (IceSize_t I = 0; I < NumCases; ++I) { | |
181 Values[I] = 0; | |
182 Labels[I] = NULL; | |
183 } | |
184 } | |
185 | |
186 void InstSwitch::addBranch(IceSize_t CaseIndex, uint64_t Value, | |
187 CfgNode *Label) { | |
188 assert(CaseIndex < NumCases); | |
189 Values[CaseIndex] = Value; | |
190 Labels[CaseIndex] = Label; | |
191 } | |
192 | |
193 NodeList InstSwitch::getTerminatorEdges() const { | |
194 NodeList OutEdges; | |
195 OutEdges.push_back(LabelDefault); | |
196 for (IceSize_t I = 0; I < NumCases; ++I) { | |
197 OutEdges.push_back(Labels[I]); | |
198 } | |
199 return OutEdges; | |
200 } | |
201 | |
202 InstUnreachable::InstUnreachable(IceCfg *Cfg) | |
203 : Inst(Cfg, Inst::Unreachable, 0, NULL) {} | |
204 | |
205 // ======================== Dump routines ======================== // | |
206 | |
207 void Inst::dumpDecorated(const IceCfg *Cfg) const { | |
208 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
209 if (!Cfg->getContext()->isVerbose(IceV_Deleted) && isDeleted()) | |
210 return; | |
211 if (Cfg->getContext()->isVerbose(IceV_InstNumbers)) { | |
212 const static size_t BufLen = 30; | |
213 char buf[BufLen]; | |
214 int32_t Number = getNumber(); | |
215 if (Number < 0) | |
216 snprintf(buf, BufLen, "[XXX]"); | |
217 else | |
218 snprintf(buf, BufLen, "[%3d]", Number); | |
219 Str << buf; | |
220 } | |
221 Str << " "; | |
222 if (isDeleted()) | |
223 Str << " //"; | |
224 dump(Cfg); | |
225 Str << "\n"; | |
226 } | |
227 | |
228 void Inst::dump(const IceCfg *Cfg) const { | |
229 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
230 dumpDest(Cfg); | |
231 Str << " =~ "; | |
232 dumpSources(Cfg); | |
233 } | |
234 | |
235 void Inst::dumpSources(const IceCfg *Cfg) const { | |
236 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
237 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
238 if (I > 0) | |
239 Str << ", "; | |
240 getSrc(I)->dump(Cfg); | |
241 } | |
242 } | |
243 | |
244 void Inst::dumpDest(const IceCfg *Cfg) const { | |
245 if (getDest()) | |
246 getDest()->dump(Cfg); | |
247 } | |
248 | |
249 void InstAlloca::dump(const IceCfg *Cfg) const { | |
250 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
251 dumpDest(Cfg); | |
252 Str << " = alloca i8, i32 "; | |
253 getSizeInBytes()->dump(Cfg); | |
254 Str << ", align " << Align; | |
255 } | |
256 | |
257 void InstArithmetic::dump(const IceCfg *Cfg) const { | |
258 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
259 dumpDest(Cfg); | |
260 Str << " = "; | |
261 | |
262 #define X(tag, str, commutative) \ | |
263 case tag: \ | |
264 Str << str; \ | |
265 break; | |
266 | |
267 switch (getOp()) { ICEINSTARITHMETIC_TABLE } | |
JF
2014/04/23 03:51:28
Same thing on table lookup from static const char
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
268 #undef X | |
269 | |
270 Str << " " << getDest()->getType() << " "; | |
271 dumpSources(Cfg); | |
272 } | |
273 | |
274 void InstAssign::dump(const IceCfg *Cfg) const { | |
275 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
276 dumpDest(Cfg); | |
277 Str << " = " << getDest()->getType() << " "; | |
278 dumpSources(Cfg); | |
279 } | |
280 | |
281 void InstBr::dump(const IceCfg *Cfg) const { | |
282 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
283 dumpDest(Cfg); | |
284 Str << "br "; | |
285 if (!isUnconditional()) { | |
286 Str << "i1 "; | |
287 getCondition()->dump(Cfg); | |
288 Str << ", label %" << getTargetTrue()->getName() << ", "; | |
289 } | |
290 Str << "label %" << getTargetFalse()->getName(); | |
291 } | |
292 | |
293 void InstCall::dump(const IceCfg *Cfg) const { | |
294 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
295 if (getDest()) { | |
296 dumpDest(Cfg); | |
297 Str << " = "; | |
298 } | |
299 if (Tail) | |
300 Str << "tail "; | |
301 Str << "call "; | |
302 if (getDest()) | |
303 Str << getDest()->getType(); | |
304 else | |
305 Str << "void"; | |
306 Str << " "; | |
307 getCallTarget()->dump(Cfg); | |
308 Str << "("; | |
309 for (IceSize_t I = 0; I < getNumArgs(); ++I) { | |
310 if (I > 0) | |
311 Str << ", "; | |
312 Str << getArg(I)->getType() << " "; | |
313 getArg(I)->dump(Cfg); | |
314 } | |
315 Str << ")"; | |
316 } | |
317 | |
318 void InstCast::dump(const IceCfg *Cfg) const { | |
319 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
320 dumpDest(Cfg); | |
321 Str << " = "; | |
322 | |
323 #define X(tag, str) \ | |
324 case tag: \ | |
325 Str << str; \ | |
326 break; | |
327 | |
328 switch (getCastKind()) { | |
329 ICEINSTCAST_TABLE | |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
330 default: | |
331 Str << "UNKNOWN"; | |
332 assert(0); | |
333 break; | |
334 } | |
335 #undef X | |
336 | |
337 Str << " " << getSrc(0)->getType() << " "; | |
338 dumpSources(Cfg); | |
339 Str << " to " << getDest()->getType(); | |
340 } | |
341 | |
342 void InstIcmp::dump(const IceCfg *Cfg) const { | |
343 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
344 dumpDest(Cfg); | |
345 Str << " = icmp "; | |
346 | |
347 #define X(tag, str) \ | |
348 case tag: \ | |
349 Str << str; \ | |
350 break; | |
351 | |
352 switch (getCondition()) { ICEINSTICMP_TABLE } | |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
353 #undef X | |
354 Str << " " << getSrc(0)->getType() << " "; | |
355 dumpSources(Cfg); | |
356 } | |
357 | |
358 void InstFcmp::dump(const IceCfg *Cfg) const { | |
359 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
360 dumpDest(Cfg); | |
361 Str << " = fcmp "; | |
362 | |
363 #define X(tag, str) \ | |
364 case tag: \ | |
365 Str << str; \ | |
366 break; | |
367 | |
368 switch (getCondition()) { ICEINSTFCMP_TABLE } | |
JF
2014/04/23 03:51:28
Same.
Jim Stichnoth
2014/04/26 15:02:11
Done.
| |
369 #undef X | |
370 Str << " " << getSrc(0)->getType() << " "; | |
371 dumpSources(Cfg); | |
372 } | |
373 | |
374 void InstLoad::dump(const IceCfg *Cfg) const { | |
375 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
376 dumpDest(Cfg); | |
377 IceType Type = getDest()->getType(); | |
378 Str << " = load " << Type << "* "; | |
379 dumpSources(Cfg); | |
380 switch (Type) { | |
381 case IceType_f32: | |
382 Str << ", align 4"; | |
383 break; | |
384 case IceType_f64: | |
385 Str << ", align 8"; | |
386 break; | |
387 default: | |
388 Str << ", align 1"; | |
389 break; | |
390 } | |
391 } | |
392 | |
393 void InstStore::dump(const IceCfg *Cfg) const { | |
394 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
395 IceType Type = getData()->getType(); | |
396 Str << "store " << Type << " "; | |
397 getData()->dump(Cfg); | |
398 Str << ", " << Type << "* "; | |
399 getAddr()->dump(Cfg); | |
400 Str << ", align "; | |
401 switch (Type) { | |
402 case IceType_f32: | |
403 Str << "4"; | |
404 break; | |
405 case IceType_f64: | |
406 Str << "8"; | |
407 break; | |
408 default: | |
409 Str << "1"; | |
410 break; | |
411 } | |
412 } | |
413 | |
414 void InstSwitch::dump(const IceCfg *Cfg) const { | |
415 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
416 IceType Type = getComparison()->getType(); | |
417 Str << "switch " << Type << " "; | |
418 getSrc(0)->dump(Cfg); | |
419 Str << ", label %" << getLabelDefault()->getName() << " [\n"; | |
420 for (IceSize_t I = 0; I < getNumCases(); ++I) { | |
421 Str << " " << Type << " " << getValue(I) << ", label %" | |
422 << getLabel(I)->getName() << "\n"; | |
423 } | |
424 Str << " ]"; | |
425 } | |
426 | |
427 void InstPhi::dump(const IceCfg *Cfg) const { | |
428 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
429 dumpDest(Cfg); | |
430 Str << " = phi " << getDest()->getType() << " "; | |
431 for (IceSize_t I = 0; I < getSrcSize(); ++I) { | |
432 if (I > 0) | |
433 Str << ", "; | |
434 Str << "[ "; | |
435 getSrc(I)->dump(Cfg); | |
436 Str << ", %" << Labels[I]->getName() << " ]"; | |
437 } | |
438 } | |
439 | |
440 void InstRet::dump(const IceCfg *Cfg) const { | |
441 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
442 IceType Type = hasRetValue() ? getSrc(0)->getType() : IceType_void; | |
443 Str << "ret " << Type; | |
444 if (hasRetValue()) { | |
445 Str << " "; | |
446 dumpSources(Cfg); | |
447 } | |
448 } | |
449 | |
450 void InstSelect::dump(const IceCfg *Cfg) const { | |
451 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
452 dumpDest(Cfg); | |
453 Operand *Condition = getCondition(); | |
454 Operand *TrueOp = getTrueOperand(); | |
455 Operand *FalseOp = getFalseOperand(); | |
456 Str << " = select " << Condition->getType() << " "; | |
457 Condition->dump(Cfg); | |
458 Str << ", " << TrueOp->getType() << " "; | |
459 TrueOp->dump(Cfg); | |
460 Str << ", " << FalseOp->getType() << " "; | |
461 FalseOp->dump(Cfg); | |
462 } | |
463 | |
464 void InstUnreachable::dump(const IceCfg *Cfg) const { | |
465 IceOstream &Str = Cfg->getContext()->getStrDump(); | |
466 Str << "unreachable"; | |
467 } | |
468 | |
469 } // end of namespace Ice | |
OLD | NEW |