OLD | NEW |
1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// | 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// |
2 // | 2 // |
3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file declares the Inst class and its target-independent | 10 // This file declares the Inst class and its target-independent |
(...skipping 29 matching lines...) Expand all Loading... |
40 Br, | 40 Br, |
41 Call, | 41 Call, |
42 Cast, | 42 Cast, |
43 Fcmp, | 43 Fcmp, |
44 Icmp, | 44 Icmp, |
45 Load, | 45 Load, |
46 Phi, | 46 Phi, |
47 Ret, | 47 Ret, |
48 Select, | 48 Select, |
49 Store, | 49 Store, |
50 Switch | 50 Switch, |
| 51 FakeDef, // not part of LLVM/PNaCl bitcode |
| 52 FakeUse, // not part of LLVM/PNaCl bitcode |
| 53 FakeKill, // not part of LLVM/PNaCl bitcode |
| 54 Target // target-specific low-level ICE |
| 55 // Anything >= Target is an InstTarget subclass. |
51 }; | 56 }; |
52 InstKind getKind() const { return Kind; } | 57 InstKind getKind() const { return Kind; } |
53 | 58 |
54 int32_t getNumber() const { return Number; } | 59 int32_t getNumber() const { return Number; } |
55 | 60 |
56 bool isDeleted() const { return Deleted; } | 61 bool isDeleted() const { return Deleted; } |
57 void setDeleted() { Deleted = true; } | 62 void setDeleted() { Deleted = true; } |
58 | 63 |
59 bool hasSideEffects() const { return HasSideEffects; } | 64 bool hasSideEffects() const { return HasSideEffects; } |
60 | 65 |
(...skipping 15 matching lines...) Expand all Loading... |
76 "getTerminatorEdges() called on a non-terminator instruction"); | 81 "getTerminatorEdges() called on a non-terminator instruction"); |
77 return NodeList(); | 82 return NodeList(); |
78 } | 83 } |
79 | 84 |
80 // Updates the status of the Variables contained within the | 85 // Updates the status of the Variables contained within the |
81 // instruction. In particular, it marks where the Dest variable is | 86 // instruction. In particular, it marks where the Dest variable is |
82 // first assigned, and it tracks whether variables are live across | 87 // first assigned, and it tracks whether variables are live across |
83 // basic blocks, i.e. used in a different block from their definition. | 88 // basic blocks, i.e. used in a different block from their definition. |
84 void updateVars(CfgNode *Node); | 89 void updateVars(CfgNode *Node); |
85 | 90 |
| 91 virtual void emit(const Cfg *Func) const; |
86 virtual void dump(const Cfg *Func) const; | 92 virtual void dump(const Cfg *Func) const; |
87 void dumpDecorated(const Cfg *Func) const; | 93 void dumpDecorated(const Cfg *Func) const; |
| 94 void emitSources(const Cfg *Func) const; |
88 void dumpSources(const Cfg *Func) const; | 95 void dumpSources(const Cfg *Func) const; |
89 void dumpDest(const Cfg *Func) const; | 96 void dumpDest(const Cfg *Func) const; |
| 97 virtual bool isRedundantAssign() const { return false; } |
90 | 98 |
91 virtual ~Inst() {} | 99 virtual ~Inst() {} |
92 | 100 |
93 protected: | 101 protected: |
94 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); | 102 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); |
95 void addSource(Operand *Src) { | 103 void addSource(Operand *Src) { |
96 assert(Src); | 104 assert(Src); |
97 assert(NumSrcs < MaxSrcs); | 105 assert(NumSrcs < MaxSrcs); |
98 Srcs[NumSrcs++] = Src; | 106 Srcs[NumSrcs++] = Src; |
99 } | 107 } |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 155 |
148 // Binary arithmetic instruction. The source operands are captured in | 156 // Binary arithmetic instruction. The source operands are captured in |
149 // getSrc(0) and getSrc(1). | 157 // getSrc(0) and getSrc(1). |
150 class InstArithmetic : public Inst { | 158 class InstArithmetic : public Inst { |
151 public: | 159 public: |
152 enum OpKind { | 160 enum OpKind { |
153 #define X(tag, str, commutative) tag, | 161 #define X(tag, str, commutative) tag, |
154 ICEINSTARITHMETIC_TABLE | 162 ICEINSTARITHMETIC_TABLE |
155 #undef X | 163 #undef X |
156 }; | 164 }; |
| 165 |
157 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, | 166 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, |
158 Operand *Source1, Operand *Source2) { | 167 Operand *Source1, Operand *Source2) { |
159 return new (Func->allocateInst<InstArithmetic>()) | 168 return new (Func->allocateInst<InstArithmetic>()) |
160 InstArithmetic(Func, Op, Dest, Source1, Source2); | 169 InstArithmetic(Func, Op, Dest, Source1, Source2); |
161 } | 170 } |
162 OpKind getOp() const { return Op; } | 171 OpKind getOp() const { return Op; } |
163 bool isCommutative() const; | 172 bool isCommutative() const; |
164 virtual void dump(const Cfg *Func) const; | 173 virtual void dump(const Cfg *Func) const; |
165 static bool classof(const Inst *Inst) { | 174 static bool classof(const Inst *Inst) { |
166 return Inst->getKind() == Arithmetic; | 175 return Inst->getKind() == Arithmetic; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
272 }; | 281 }; |
273 | 282 |
274 // Cast instruction (a.k.a. conversion operation). | 283 // Cast instruction (a.k.a. conversion operation). |
275 class InstCast : public Inst { | 284 class InstCast : public Inst { |
276 public: | 285 public: |
277 enum OpKind { | 286 enum OpKind { |
278 #define X(tag, str) tag, | 287 #define X(tag, str) tag, |
279 ICEINSTCAST_TABLE | 288 ICEINSTCAST_TABLE |
280 #undef X | 289 #undef X |
281 }; | 290 }; |
| 291 |
282 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, | 292 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
283 Operand *Source) { | 293 Operand *Source) { |
284 return new (Func->allocateInst<InstCast>()) | 294 return new (Func->allocateInst<InstCast>()) |
285 InstCast(Func, CastKind, Dest, Source); | 295 InstCast(Func, CastKind, Dest, Source); |
286 } | 296 } |
287 OpKind getCastKind() const { return CastKind; } | 297 OpKind getCastKind() const { return CastKind; } |
288 virtual void dump(const Cfg *Func) const; | 298 virtual void dump(const Cfg *Func) const; |
289 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 299 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } |
290 | 300 |
291 private: | 301 private: |
292 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 302 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
293 InstCast(const InstCast &) LLVM_DELETED_FUNCTION; | 303 InstCast(const InstCast &) LLVM_DELETED_FUNCTION; |
294 InstCast &operator=(const InstCast &) LLVM_DELETED_FUNCTION; | 304 InstCast &operator=(const InstCast &) LLVM_DELETED_FUNCTION; |
295 virtual ~InstCast() {} | 305 virtual ~InstCast() {} |
296 const OpKind CastKind; | 306 const OpKind CastKind; |
297 }; | 307 }; |
298 | 308 |
299 // Floating-point comparison instruction. The source operands are | 309 // Floating-point comparison instruction. The source operands are |
300 // captured in getSrc(0) and getSrc(1). | 310 // captured in getSrc(0) and getSrc(1). |
301 class InstFcmp : public Inst { | 311 class InstFcmp : public Inst { |
302 public: | 312 public: |
303 enum FCond { | 313 enum FCond { |
304 #define X(tag, str) tag, | 314 #define X(tag, str) tag, |
305 ICEINSTFCMP_TABLE | 315 ICEINSTFCMP_TABLE |
306 #undef X | 316 #undef X |
307 }; | 317 }; |
| 318 |
308 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 319 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
309 Operand *Source1, Operand *Source2) { | 320 Operand *Source1, Operand *Source2) { |
310 return new (Func->allocateInst<InstFcmp>()) | 321 return new (Func->allocateInst<InstFcmp>()) |
311 InstFcmp(Func, Condition, Dest, Source1, Source2); | 322 InstFcmp(Func, Condition, Dest, Source1, Source2); |
312 } | 323 } |
313 FCond getCondition() const { return Condition; } | 324 FCond getCondition() const { return Condition; } |
314 virtual void dump(const Cfg *Func) const; | 325 virtual void dump(const Cfg *Func) const; |
315 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } | 326 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } |
316 | 327 |
317 private: | 328 private: |
318 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 329 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
319 Operand *Source2); | 330 Operand *Source2); |
320 InstFcmp(const InstFcmp &) LLVM_DELETED_FUNCTION; | 331 InstFcmp(const InstFcmp &) LLVM_DELETED_FUNCTION; |
321 InstFcmp &operator=(const InstFcmp &) LLVM_DELETED_FUNCTION; | 332 InstFcmp &operator=(const InstFcmp &) LLVM_DELETED_FUNCTION; |
322 virtual ~InstFcmp() {} | 333 virtual ~InstFcmp() {} |
323 const FCond Condition; | 334 const FCond Condition; |
324 }; | 335 }; |
325 | 336 |
326 // Integer comparison instruction. The source operands are captured | 337 // Integer comparison instruction. The source operands are captured |
327 // in getSrc(0) and getSrc(1). | 338 // in getSrc(0) and getSrc(1). |
328 class InstIcmp : public Inst { | 339 class InstIcmp : public Inst { |
329 public: | 340 public: |
330 enum ICond { | 341 enum ICond { |
331 #define X(tag, str) tag, | 342 #define X(tag, str) tag, |
332 ICEINSTICMP_TABLE | 343 ICEINSTICMP_TABLE |
333 #undef X | 344 #undef X |
334 }; | 345 }; |
| 346 |
335 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 347 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
336 Operand *Source1, Operand *Source2) { | 348 Operand *Source1, Operand *Source2) { |
337 return new (Func->allocateInst<InstIcmp>()) | 349 return new (Func->allocateInst<InstIcmp>()) |
338 InstIcmp(Func, Condition, Dest, Source1, Source2); | 350 InstIcmp(Func, Condition, Dest, Source1, Source2); |
339 } | 351 } |
340 ICond getCondition() const { return Condition; } | 352 ICond getCondition() const { return Condition; } |
341 virtual void dump(const Cfg *Func) const; | 353 virtual void dump(const Cfg *Func) const; |
342 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 354 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } |
343 | 355 |
344 private: | 356 private: |
(...skipping 24 matching lines...) Expand all Loading... |
369 }; | 381 }; |
370 | 382 |
371 // Phi instruction. For incoming edge I, the node is Labels[I] and | 383 // Phi instruction. For incoming edge I, the node is Labels[I] and |
372 // the Phi source operand is getSrc(I). | 384 // the Phi source operand is getSrc(I). |
373 class InstPhi : public Inst { | 385 class InstPhi : public Inst { |
374 public: | 386 public: |
375 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 387 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
376 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 388 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
377 } | 389 } |
378 void addArgument(Operand *Source, CfgNode *Label); | 390 void addArgument(Operand *Source, CfgNode *Label); |
| 391 Operand *getOperandForTarget(CfgNode *Target) const; |
| 392 Inst *lower(Cfg *Func, CfgNode *Node); |
379 virtual void dump(const Cfg *Func) const; | 393 virtual void dump(const Cfg *Func) const; |
380 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } | 394 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } |
381 | 395 |
382 private: | 396 private: |
383 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 397 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
384 InstPhi(const InstPhi &) LLVM_DELETED_FUNCTION; | 398 InstPhi(const InstPhi &) LLVM_DELETED_FUNCTION; |
385 InstPhi &operator=(const InstPhi &) LLVM_DELETED_FUNCTION; | 399 InstPhi &operator=(const InstPhi &) LLVM_DELETED_FUNCTION; |
386 virtual void destroy(Cfg *Func) { | 400 virtual void destroy(Cfg *Func) { |
387 Func->deallocateArrayOf<CfgNode *>(Labels); | 401 Func->deallocateArrayOf<CfgNode *>(Labels); |
388 Inst::destroy(Func); | 402 Inst::destroy(Func); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 return Inst->getKind() == Unreachable; | 529 return Inst->getKind() == Unreachable; |
516 } | 530 } |
517 | 531 |
518 private: | 532 private: |
519 InstUnreachable(Cfg *Func); | 533 InstUnreachable(Cfg *Func); |
520 InstUnreachable(const InstUnreachable &) LLVM_DELETED_FUNCTION; | 534 InstUnreachable(const InstUnreachable &) LLVM_DELETED_FUNCTION; |
521 InstUnreachable &operator=(const InstUnreachable &) LLVM_DELETED_FUNCTION; | 535 InstUnreachable &operator=(const InstUnreachable &) LLVM_DELETED_FUNCTION; |
522 virtual ~InstUnreachable() {} | 536 virtual ~InstUnreachable() {} |
523 }; | 537 }; |
524 | 538 |
| 539 // FakeDef instruction. This creates a fake definition of a variable, |
| 540 // which is how we represent the case when an instruction produces |
| 541 // multiple results. This doesn't happen with high-level ICE |
| 542 // instructions, but might with lowered instructions. For example, |
| 543 // this would be a way to represent condition flags being modified by |
| 544 // an instruction. |
| 545 // |
| 546 // It's generally useful to set the optional source operand to be the |
| 547 // dest variable of the instruction that actually produces the FakeDef |
| 548 // dest. Otherwise, the original instruction could be dead-code |
| 549 // eliminated if its dest operand is unused, and therefore the FakeDef |
| 550 // dest wouldn't be properly initialized. |
| 551 class InstFakeDef : public Inst { |
| 552 public: |
| 553 static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { |
| 554 return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
| 555 } |
| 556 virtual void emit(const Cfg *Func) const; |
| 557 virtual void dump(const Cfg *Func) const; |
| 558 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
| 559 |
| 560 private: |
| 561 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
| 562 InstFakeDef(const InstFakeDef &) LLVM_DELETED_FUNCTION; |
| 563 InstFakeDef &operator=(const InstFakeDef &) LLVM_DELETED_FUNCTION; |
| 564 virtual ~InstFakeDef() {} |
| 565 }; |
| 566 |
| 567 // FakeUse instruction. This creates a fake use of a variable, to |
| 568 // keep the instruction that produces that variable from being |
| 569 // dead-code eliminated. This is useful in a variety of lowering |
| 570 // situations. The FakeUse instruction has no dest, so it can itself |
| 571 // never be dead-code eliminated. |
| 572 class InstFakeUse : public Inst { |
| 573 public: |
| 574 static InstFakeUse *create(Cfg *Func, Variable *Src) { |
| 575 return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); |
| 576 } |
| 577 virtual void emit(const Cfg *Func) const; |
| 578 virtual void dump(const Cfg *Func) const; |
| 579 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
| 580 |
| 581 private: |
| 582 InstFakeUse(Cfg *Func, Variable *Src); |
| 583 InstFakeUse(const InstFakeUse &) LLVM_DELETED_FUNCTION; |
| 584 InstFakeUse &operator=(const InstFakeUse &) LLVM_DELETED_FUNCTION; |
| 585 virtual ~InstFakeUse() {} |
| 586 }; |
| 587 |
| 588 // FakeKill instruction. This "kills" a set of variables by adding a |
| 589 // trivial live range at this instruction to each variable. The |
| 590 // primary use is to indicate that scratch registers are killed after |
| 591 // a call, so that the register allocator won't assign a scratch |
| 592 // register to a variable whose live range spans a call. |
| 593 // |
| 594 // The FakeKill instruction also holds a pointer to the instruction |
| 595 // that kills the set of variables, so that if that linked instruction |
| 596 // gets dead-code eliminated, the FakeKill instruction will as well. |
| 597 class InstFakeKill : public Inst { |
| 598 public: |
| 599 static InstFakeKill *create(Cfg *Func, const VarList &KilledRegs, |
| 600 const Inst *Linked) { |
| 601 return new (Func->allocateInst<InstFakeKill>()) |
| 602 InstFakeKill(Func, KilledRegs, Linked); |
| 603 } |
| 604 const Inst *getLinked() const { return Linked; } |
| 605 virtual void emit(const Cfg *Func) const; |
| 606 virtual void dump(const Cfg *Func) const; |
| 607 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
| 608 |
| 609 private: |
| 610 InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked); |
| 611 InstFakeKill(const InstFakeKill &) LLVM_DELETED_FUNCTION; |
| 612 InstFakeKill &operator=(const InstFakeKill &) LLVM_DELETED_FUNCTION; |
| 613 virtual ~InstFakeKill() {} |
| 614 |
| 615 // This instruction is ignored if Linked->isDeleted() is true. |
| 616 const Inst *Linked; |
| 617 }; |
| 618 |
| 619 // The Target instruction is the base class for all target-specific |
| 620 // instructions. |
| 621 class InstTarget : public Inst { |
| 622 public: |
| 623 virtual void emit(const Cfg *Func) const = 0; |
| 624 virtual void dump(const Cfg *Func) const; |
| 625 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
| 626 |
| 627 protected: |
| 628 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 629 : Inst(Func, Kind, MaxSrcs, Dest) { |
| 630 assert(Kind >= Target); |
| 631 } |
| 632 InstTarget(const InstTarget &) LLVM_DELETED_FUNCTION; |
| 633 InstTarget &operator=(const InstTarget &) LLVM_DELETED_FUNCTION; |
| 634 virtual ~InstTarget() {} |
| 635 }; |
| 636 |
525 } // end of namespace Ice | 637 } // end of namespace Ice |
526 | 638 |
527 #endif // SUBZERO_SRC_ICEINST_H | 639 #endif // SUBZERO_SRC_ICEINST_H |
OLD | NEW |