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 IceInst 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 IceInst::IceInst(IceCfg *Cfg, InstKind Kind, uint32_t MaxSrcs, | |
21 IceVariable *Dest) | |
22 : Kind(Kind), Deleted(false), HasSideEffects(false), Dest(Dest), | |
23 MaxSrcs(MaxSrcs), NumSrcs(0) { | |
24 Number = Cfg->newInstNumber(); | |
25 Srcs = Cfg->allocateArrayOf<IceOperand *>(MaxSrcs); | |
JF
2014/04/16 01:27:32
Move to the initialization list.
Jim Stichnoth
2014/04/21 20:26:40
Done.
| |
26 } | |
27 | |
28 void IceInst::updateVars(IceCfgNode *Node) { | |
29 if (Dest) | |
30 Dest->setDefinition(this, Node); | |
31 for (uint32_t I = 0; I < getSrcSize(); ++I) { | |
32 getSrc(I)->setUse(this, Node); | |
33 } | |
34 } | |
35 | |
36 IceInstAlloca::IceInstAlloca(IceCfg *Cfg, IceOperand *ByteCount, uint32_t Align, | |
37 IceVariable *Dest) | |
38 : IceInst(Cfg, IceInst::Alloca, 1, Dest), Align(Align) { | |
39 addSource(ByteCount); | |
40 } | |
41 | |
42 IceInstArithmetic::IceInstArithmetic(IceCfg *Cfg, OpKind Op, IceVariable *Dest, | |
43 IceOperand *Source1, IceOperand *Source2) | |
44 : IceInst(Cfg, IceInst::Arithmetic, 2, Dest), Op(Op) { | |
45 addSource(Source1); | |
46 addSource(Source2); | |
47 } | |
48 | |
49 bool IceInstArithmetic::isCommutative() const { | |
50 switch (getOp()) { | |
51 case Add: | |
52 case Fadd: | |
53 case Mul: | |
54 case Fmul: | |
JF
2014/04/16 01:27:32
Fadd and Fmul aren't commutative.
Jim Stichnoth
2014/04/21 20:26:40
Done. I was sad to learn this.
Jim Stichnoth
2015/09/25 17:23:09
LLVM disagrees... see Instruction::isCommutative()
| |
55 case And: | |
56 case Or: | |
57 case Xor: | |
58 return true; | |
59 default: | |
JF
2014/04/16 01:27:32
It would be better to list everything so that if y
Jim Stichnoth
2014/04/21 20:26:40
Done. And converted to x-macros.
| |
60 return false; | |
61 } | |
62 } | |
63 | |
64 IceInstAssign::IceInstAssign(IceCfg *Cfg, IceVariable *Dest, IceOperand *Source) | |
65 : IceInst(Cfg, IceInst::Assign, 1, Dest) { | |
66 addSource(Source); | |
67 } | |
68 | |
69 // If TargetTrue==TargetFalse, we turn it into an unconditional | |
70 // branch. This ensures that, along with the 'switch' instruction | |
71 // semantics, there is at most one edge from one node to another. | |
72 IceInstBr::IceInstBr(IceCfg *Cfg, IceOperand *Source, IceCfgNode *TargetTrue, | |
73 IceCfgNode *TargetFalse) | |
74 : IceInst(Cfg, IceInst::Br, 1, NULL), TargetFalse(TargetFalse), | |
75 TargetTrue(TargetTrue) { | |
76 if (TargetTrue == TargetFalse) { | |
77 TargetTrue = NULL; // turn into unconditional version | |
78 } else { | |
79 addSource(Source); | |
JF
2014/04/16 01:27:32
It doesn't look like you have an invariant on True
Jim Stichnoth
2014/04/21 20:26:40
You crash, of course. :) Here and in all other in
| |
80 } | |
81 } | |
82 | |
83 IceInstBr::IceInstBr(IceCfg *Cfg, IceCfgNode *Target) | |
84 : IceInst(Cfg, IceInst::Br, 0, NULL), TargetFalse(Target), | |
85 TargetTrue(NULL) {} | |
86 | |
87 IceNodeList IceInstBr::getTerminatorEdges() const { | |
88 IceNodeList OutEdges; | |
89 OutEdges.push_back(TargetFalse); | |
90 if (TargetTrue) | |
91 OutEdges.push_back(TargetTrue); | |
92 return OutEdges; | |
93 } | |
94 | |
95 IceInstCast::IceInstCast(IceCfg *Cfg, OpKind CastKind, IceVariable *Dest, | |
96 IceOperand *Source) | |
97 : IceInst(Cfg, IceInst::Cast, 1, Dest), CastKind(CastKind) { | |
98 addSource(Source); | |
99 } | |
100 | |
101 IceInstFcmp::IceInstFcmp(IceCfg *Cfg, FCond Condition, IceVariable *Dest, | |
102 IceOperand *Source1, IceOperand *Source2) | |
103 : IceInst(Cfg, IceInst::Fcmp, 2, Dest), Condition(Condition) { | |
104 addSource(Source1); | |
105 addSource(Source2); | |
106 } | |
107 | |
108 IceInstIcmp::IceInstIcmp(IceCfg *Cfg, ICond Condition, IceVariable *Dest, | |
109 IceOperand *Source1, IceOperand *Source2) | |
110 : IceInst(Cfg, IceInst::Icmp, 2, Dest), Condition(Condition) { | |
111 addSource(Source1); | |
112 addSource(Source2); | |
113 } | |
114 | |
115 IceInstLoad::IceInstLoad(IceCfg *Cfg, IceVariable *Dest, IceOperand *SourceAddr) | |
116 : IceInst(Cfg, IceInst::Load, 1, Dest) { | |
117 addSource(SourceAddr); | |
118 } | |
119 | |
120 IceInstPhi::IceInstPhi(IceCfg *Cfg, uint32_t MaxSrcs, IceVariable *Dest) | |
121 : IceInst(Cfg, Phi, MaxSrcs, Dest) { | |
122 Labels = Cfg->allocateArrayOf<IceCfgNode *>(MaxSrcs); | |
123 } | |
124 | |
125 // TODO: A Switch instruction (and maybe others) can add duplicate | |
126 // edges. We may want to de-dup Phis and validate consistency (i.e., | |
127 // the source operands are the same for duplicate edges), though it | |
128 // seems the current lowering code is OK with this situation. | |
129 void IceInstPhi::addArgument(IceOperand *Source, IceCfgNode *Label) { | |
130 Labels[getSrcSize()] = Label; | |
131 addSource(Source); | |
132 } | |
133 | |
134 IceInstRet::IceInstRet(IceCfg *Cfg, IceOperand *Source) | |
135 : IceInst(Cfg, Ret, Source ? 1 : 0, NULL) { | |
136 if (Source) | |
137 addSource(Source); | |
138 } | |
139 | |
140 IceInstSelect::IceInstSelect(IceCfg *Cfg, IceVariable *Dest, | |
141 IceOperand *Condition, IceOperand *SourceTrue, | |
142 IceOperand *SourceFalse) | |
143 : IceInst(Cfg, IceInst::Select, 3, Dest) { | |
144 assert(Condition->getType() == IceType_i1); | |
145 addSource(Condition); | |
146 addSource(SourceTrue); | |
147 addSource(SourceFalse); | |
148 } | |
149 | |
150 IceInstStore::IceInstStore(IceCfg *Cfg, IceOperand *Data, IceOperand *Addr) | |
151 : IceInst(Cfg, IceInst::Store, 2, NULL) { | |
152 addSource(Data); | |
153 addSource(Addr); | |
154 } | |
155 | |
156 IceInstSwitch::IceInstSwitch(IceCfg *Cfg, uint32_t NumCases, IceOperand *Source, | |
157 IceCfgNode *LabelDefault) | |
158 : IceInst(Cfg, IceInst::Switch, 1, NULL), LabelDefault(LabelDefault), | |
159 NumCases(NumCases) { | |
160 addSource(Source); | |
161 Values = Cfg->allocateArrayOf<uint64_t>(NumCases); | |
162 Labels = Cfg->allocateArrayOf<IceCfgNode *>(NumCases); | |
163 // Initialize in case buggy code doesn't set all entries | |
164 for (uint32_t I = 0; I < NumCases; ++I) { | |
165 Values[I] = 0; | |
166 Labels[I] = NULL; | |
167 } | |
168 } | |
169 | |
170 void IceInstSwitch::addBranch(uint32_t CaseIndex, uint64_t Value, | |
171 IceCfgNode *Label) { | |
172 assert(CaseIndex < NumCases); | |
173 Values[CaseIndex] = Value; | |
174 Labels[CaseIndex] = Label; | |
175 } | |
176 | |
177 IceNodeList IceInstSwitch::getTerminatorEdges() const { | |
178 IceNodeList OutEdges; | |
179 OutEdges.push_back(LabelDefault); | |
180 for (uint32_t I = 0; I < NumCases; ++I) { | |
181 OutEdges.push_back(Labels[I]); | |
182 } | |
183 return OutEdges; | |
184 } | |
185 | |
186 IceInstUnreachable::IceInstUnreachable(IceCfg *Cfg) | |
187 : IceInst(Cfg, IceInst::Unreachable, 0, NULL) {} | |
188 | |
189 // ======================== Dump routines ======================== // | |
190 | |
191 void IceInst::dumpDecorated(const IceCfg *Cfg) const { | |
192 IceOstream &Str = Cfg->getContext()->StrDump; | |
193 if (!Cfg->getContext()->isVerbose(IceV_Deleted) && isDeleted()) | |
194 return; | |
195 if (Cfg->getContext()->isVerbose(IceV_InstNumbers)) { | |
196 char buf[30]; | |
197 int32_t Number = getNumber(); | |
198 if (Number < 0) | |
199 sprintf(buf, "[XXX]"); | |
200 else | |
201 sprintf(buf, "[%3d]", Number); | |
202 Str << buf; | |
203 } | |
204 Str << " "; | |
205 if (isDeleted()) | |
206 Str << " //"; | |
207 dump(Cfg); | |
208 Str << "\n"; | |
209 } | |
210 | |
211 void IceInst::dump(const IceCfg *Cfg) const { | |
212 IceOstream &Str = Cfg->getContext()->StrDump; | |
213 dumpDest(Cfg); | |
214 Str << " =~ "; | |
215 dumpSources(Cfg); | |
216 } | |
217 | |
218 void IceInst::dumpSources(const IceCfg *Cfg) const { | |
219 IceOstream &Str = Cfg->getContext()->StrDump; | |
220 for (uint32_t I = 0; I < getSrcSize(); ++I) { | |
221 if (I > 0) | |
222 Str << ", "; | |
223 getSrc(I)->dump(Cfg); | |
224 } | |
225 } | |
226 | |
227 void IceInst::dumpDest(const IceCfg *Cfg) const { | |
228 if (getDest()) | |
229 getDest()->dump(Cfg); | |
230 } | |
231 | |
232 void IceInstAlloca::dump(const IceCfg *Cfg) const { | |
233 IceOstream &Str = Cfg->getContext()->StrDump; | |
234 dumpDest(Cfg); | |
235 Str << " = alloca i8, i32 "; | |
236 getSrc(0)->dump(Cfg); | |
237 Str << ", align " << Align; | |
238 } | |
239 | |
240 void IceInstArithmetic::dump(const IceCfg *Cfg) const { | |
241 IceOstream &Str = Cfg->getContext()->StrDump; | |
242 dumpDest(Cfg); | |
243 Str << " = "; | |
244 switch (getOp()) { | |
245 case Add: | |
246 Str << "add"; | |
247 break; | |
248 case Fadd: | |
249 Str << "fadd"; | |
250 break; | |
251 case Sub: | |
252 Str << "sub"; | |
253 break; | |
254 case Fsub: | |
255 Str << "fsub"; | |
256 break; | |
257 case Mul: | |
258 Str << "mul"; | |
259 break; | |
260 case Fmul: | |
261 Str << "fmul"; | |
262 break; | |
263 case Udiv: | |
264 Str << "udiv"; | |
265 break; | |
266 case Sdiv: | |
267 Str << "sdiv"; | |
268 break; | |
269 case Fdiv: | |
270 Str << "fdiv"; | |
271 break; | |
272 case Urem: | |
273 Str << "urem"; | |
274 break; | |
275 case Srem: | |
276 Str << "srem"; | |
277 break; | |
278 case Frem: | |
279 Str << "frem"; | |
280 break; | |
281 case Shl: | |
282 Str << "shl"; | |
283 break; | |
284 case Lshr: | |
285 Str << "lshr"; | |
286 break; | |
287 case Ashr: | |
288 Str << "ashr"; | |
289 break; | |
290 case And: | |
291 Str << "and"; | |
292 break; | |
293 case Or: | |
294 Str << "or"; | |
295 break; | |
296 case Xor: | |
297 Str << "xor"; | |
298 break; | |
JF
2014/04/16 01:27:32
Another place where xmacros would be nice ;-)
Jim Stichnoth
2014/04/21 20:26:40
Done.
| |
299 } | |
300 Str << " " << getDest()->getType() << " "; | |
301 dumpSources(Cfg); | |
302 } | |
303 | |
304 void IceInstAssign::dump(const IceCfg *Cfg) const { | |
305 IceOstream &Str = Cfg->getContext()->StrDump; | |
306 dumpDest(Cfg); | |
307 Str << " = " << getDest()->getType() << " "; | |
308 dumpSources(Cfg); | |
309 } | |
310 | |
311 void IceInstBr::dump(const IceCfg *Cfg) const { | |
312 IceOstream &Str = Cfg->getContext()->StrDump; | |
313 dumpDest(Cfg); | |
314 Str << "br "; | |
315 if (!isUnconditional()) { | |
316 Str << "i1 "; | |
317 getSrc(0)->dump(Cfg); | |
318 Str << ", label %" << getTargetTrue()->getName() << ", "; | |
319 } | |
320 Str << "label %" << getTargetFalse()->getName(); | |
321 } | |
322 | |
323 void IceInstCall::dump(const IceCfg *Cfg) const { | |
324 IceOstream &Str = Cfg->getContext()->StrDump; | |
325 if (getDest()) { | |
326 dumpDest(Cfg); | |
327 Str << " = "; | |
328 } | |
329 if (Tail) | |
330 Str << "tail "; | |
331 Str << "call "; | |
332 if (getDest()) | |
333 Str << getDest()->getType(); | |
334 else | |
335 Str << "void"; | |
336 Str << " "; | |
337 getCallTarget()->dump(Cfg); | |
338 Str << "("; | |
339 for (uint32_t I = 0; I < getNumArgs(); ++I) { | |
340 if (I > 0) | |
341 Str << ", "; | |
342 Str << getArg(I)->getType() << " "; | |
343 getArg(I)->dump(Cfg); | |
344 } | |
345 Str << ")"; | |
346 } | |
347 | |
348 void IceInstCast::dump(const IceCfg *Cfg) const { | |
349 IceOstream &Str = Cfg->getContext()->StrDump; | |
350 dumpDest(Cfg); | |
351 Str << " = "; | |
352 switch (getCastKind()) { | |
353 default: | |
354 Str << "UNKNOWN"; | |
355 assert(0); | |
356 break; | |
357 case Trunc: | |
358 Str << "trunc"; | |
359 break; | |
360 case Zext: | |
361 Str << "zext"; | |
362 break; | |
363 case Sext: | |
364 Str << "sext"; | |
365 break; | |
366 case Fptrunc: | |
367 Str << "fptrunc"; | |
368 break; | |
369 case Fpext: | |
370 Str << "fpext"; | |
371 break; | |
372 case Fptoui: | |
373 Str << "fptoui"; | |
374 break; | |
375 case Fptosi: | |
376 Str << "fptosi"; | |
377 break; | |
378 case Uitofp: | |
379 Str << "uitofp"; | |
380 break; | |
381 case Sitofp: | |
382 Str << "sitofp"; | |
383 break; | |
384 case Bitcast: | |
385 Str << "bitcast"; | |
386 break; | |
JF
2014/04/16 01:27:32
xmacros :-)
Jim Stichnoth
2014/04/21 20:26:40
Done.
| |
387 } | |
388 Str << " " << getSrc(0)->getType() << " "; | |
389 dumpSources(Cfg); | |
390 Str << " to " << getDest()->getType(); | |
391 } | |
392 | |
393 void IceInstIcmp::dump(const IceCfg *Cfg) const { | |
394 IceOstream &Str = Cfg->getContext()->StrDump; | |
395 dumpDest(Cfg); | |
396 Str << " = icmp "; | |
397 switch (getCondition()) { | |
398 case Eq: | |
399 Str << "eq"; | |
400 break; | |
401 case Ne: | |
402 Str << "ne"; | |
403 break; | |
404 case Ugt: | |
405 Str << "ugt"; | |
406 break; | |
407 case Uge: | |
408 Str << "uge"; | |
409 break; | |
410 case Ult: | |
411 Str << "ult"; | |
412 break; | |
413 case Ule: | |
414 Str << "ule"; | |
415 break; | |
416 case Sgt: | |
417 Str << "sgt"; | |
418 break; | |
419 case Sge: | |
420 Str << "sge"; | |
421 break; | |
422 case Slt: | |
423 Str << "slt"; | |
424 break; | |
425 case Sle: | |
426 Str << "sle"; | |
427 break; | |
JF
2014/04/16 01:27:32
Ditto.
Jim Stichnoth
2014/04/21 20:26:40
Done.
| |
428 } | |
429 Str << " " << getSrc(0)->getType() << " "; | |
430 dumpSources(Cfg); | |
431 } | |
432 | |
433 void IceInstFcmp::dump(const IceCfg *Cfg) const { | |
434 IceOstream &Str = Cfg->getContext()->StrDump; | |
435 dumpDest(Cfg); | |
436 Str << " = fcmp "; | |
437 | |
438 switch (getCondition()) { | |
439 case False: | |
440 Str << "false"; | |
441 break; | |
442 case Oeq: | |
443 Str << "oeq"; | |
444 break; | |
445 case Ogt: | |
446 Str << "ogt"; | |
447 break; | |
448 case Oge: | |
449 Str << "oge"; | |
450 break; | |
451 case Olt: | |
452 Str << "olt"; | |
453 break; | |
454 case Ole: | |
455 Str << "ole"; | |
456 break; | |
457 case One: | |
458 Str << "one"; | |
459 break; | |
460 case Ord: | |
461 Str << "ord"; | |
462 break; | |
463 case Ueq: | |
464 Str << "ueq"; | |
465 break; | |
466 case Ugt: | |
467 Str << "ugt"; | |
468 break; | |
469 case Uge: | |
470 Str << "uge"; | |
471 break; | |
472 case Ult: | |
473 Str << "ult"; | |
474 break; | |
475 case Ule: | |
476 Str << "ule"; | |
477 break; | |
478 case Une: | |
479 Str << "une"; | |
480 break; | |
481 case Uno: | |
482 Str << "uno"; | |
483 break; | |
484 case True: | |
485 Str << "true"; | |
486 break; | |
JF
2014/04/16 01:27:32
Ditto.
Jim Stichnoth
2014/04/21 20:26:40
Done.
| |
487 } | |
488 Str << " " << getSrc(0)->getType() << " "; | |
489 dumpSources(Cfg); | |
490 } | |
491 | |
492 void IceInstLoad::dump(const IceCfg *Cfg) const { | |
493 IceOstream &Str = Cfg->getContext()->StrDump; | |
494 dumpDest(Cfg); | |
495 IceType Type = getDest()->getType(); | |
496 Str << " = load " << Type << "* "; | |
497 dumpSources(Cfg); | |
498 switch (Type) { | |
499 case IceType_f32: | |
500 Str << ", align 4"; | |
501 break; | |
502 case IceType_f64: | |
503 Str << ", align 8"; | |
504 break; | |
505 default: | |
506 Str << ", align 1"; | |
507 break; | |
508 } | |
509 } | |
510 | |
511 void IceInstStore::dump(const IceCfg *Cfg) const { | |
512 IceOstream &Str = Cfg->getContext()->StrDump; | |
513 IceType Type = getData()->getType(); | |
514 Str << "store " << Type << " "; | |
515 getData()->dump(Cfg); | |
516 Str << ", " << Type << "* "; | |
517 getAddr()->dump(Cfg); | |
518 Str << ", align "; | |
519 switch (Type) { | |
520 case IceType_f32: | |
521 Str << "4"; | |
522 break; | |
523 case IceType_f64: | |
524 Str << "8"; | |
525 break; | |
526 default: | |
527 Str << "1"; | |
528 break; | |
529 } | |
530 } | |
531 | |
532 void IceInstSwitch::dump(const IceCfg *Cfg) const { | |
533 IceOstream &Str = Cfg->getContext()->StrDump; | |
534 IceType Type = getSrc(0)->getType(); | |
535 Str << "switch " << Type << " "; | |
536 getSrc(0)->dump(Cfg); | |
537 Str << ", label %" << getLabelDefault()->getName() << " [\n"; | |
538 for (uint32_t I = 0; I < getNumCases(); ++I) { | |
539 Str << " " << Type << " " << getValue(I) << ", label %" | |
540 << getLabel(I)->getName() << "\n"; | |
541 } | |
542 Str << " ]"; | |
543 } | |
544 | |
545 void IceInstPhi::dump(const IceCfg *Cfg) const { | |
546 IceOstream &Str = Cfg->getContext()->StrDump; | |
547 dumpDest(Cfg); | |
548 Str << " = phi " << getDest()->getType() << " "; | |
549 for (uint32_t I = 0; I < getSrcSize(); ++I) { | |
550 if (I > 0) | |
551 Str << ", "; | |
552 Str << "[ "; | |
553 getSrc(I)->dump(Cfg); | |
554 Str << ", %" << Labels[I]->getName() << " ]"; | |
555 } | |
556 } | |
557 | |
558 void IceInstRet::dump(const IceCfg *Cfg) const { | |
559 IceOstream &Str = Cfg->getContext()->StrDump; | |
560 IceType Type = getSrcSize() == 0 ? IceType_void : getSrc(0)->getType(); | |
561 Str << "ret " << Type; | |
562 if (getSrcSize()) { | |
563 Str << " "; | |
564 dumpSources(Cfg); | |
565 } | |
566 } | |
567 | |
568 void IceInstSelect::dump(const IceCfg *Cfg) const { | |
569 IceOstream &Str = Cfg->getContext()->StrDump; | |
570 dumpDest(Cfg); | |
571 IceOperand *Condition = getCondition(); | |
572 IceOperand *TrueOp = getTrueOperand(); | |
573 IceOperand *FalseOp = getFalseOperand(); | |
574 Str << " = select " << Condition->getType() << " "; | |
575 Condition->dump(Cfg); | |
576 Str << ", " << TrueOp->getType() << " "; | |
577 TrueOp->dump(Cfg); | |
578 Str << ", " << FalseOp->getType() << " "; | |
579 FalseOp->dump(Cfg); | |
580 } | |
581 | |
582 void IceInstUnreachable::dump(const IceCfg *Cfg) const { | |
583 IceOstream &Str = Cfg->getContext()->StrDump; | |
584 Str << "unreachable"; | |
585 } | |
OLD | NEW |