| 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 |