| 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 /// \file | 10 /// \file |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 251 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, | 251 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, |
| 252 uint32_t AlignInBytes) { | 252 uint32_t AlignInBytes) { |
| 253 return new (Func->allocate<InstAlloca>()) | 253 return new (Func->allocate<InstAlloca>()) |
| 254 InstAlloca(Func, Dest, ByteCount, AlignInBytes); | 254 InstAlloca(Func, Dest, ByteCount, AlignInBytes); |
| 255 } | 255 } |
| 256 uint32_t getAlignInBytes() const { return AlignInBytes; } | 256 uint32_t getAlignInBytes() const { return AlignInBytes; } |
| 257 Operand *getSizeInBytes() const { return getSrc(0); } | 257 Operand *getSizeInBytes() const { return getSrc(0); } |
| 258 bool getKnownFrameOffset() const { return KnownFrameOffset; } | 258 bool getKnownFrameOffset() const { return KnownFrameOffset; } |
| 259 void setKnownFrameOffset() { KnownFrameOffset = true; } | 259 void setKnownFrameOffset() { KnownFrameOffset = true; } |
| 260 void dump(const Cfg *Func) const override; | 260 void dump(const Cfg *Func) const override; |
| 261 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } | 261 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } |
| 262 | 262 |
| 263 private: | 263 private: |
| 264 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, | 264 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, |
| 265 uint32_t AlignInBytes); | 265 uint32_t AlignInBytes); |
| 266 | 266 |
| 267 const uint32_t AlignInBytes; | 267 const uint32_t AlignInBytes; |
| 268 bool KnownFrameOffset = false; | 268 bool KnownFrameOffset = false; |
| 269 }; | 269 }; |
| 270 | 270 |
| 271 /// Binary arithmetic instruction. The source operands are captured in getSrc(0) | 271 /// Binary arithmetic instruction. The source operands are captured in getSrc(0) |
| (...skipping 16 matching lines...) Expand all Loading... |
| 288 return new (Func->allocate<InstArithmetic>()) | 288 return new (Func->allocate<InstArithmetic>()) |
| 289 InstArithmetic(Func, Op, Dest, Source1, Source2); | 289 InstArithmetic(Func, Op, Dest, Source1, Source2); |
| 290 } | 290 } |
| 291 OpKind getOp() const { return Op; } | 291 OpKind getOp() const { return Op; } |
| 292 | 292 |
| 293 virtual IceString getInstName() const override; | 293 virtual IceString getInstName() const override; |
| 294 | 294 |
| 295 static const char *getOpName(OpKind Op); | 295 static const char *getOpName(OpKind Op); |
| 296 bool isCommutative() const; | 296 bool isCommutative() const; |
| 297 void dump(const Cfg *Func) const override; | 297 void dump(const Cfg *Func) const override; |
| 298 static bool classof(const Inst *Inst) { | 298 static bool classof(const Inst *Instr) { |
| 299 return Inst->getKind() == Arithmetic; | 299 return Instr->getKind() == Arithmetic; |
| 300 } | 300 } |
| 301 | 301 |
| 302 private: | 302 private: |
| 303 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, | 303 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, |
| 304 Operand *Source2); | 304 Operand *Source2); |
| 305 | 305 |
| 306 const OpKind Op; | 306 const OpKind Op; |
| 307 }; | 307 }; |
| 308 | 308 |
| 309 /// Assignment instruction. The source operand is captured in getSrc(0). This is | 309 /// Assignment instruction. The source operand is captured in getSrc(0). This is |
| 310 /// not part of the LLVM bitcode, but is a useful abstraction for some of the | 310 /// not part of the LLVM bitcode, but is a useful abstraction for some of the |
| 311 /// lowering. E.g., if Phi instruction lowering happens before target lowering, | 311 /// lowering. E.g., if Phi instruction lowering happens before target lowering, |
| 312 /// or for representing an Inttoptr instruction, or as an intermediate step for | 312 /// or for representing an Inttoptr instruction, or as an intermediate step for |
| 313 /// lowering a Load instruction. | 313 /// lowering a Load instruction. |
| 314 class InstAssign : public InstHighLevel { | 314 class InstAssign : public InstHighLevel { |
| 315 InstAssign() = delete; | 315 InstAssign() = delete; |
| 316 InstAssign(const InstAssign &) = delete; | 316 InstAssign(const InstAssign &) = delete; |
| 317 InstAssign &operator=(const InstAssign &) = delete; | 317 InstAssign &operator=(const InstAssign &) = delete; |
| 318 | 318 |
| 319 public: | 319 public: |
| 320 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 320 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 321 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); | 321 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
| 322 } | 322 } |
| 323 bool isVarAssign() const override; | 323 bool isVarAssign() const override; |
| 324 void dump(const Cfg *Func) const override; | 324 void dump(const Cfg *Func) const override; |
| 325 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } | 325 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } |
| 326 | 326 |
| 327 private: | 327 private: |
| 328 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 328 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
| 329 }; | 329 }; |
| 330 | 330 |
| 331 /// Branch instruction. This represents both conditional and unconditional | 331 /// Branch instruction. This represents both conditional and unconditional |
| 332 /// branches. | 332 /// branches. |
| 333 class InstBr : public InstHighLevel { | 333 class InstBr : public InstHighLevel { |
| 334 InstBr() = delete; | 334 InstBr() = delete; |
| 335 InstBr(const InstBr &) = delete; | 335 InstBr(const InstBr &) = delete; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 355 CfgNode *getTargetTrue() const { return TargetTrue; } | 355 CfgNode *getTargetTrue() const { return TargetTrue; } |
| 356 CfgNode *getTargetFalse() const { return TargetFalse; } | 356 CfgNode *getTargetFalse() const { return TargetFalse; } |
| 357 CfgNode *getTargetUnconditional() const { | 357 CfgNode *getTargetUnconditional() const { |
| 358 assert(isUnconditional()); | 358 assert(isUnconditional()); |
| 359 return getTargetFalse(); | 359 return getTargetFalse(); |
| 360 } | 360 } |
| 361 NodeList getTerminatorEdges() const override; | 361 NodeList getTerminatorEdges() const override; |
| 362 bool isUnconditionalBranch() const override { return isUnconditional(); } | 362 bool isUnconditionalBranch() const override { return isUnconditional(); } |
| 363 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 363 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
| 364 void dump(const Cfg *Func) const override; | 364 void dump(const Cfg *Func) const override; |
| 365 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } | 365 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } |
| 366 | 366 |
| 367 private: | 367 private: |
| 368 /// Conditional branch | 368 /// Conditional branch |
| 369 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); | 369 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); |
| 370 /// Unconditional branch | 370 /// Unconditional branch |
| 371 InstBr(Cfg *Func, CfgNode *Target); | 371 InstBr(Cfg *Func, CfgNode *Target); |
| 372 | 372 |
| 373 CfgNode *TargetFalse; /// Doubles as unconditional branch target | 373 CfgNode *TargetFalse; /// Doubles as unconditional branch target |
| 374 CfgNode *TargetTrue; /// nullptr if unconditional branch | 374 CfgNode *TargetTrue; /// nullptr if unconditional branch |
| 375 }; | 375 }; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 394 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, | 394 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, |
| 395 IsTargetHelperCall, HasSideEffects, Kind); | 395 IsTargetHelperCall, HasSideEffects, Kind); |
| 396 } | 396 } |
| 397 void addArg(Operand *Arg) { addSource(Arg); } | 397 void addArg(Operand *Arg) { addSource(Arg); } |
| 398 Operand *getCallTarget() const { return getSrc(0); } | 398 Operand *getCallTarget() const { return getSrc(0); } |
| 399 Operand *getArg(SizeT I) const { return getSrc(I + 1); } | 399 Operand *getArg(SizeT I) const { return getSrc(I + 1); } |
| 400 SizeT getNumArgs() const { return getSrcSize() - 1; } | 400 SizeT getNumArgs() const { return getSrcSize() - 1; } |
| 401 bool isTailcall() const { return HasTailCall; } | 401 bool isTailcall() const { return HasTailCall; } |
| 402 bool isTargetHelperCall() const { return IsTargetHelperCall; } | 402 bool isTargetHelperCall() const { return IsTargetHelperCall; } |
| 403 void dump(const Cfg *Func) const override; | 403 void dump(const Cfg *Func) const override; |
| 404 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } | 404 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } |
| 405 Type getReturnType() const; | 405 Type getReturnType() const; |
| 406 | 406 |
| 407 protected: | 407 protected: |
| 408 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, | 408 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, |
| 409 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, | 409 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, |
| 410 InstKind Kind) | 410 InstKind Kind) |
| 411 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), | 411 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), |
| 412 IsTargetHelperCall(IsTargetHelperCall) { | 412 IsTargetHelperCall(IsTargetHelperCall) { |
| 413 HasSideEffects = HasSideEff; | 413 HasSideEffects = HasSideEff; |
| 414 addSource(CallTarget); | 414 addSource(CallTarget); |
| (...skipping 20 matching lines...) Expand all Loading... |
| 435 | 435 |
| 436 static const char *getCastName(OpKind Kind); | 436 static const char *getCastName(OpKind Kind); |
| 437 | 437 |
| 438 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, | 438 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
| 439 Operand *Source) { | 439 Operand *Source) { |
| 440 return new (Func->allocate<InstCast>()) | 440 return new (Func->allocate<InstCast>()) |
| 441 InstCast(Func, CastKind, Dest, Source); | 441 InstCast(Func, CastKind, Dest, Source); |
| 442 } | 442 } |
| 443 OpKind getCastKind() const { return CastKind; } | 443 OpKind getCastKind() const { return CastKind; } |
| 444 void dump(const Cfg *Func) const override; | 444 void dump(const Cfg *Func) const override; |
| 445 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 445 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } |
| 446 | 446 |
| 447 private: | 447 private: |
| 448 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 448 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
| 449 | 449 |
| 450 const OpKind CastKind; | 450 const OpKind CastKind; |
| 451 }; | 451 }; |
| 452 | 452 |
| 453 /// ExtractElement instruction. | 453 /// ExtractElement instruction. |
| 454 class InstExtractElement : public InstHighLevel { | 454 class InstExtractElement : public InstHighLevel { |
| 455 InstExtractElement() = delete; | 455 InstExtractElement() = delete; |
| 456 InstExtractElement(const InstExtractElement &) = delete; | 456 InstExtractElement(const InstExtractElement &) = delete; |
| 457 InstExtractElement &operator=(const InstExtractElement &) = delete; | 457 InstExtractElement &operator=(const InstExtractElement &) = delete; |
| 458 | 458 |
| 459 public: | 459 public: |
| 460 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 460 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 461 Operand *Source2) { | 461 Operand *Source2) { |
| 462 return new (Func->allocate<InstExtractElement>()) | 462 return new (Func->allocate<InstExtractElement>()) |
| 463 InstExtractElement(Func, Dest, Source1, Source2); | 463 InstExtractElement(Func, Dest, Source1, Source2); |
| 464 } | 464 } |
| 465 | 465 |
| 466 void dump(const Cfg *Func) const override; | 466 void dump(const Cfg *Func) const override; |
| 467 static bool classof(const Inst *Inst) { | 467 static bool classof(const Inst *Instr) { |
| 468 return Inst->getKind() == ExtractElement; | 468 return Instr->getKind() == ExtractElement; |
| 469 } | 469 } |
| 470 | 470 |
| 471 private: | 471 private: |
| 472 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 472 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 473 Operand *Source2); | 473 Operand *Source2); |
| 474 }; | 474 }; |
| 475 | 475 |
| 476 /// Floating-point comparison instruction. The source operands are captured in | 476 /// Floating-point comparison instruction. The source operands are captured in |
| 477 /// getSrc(0) and getSrc(1). | 477 /// getSrc(0) and getSrc(1). |
| 478 class InstFcmp : public InstHighLevel { | 478 class InstFcmp : public InstHighLevel { |
| 479 InstFcmp() = delete; | 479 InstFcmp() = delete; |
| 480 InstFcmp(const InstFcmp &) = delete; | 480 InstFcmp(const InstFcmp &) = delete; |
| 481 InstFcmp &operator=(const InstFcmp &) = delete; | 481 InstFcmp &operator=(const InstFcmp &) = delete; |
| 482 | 482 |
| 483 public: | 483 public: |
| 484 enum FCond { | 484 enum FCond { |
| 485 #define X(tag, str) tag, | 485 #define X(tag, str) tag, |
| 486 ICEINSTFCMP_TABLE | 486 ICEINSTFCMP_TABLE |
| 487 #undef X | 487 #undef X |
| 488 _num | 488 _num |
| 489 }; | 489 }; |
| 490 | 490 |
| 491 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 491 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
| 492 Operand *Source1, Operand *Source2) { | 492 Operand *Source1, Operand *Source2) { |
| 493 return new (Func->allocate<InstFcmp>()) | 493 return new (Func->allocate<InstFcmp>()) |
| 494 InstFcmp(Func, Condition, Dest, Source1, Source2); | 494 InstFcmp(Func, Condition, Dest, Source1, Source2); |
| 495 } | 495 } |
| 496 FCond getCondition() const { return Condition; } | 496 FCond getCondition() const { return Condition; } |
| 497 void dump(const Cfg *Func) const override; | 497 void dump(const Cfg *Func) const override; |
| 498 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } | 498 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } |
| 499 | 499 |
| 500 private: | 500 private: |
| 501 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 501 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
| 502 Operand *Source2); | 502 Operand *Source2); |
| 503 | 503 |
| 504 const FCond Condition; | 504 const FCond Condition; |
| 505 }; | 505 }; |
| 506 | 506 |
| 507 /// Integer comparison instruction. The source operands are captured in | 507 /// Integer comparison instruction. The source operands are captured in |
| 508 /// getSrc(0) and getSrc(1). | 508 /// getSrc(0) and getSrc(1). |
| (...skipping 10 matching lines...) Expand all Loading... |
| 519 _num | 519 _num |
| 520 }; | 520 }; |
| 521 | 521 |
| 522 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 522 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
| 523 Operand *Source1, Operand *Source2) { | 523 Operand *Source1, Operand *Source2) { |
| 524 return new (Func->allocate<InstIcmp>()) | 524 return new (Func->allocate<InstIcmp>()) |
| 525 InstIcmp(Func, Condition, Dest, Source1, Source2); | 525 InstIcmp(Func, Condition, Dest, Source1, Source2); |
| 526 } | 526 } |
| 527 ICond getCondition() const { return Condition; } | 527 ICond getCondition() const { return Condition; } |
| 528 void dump(const Cfg *Func) const override; | 528 void dump(const Cfg *Func) const override; |
| 529 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 529 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } |
| 530 | 530 |
| 531 private: | 531 private: |
| 532 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 532 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
| 533 Operand *Source2); | 533 Operand *Source2); |
| 534 | 534 |
| 535 const ICond Condition; | 535 const ICond Condition; |
| 536 }; | 536 }; |
| 537 | 537 |
| 538 /// InsertElement instruction. | 538 /// InsertElement instruction. |
| 539 class InstInsertElement : public InstHighLevel { | 539 class InstInsertElement : public InstHighLevel { |
| 540 InstInsertElement() = delete; | 540 InstInsertElement() = delete; |
| 541 InstInsertElement(const InstInsertElement &) = delete; | 541 InstInsertElement(const InstInsertElement &) = delete; |
| 542 InstInsertElement &operator=(const InstInsertElement &) = delete; | 542 InstInsertElement &operator=(const InstInsertElement &) = delete; |
| 543 | 543 |
| 544 public: | 544 public: |
| 545 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 545 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 546 Operand *Source2, Operand *Source3) { | 546 Operand *Source2, Operand *Source3) { |
| 547 return new (Func->allocate<InstInsertElement>()) | 547 return new (Func->allocate<InstInsertElement>()) |
| 548 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 548 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
| 549 } | 549 } |
| 550 | 550 |
| 551 void dump(const Cfg *Func) const override; | 551 void dump(const Cfg *Func) const override; |
| 552 static bool classof(const Inst *Inst) { | 552 static bool classof(const Inst *Instr) { |
| 553 return Inst->getKind() == InsertElement; | 553 return Instr->getKind() == InsertElement; |
| 554 } | 554 } |
| 555 | 555 |
| 556 private: | 556 private: |
| 557 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 557 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 558 Operand *Source2, Operand *Source3); | 558 Operand *Source2, Operand *Source3); |
| 559 }; | 559 }; |
| 560 | 560 |
| 561 /// Call to an intrinsic function. The call target is captured as getSrc(0), and | 561 /// Call to an intrinsic function. The call target is captured as getSrc(0), and |
| 562 /// arg I is captured as getSrc(I+1). | 562 /// arg I is captured as getSrc(I+1). |
| 563 class InstIntrinsicCall : public InstCall { | 563 class InstIntrinsicCall : public InstCall { |
| 564 InstIntrinsicCall() = delete; | 564 InstIntrinsicCall() = delete; |
| 565 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | 565 InstIntrinsicCall(const InstIntrinsicCall &) = delete; |
| 566 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | 566 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; |
| 567 | 567 |
| 568 public: | 568 public: |
| 569 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 569 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 570 Operand *CallTarget, | 570 Operand *CallTarget, |
| 571 const Intrinsics::IntrinsicInfo &Info) { | 571 const Intrinsics::IntrinsicInfo &Info) { |
| 572 return new (Func->allocate<InstIntrinsicCall>()) | 572 return new (Func->allocate<InstIntrinsicCall>()) |
| 573 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 573 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
| 574 } | 574 } |
| 575 static bool classof(const Inst *Inst) { | 575 static bool classof(const Inst *Instr) { |
| 576 return Inst->getKind() == IntrinsicCall; | 576 return Instr->getKind() == IntrinsicCall; |
| 577 } | 577 } |
| 578 | 578 |
| 579 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 579 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
| 580 | 580 |
| 581 private: | 581 private: |
| 582 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 582 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 583 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 583 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
| 584 : InstCall(Func, NumArgs, Dest, CallTarget, false, false, | 584 : InstCall(Func, NumArgs, Dest, CallTarget, false, false, |
| 585 Info.HasSideEffects, Inst::IntrinsicCall), | 585 Info.HasSideEffects, Inst::IntrinsicCall), |
| 586 Info(Info) {} | 586 Info(Info) {} |
| 587 | 587 |
| 588 const Intrinsics::IntrinsicInfo Info; | 588 const Intrinsics::IntrinsicInfo Info; |
| 589 }; | 589 }; |
| 590 | 590 |
| 591 /// Load instruction. The source address is captured in getSrc(0). | 591 /// Load instruction. The source address is captured in getSrc(0). |
| 592 class InstLoad : public InstHighLevel { | 592 class InstLoad : public InstHighLevel { |
| 593 InstLoad() = delete; | 593 InstLoad() = delete; |
| 594 InstLoad(const InstLoad &) = delete; | 594 InstLoad(const InstLoad &) = delete; |
| 595 InstLoad &operator=(const InstLoad &) = delete; | 595 InstLoad &operator=(const InstLoad &) = delete; |
| 596 | 596 |
| 597 public: | 597 public: |
| 598 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 598 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
| 599 uint32_t Align = 1) { | 599 uint32_t Align = 1) { |
| 600 // TODO(kschimpf) Stop ignoring alignment specification. | 600 // TODO(kschimpf) Stop ignoring alignment specification. |
| 601 (void)Align; | 601 (void)Align; |
| 602 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); | 602 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
| 603 } | 603 } |
| 604 Operand *getSourceAddress() const { return getSrc(0); } | 604 Operand *getSourceAddress() const { return getSrc(0); } |
| 605 void dump(const Cfg *Func) const override; | 605 void dump(const Cfg *Func) const override; |
| 606 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } | 606 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } |
| 607 | 607 |
| 608 private: | 608 private: |
| 609 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 609 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
| 610 }; | 610 }; |
| 611 | 611 |
| 612 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi | 612 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi |
| 613 /// source operand is getSrc(I). | 613 /// source operand is getSrc(I). |
| 614 class InstPhi : public InstHighLevel { | 614 class InstPhi : public InstHighLevel { |
| 615 InstPhi() = delete; | 615 InstPhi() = delete; |
| 616 InstPhi(const InstPhi &) = delete; | 616 InstPhi(const InstPhi &) = delete; |
| 617 InstPhi &operator=(const InstPhi &) = delete; | 617 InstPhi &operator=(const InstPhi &) = delete; |
| 618 | 618 |
| 619 public: | 619 public: |
| 620 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 620 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
| 621 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 621 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
| 622 } | 622 } |
| 623 void addArgument(Operand *Source, CfgNode *Label); | 623 void addArgument(Operand *Source, CfgNode *Label); |
| 624 Operand *getOperandForTarget(CfgNode *Target) const; | 624 Operand *getOperandForTarget(CfgNode *Target) const; |
| 625 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } | 625 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } |
| 626 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 626 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
| 627 Liveness *Liveness); | 627 Liveness *Liveness); |
| 628 Inst *lower(Cfg *Func); | 628 Inst *lower(Cfg *Func); |
| 629 void dump(const Cfg *Func) const override; | 629 void dump(const Cfg *Func) const override; |
| 630 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } | 630 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } |
| 631 | 631 |
| 632 private: | 632 private: |
| 633 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 633 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
| 634 void destroy(Cfg *Func) override { | 634 void destroy(Cfg *Func) override { |
| 635 Func->deallocateArrayOf<CfgNode *>(Labels); | 635 Func->deallocateArrayOf<CfgNode *>(Labels); |
| 636 Inst::destroy(Func); | 636 Inst::destroy(Func); |
| 637 } | 637 } |
| 638 | 638 |
| 639 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, | 639 /// Labels[] duplicates the InEdges[] information in the enclosing CfgNode, |
| 640 /// but the Phi instruction is created before InEdges[] is available, so it's | 640 /// but the Phi instruction is created before InEdges[] is available, so it's |
| (...skipping 13 matching lines...) Expand all Loading... |
| 654 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { | 654 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { |
| 655 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); | 655 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); |
| 656 } | 656 } |
| 657 bool hasRetValue() const { return getSrcSize(); } | 657 bool hasRetValue() const { return getSrcSize(); } |
| 658 Operand *getRetValue() const { | 658 Operand *getRetValue() const { |
| 659 assert(hasRetValue()); | 659 assert(hasRetValue()); |
| 660 return getSrc(0); | 660 return getSrc(0); |
| 661 } | 661 } |
| 662 NodeList getTerminatorEdges() const override { return NodeList(); } | 662 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 663 void dump(const Cfg *Func) const override; | 663 void dump(const Cfg *Func) const override; |
| 664 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } | 664 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } |
| 665 | 665 |
| 666 private: | 666 private: |
| 667 InstRet(Cfg *Func, Operand *RetValue); | 667 InstRet(Cfg *Func, Operand *RetValue); |
| 668 }; | 668 }; |
| 669 | 669 |
| 670 /// Select instruction. The condition, true, and false operands are captured. | 670 /// Select instruction. The condition, true, and false operands are captured. |
| 671 class InstSelect : public InstHighLevel { | 671 class InstSelect : public InstHighLevel { |
| 672 InstSelect() = delete; | 672 InstSelect() = delete; |
| 673 InstSelect(const InstSelect &) = delete; | 673 InstSelect(const InstSelect &) = delete; |
| 674 InstSelect &operator=(const InstSelect &) = delete; | 674 InstSelect &operator=(const InstSelect &) = delete; |
| 675 | 675 |
| 676 public: | 676 public: |
| 677 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 677 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
| 678 Operand *SourceTrue, Operand *SourceFalse) { | 678 Operand *SourceTrue, Operand *SourceFalse) { |
| 679 return new (Func->allocate<InstSelect>()) | 679 return new (Func->allocate<InstSelect>()) |
| 680 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 680 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
| 681 } | 681 } |
| 682 Operand *getCondition() const { return getSrc(0); } | 682 Operand *getCondition() const { return getSrc(0); } |
| 683 Operand *getTrueOperand() const { return getSrc(1); } | 683 Operand *getTrueOperand() const { return getSrc(1); } |
| 684 Operand *getFalseOperand() const { return getSrc(2); } | 684 Operand *getFalseOperand() const { return getSrc(2); } |
| 685 void dump(const Cfg *Func) const override; | 685 void dump(const Cfg *Func) const override; |
| 686 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } | 686 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } |
| 687 | 687 |
| 688 private: | 688 private: |
| 689 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 689 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
| 690 Operand *Source2); | 690 Operand *Source2); |
| 691 }; | 691 }; |
| 692 | 692 |
| 693 /// Store instruction. The address operand is captured, along with the data | 693 /// Store instruction. The address operand is captured, along with the data |
| 694 /// operand to be stored into the address. | 694 /// operand to be stored into the address. |
| 695 class InstStore : public InstHighLevel { | 695 class InstStore : public InstHighLevel { |
| 696 InstStore() = delete; | 696 InstStore() = delete; |
| 697 InstStore(const InstStore &) = delete; | 697 InstStore(const InstStore &) = delete; |
| 698 InstStore &operator=(const InstStore &) = delete; | 698 InstStore &operator=(const InstStore &) = delete; |
| 699 | 699 |
| 700 public: | 700 public: |
| 701 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, | 701 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, |
| 702 uint32_t Align = 1) { | 702 uint32_t Align = 1) { |
| 703 // TODO(kschimpf) Stop ignoring alignment specification. | 703 // TODO(kschimpf) Stop ignoring alignment specification. |
| 704 (void)Align; | 704 (void)Align; |
| 705 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); | 705 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); |
| 706 } | 706 } |
| 707 Operand *getAddr() const { return getSrc(1); } | 707 Operand *getAddr() const { return getSrc(1); } |
| 708 Operand *getData() const { return getSrc(0); } | 708 Operand *getData() const { return getSrc(0); } |
| 709 Variable *getRmwBeacon() const; | 709 Variable *getRmwBeacon() const; |
| 710 void setRmwBeacon(Variable *Beacon); | 710 void setRmwBeacon(Variable *Beacon); |
| 711 void dump(const Cfg *Func) const override; | 711 void dump(const Cfg *Func) const override; |
| 712 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } | 712 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } |
| 713 | 713 |
| 714 private: | 714 private: |
| 715 InstStore(Cfg *Func, Operand *Data, Operand *Addr); | 715 InstStore(Cfg *Func, Operand *Data, Operand *Addr); |
| 716 }; | 716 }; |
| 717 | 717 |
| 718 /// Switch instruction. The single source operand is captured as getSrc(0). | 718 /// Switch instruction. The single source operand is captured as getSrc(0). |
| 719 class InstSwitch : public InstHighLevel { | 719 class InstSwitch : public InstHighLevel { |
| 720 InstSwitch() = delete; | 720 InstSwitch() = delete; |
| 721 InstSwitch(const InstSwitch &) = delete; | 721 InstSwitch(const InstSwitch &) = delete; |
| 722 InstSwitch &operator=(const InstSwitch &) = delete; | 722 InstSwitch &operator=(const InstSwitch &) = delete; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 735 return Values[I]; | 735 return Values[I]; |
| 736 } | 736 } |
| 737 CfgNode *getLabel(SizeT I) const { | 737 CfgNode *getLabel(SizeT I) const { |
| 738 assert(I < NumCases); | 738 assert(I < NumCases); |
| 739 return Labels[I]; | 739 return Labels[I]; |
| 740 } | 740 } |
| 741 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); | 741 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); |
| 742 NodeList getTerminatorEdges() const override; | 742 NodeList getTerminatorEdges() const override; |
| 743 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 743 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
| 744 void dump(const Cfg *Func) const override; | 744 void dump(const Cfg *Func) const override; |
| 745 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } | 745 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } |
| 746 | 746 |
| 747 private: | 747 private: |
| 748 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); | 748 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); |
| 749 void destroy(Cfg *Func) override { | 749 void destroy(Cfg *Func) override { |
| 750 Func->deallocateArrayOf<uint64_t>(Values); | 750 Func->deallocateArrayOf<uint64_t>(Values); |
| 751 Func->deallocateArrayOf<CfgNode *>(Labels); | 751 Func->deallocateArrayOf<CfgNode *>(Labels); |
| 752 Inst::destroy(Func); | 752 Inst::destroy(Func); |
| 753 } | 753 } |
| 754 | 754 |
| 755 CfgNode *LabelDefault; | 755 CfgNode *LabelDefault; |
| 756 SizeT NumCases; /// not including the default case | 756 SizeT NumCases; /// not including the default case |
| 757 uint64_t *Values; /// size is NumCases | 757 uint64_t *Values; /// size is NumCases |
| 758 CfgNode **Labels; /// size is NumCases | 758 CfgNode **Labels; /// size is NumCases |
| 759 }; | 759 }; |
| 760 | 760 |
| 761 /// Unreachable instruction. This is a terminator instruction with no operands. | 761 /// Unreachable instruction. This is a terminator instruction with no operands. |
| 762 class InstUnreachable : public InstHighLevel { | 762 class InstUnreachable : public InstHighLevel { |
| 763 InstUnreachable() = delete; | 763 InstUnreachable() = delete; |
| 764 InstUnreachable(const InstUnreachable &) = delete; | 764 InstUnreachable(const InstUnreachable &) = delete; |
| 765 InstUnreachable &operator=(const InstUnreachable &) = delete; | 765 InstUnreachable &operator=(const InstUnreachable &) = delete; |
| 766 | 766 |
| 767 public: | 767 public: |
| 768 static InstUnreachable *create(Cfg *Func) { | 768 static InstUnreachable *create(Cfg *Func) { |
| 769 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); | 769 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
| 770 } | 770 } |
| 771 NodeList getTerminatorEdges() const override { return NodeList(); } | 771 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 772 void dump(const Cfg *Func) const override; | 772 void dump(const Cfg *Func) const override; |
| 773 static bool classof(const Inst *Inst) { | 773 static bool classof(const Inst *Instr) { |
| 774 return Inst->getKind() == Unreachable; | 774 return Instr->getKind() == Unreachable; |
| 775 } | 775 } |
| 776 | 776 |
| 777 private: | 777 private: |
| 778 explicit InstUnreachable(Cfg *Func); | 778 explicit InstUnreachable(Cfg *Func); |
| 779 }; | 779 }; |
| 780 | 780 |
| 781 /// BundleLock instruction. There are no operands. Contains an option | 781 /// BundleLock instruction. There are no operands. Contains an option |
| 782 /// indicating whether align_to_end is specified. | 782 /// indicating whether align_to_end is specified. |
| 783 class InstBundleLock : public InstHighLevel { | 783 class InstBundleLock : public InstHighLevel { |
| 784 InstBundleLock() = delete; | 784 InstBundleLock() = delete; |
| 785 InstBundleLock(const InstBundleLock &) = delete; | 785 InstBundleLock(const InstBundleLock &) = delete; |
| 786 InstBundleLock &operator=(const InstBundleLock &) = delete; | 786 InstBundleLock &operator=(const InstBundleLock &) = delete; |
| 787 | 787 |
| 788 public: | 788 public: |
| 789 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; | 789 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; |
| 790 static InstBundleLock *create(Cfg *Func, Option BundleOption) { | 790 static InstBundleLock *create(Cfg *Func, Option BundleOption) { |
| 791 return new (Func->allocate<InstBundleLock>()) | 791 return new (Func->allocate<InstBundleLock>()) |
| 792 InstBundleLock(Func, BundleOption); | 792 InstBundleLock(Func, BundleOption); |
| 793 } | 793 } |
| 794 void emit(const Cfg *Func) const override; | 794 void emit(const Cfg *Func) const override; |
| 795 void emitIAS(const Cfg * /* Func */) const override {} | 795 void emitIAS(const Cfg * /* Func */) const override {} |
| 796 void dump(const Cfg *Func) const override; | 796 void dump(const Cfg *Func) const override; |
| 797 Option getOption() const { return BundleOption; } | 797 Option getOption() const { return BundleOption; } |
| 798 static bool classof(const Inst *Inst) { | 798 static bool classof(const Inst *Instr) { |
| 799 return Inst->getKind() == BundleLock; | 799 return Instr->getKind() == BundleLock; |
| 800 } | 800 } |
| 801 | 801 |
| 802 private: | 802 private: |
| 803 Option BundleOption; | 803 Option BundleOption; |
| 804 InstBundleLock(Cfg *Func, Option BundleOption); | 804 InstBundleLock(Cfg *Func, Option BundleOption); |
| 805 }; | 805 }; |
| 806 | 806 |
| 807 /// BundleUnlock instruction. There are no operands. | 807 /// BundleUnlock instruction. There are no operands. |
| 808 class InstBundleUnlock : public InstHighLevel { | 808 class InstBundleUnlock : public InstHighLevel { |
| 809 InstBundleUnlock() = delete; | 809 InstBundleUnlock() = delete; |
| 810 InstBundleUnlock(const InstBundleUnlock &) = delete; | 810 InstBundleUnlock(const InstBundleUnlock &) = delete; |
| 811 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; | 811 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; |
| 812 | 812 |
| 813 public: | 813 public: |
| 814 static InstBundleUnlock *create(Cfg *Func) { | 814 static InstBundleUnlock *create(Cfg *Func) { |
| 815 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); | 815 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); |
| 816 } | 816 } |
| 817 void emit(const Cfg *Func) const override; | 817 void emit(const Cfg *Func) const override; |
| 818 void emitIAS(const Cfg * /* Func */) const override {} | 818 void emitIAS(const Cfg * /* Func */) const override {} |
| 819 void dump(const Cfg *Func) const override; | 819 void dump(const Cfg *Func) const override; |
| 820 static bool classof(const Inst *Inst) { | 820 static bool classof(const Inst *Instr) { |
| 821 return Inst->getKind() == BundleUnlock; | 821 return Instr->getKind() == BundleUnlock; |
| 822 } | 822 } |
| 823 | 823 |
| 824 private: | 824 private: |
| 825 explicit InstBundleUnlock(Cfg *Func); | 825 explicit InstBundleUnlock(Cfg *Func); |
| 826 }; | 826 }; |
| 827 | 827 |
| 828 /// FakeDef instruction. This creates a fake definition of a variable, which is | 828 /// FakeDef instruction. This creates a fake definition of a variable, which is |
| 829 /// how we represent the case when an instruction produces multiple results. | 829 /// how we represent the case when an instruction produces multiple results. |
| 830 /// This doesn't happen with high-level ICE instructions, but might with lowered | 830 /// This doesn't happen with high-level ICE instructions, but might with lowered |
| 831 /// instructions. For example, this would be a way to represent condition flags | 831 /// instructions. For example, this would be a way to represent condition flags |
| (...skipping 10 matching lines...) Expand all Loading... |
| 842 InstFakeDef &operator=(const InstFakeDef &) = delete; | 842 InstFakeDef &operator=(const InstFakeDef &) = delete; |
| 843 | 843 |
| 844 public: | 844 public: |
| 845 static InstFakeDef *create(Cfg *Func, Variable *Dest, | 845 static InstFakeDef *create(Cfg *Func, Variable *Dest, |
| 846 Variable *Src = nullptr) { | 846 Variable *Src = nullptr) { |
| 847 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 847 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
| 848 } | 848 } |
| 849 void emit(const Cfg *Func) const override; | 849 void emit(const Cfg *Func) const override; |
| 850 void emitIAS(const Cfg * /* Func */) const override {} | 850 void emitIAS(const Cfg * /* Func */) const override {} |
| 851 void dump(const Cfg *Func) const override; | 851 void dump(const Cfg *Func) const override; |
| 852 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } | 852 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } |
| 853 | 853 |
| 854 private: | 854 private: |
| 855 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 855 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
| 856 }; | 856 }; |
| 857 | 857 |
| 858 /// FakeUse instruction. This creates a fake use of a variable, to keep the | 858 /// FakeUse instruction. This creates a fake use of a variable, to keep the |
| 859 /// instruction that produces that variable from being dead-code eliminated. | 859 /// instruction that produces that variable from being dead-code eliminated. |
| 860 /// This is useful in a variety of lowering situations. The FakeUse instruction | 860 /// This is useful in a variety of lowering situations. The FakeUse instruction |
| 861 /// has no dest, so it can itself never be dead-code eliminated. A weight can | 861 /// has no dest, so it can itself never be dead-code eliminated. A weight can |
| 862 /// be provided to provide extra bias to the register allocator - for simplicity | 862 /// be provided to provide extra bias to the register allocator - for simplicity |
| 863 /// of implementation, weight=N is handled by holding N copies of the variable | 863 /// of implementation, weight=N is handled by holding N copies of the variable |
| 864 /// as source operands. | 864 /// as source operands. |
| 865 class InstFakeUse : public InstHighLevel { | 865 class InstFakeUse : public InstHighLevel { |
| 866 InstFakeUse() = delete; | 866 InstFakeUse() = delete; |
| 867 InstFakeUse(const InstFakeUse &) = delete; | 867 InstFakeUse(const InstFakeUse &) = delete; |
| 868 InstFakeUse &operator=(const InstFakeUse &) = delete; | 868 InstFakeUse &operator=(const InstFakeUse &) = delete; |
| 869 | 869 |
| 870 public: | 870 public: |
| 871 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { | 871 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { |
| 872 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); | 872 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); |
| 873 } | 873 } |
| 874 void emit(const Cfg *Func) const override; | 874 void emit(const Cfg *Func) const override; |
| 875 void emitIAS(const Cfg * /* Func */) const override {} | 875 void emitIAS(const Cfg * /* Func */) const override {} |
| 876 void dump(const Cfg *Func) const override; | 876 void dump(const Cfg *Func) const override; |
| 877 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } | 877 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } |
| 878 | 878 |
| 879 private: | 879 private: |
| 880 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); | 880 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); |
| 881 }; | 881 }; |
| 882 | 882 |
| 883 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial | 883 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial |
| 884 /// live range at this instruction for each (implicit) variable. The primary use | 884 /// live range at this instruction for each (implicit) variable. The primary use |
| 885 /// is to indicate that scratch registers are killed after a call, so that the | 885 /// is to indicate that scratch registers are killed after a call, so that the |
| 886 /// register allocator won't assign a scratch register to a variable whose live | 886 /// register allocator won't assign a scratch register to a variable whose live |
| 887 /// range spans a call. | 887 /// range spans a call. |
| 888 /// | 888 /// |
| 889 /// The FakeKill instruction also holds a pointer to the instruction that kills | 889 /// The FakeKill instruction also holds a pointer to the instruction that kills |
| 890 /// the set of variables, so that if that linked instruction gets dead-code | 890 /// the set of variables, so that if that linked instruction gets dead-code |
| 891 /// eliminated, the FakeKill instruction will as well. | 891 /// eliminated, the FakeKill instruction will as well. |
| 892 class InstFakeKill : public InstHighLevel { | 892 class InstFakeKill : public InstHighLevel { |
| 893 InstFakeKill() = delete; | 893 InstFakeKill() = delete; |
| 894 InstFakeKill(const InstFakeKill &) = delete; | 894 InstFakeKill(const InstFakeKill &) = delete; |
| 895 InstFakeKill &operator=(const InstFakeKill &) = delete; | 895 InstFakeKill &operator=(const InstFakeKill &) = delete; |
| 896 | 896 |
| 897 public: | 897 public: |
| 898 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { | 898 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { |
| 899 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); | 899 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); |
| 900 } | 900 } |
| 901 const Inst *getLinked() const { return Linked; } | 901 const Inst *getLinked() const { return Linked; } |
| 902 void emit(const Cfg *Func) const override; | 902 void emit(const Cfg *Func) const override; |
| 903 void emitIAS(const Cfg * /* Func */) const override {} | 903 void emitIAS(const Cfg * /* Func */) const override {} |
| 904 void dump(const Cfg *Func) const override; | 904 void dump(const Cfg *Func) const override; |
| 905 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } | 905 static bool classof(const Inst *Instr) { |
| 906 return Instr->getKind() == FakeKill; |
| 907 } |
| 906 | 908 |
| 907 private: | 909 private: |
| 908 InstFakeKill(Cfg *Func, const Inst *Linked); | 910 InstFakeKill(Cfg *Func, const Inst *Linked); |
| 909 | 911 |
| 910 /// This instruction is ignored if Linked->isDeleted() is true. | 912 /// This instruction is ignored if Linked->isDeleted() is true. |
| 911 const Inst *Linked; | 913 const Inst *Linked; |
| 912 }; | 914 }; |
| 913 | 915 |
| 914 /// JumpTable instruction. This represents a jump table that will be stored in | 916 /// JumpTable instruction. This represents a jump table that will be stored in |
| 915 /// the .rodata section. This is used to track and repoint the target CfgNodes | 917 /// the .rodata section. This is used to track and repoint the target CfgNodes |
| (...skipping 13 matching lines...) Expand all Loading... |
| 929 Targets[TargetIndex] = Target; | 931 Targets[TargetIndex] = Target; |
| 930 } | 932 } |
| 931 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 933 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
| 932 SizeT getId() const { return Id; } | 934 SizeT getId() const { return Id; } |
| 933 SizeT getNumTargets() const { return NumTargets; } | 935 SizeT getNumTargets() const { return NumTargets; } |
| 934 CfgNode *getTarget(SizeT I) const { | 936 CfgNode *getTarget(SizeT I) const { |
| 935 assert(I < NumTargets); | 937 assert(I < NumTargets); |
| 936 return Targets[I]; | 938 return Targets[I]; |
| 937 } | 939 } |
| 938 void dump(const Cfg *Func) const override; | 940 void dump(const Cfg *Func) const override; |
| 939 static bool classof(const Inst *Inst) { return Inst->getKind() == JumpTable; } | 941 static bool classof(const Inst *Instr) { |
| 942 return Instr->getKind() == JumpTable; |
| 943 } |
| 940 | 944 |
| 941 static IceString makeName(const IceString &FuncName, SizeT Id) { | 945 static IceString makeName(const IceString &FuncName, SizeT Id) { |
| 942 return ".L" + FuncName + "$jumptable$__" + std::to_string(Id); | 946 return ".L" + FuncName + "$jumptable$__" + std::to_string(Id); |
| 943 } | 947 } |
| 944 | 948 |
| 945 private: | 949 private: |
| 946 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); | 950 InstJumpTable(Cfg *Func, SizeT NumTargets, CfgNode *Default); |
| 947 void destroy(Cfg *Func) override { | 951 void destroy(Cfg *Func) override { |
| 948 Func->deallocateArrayOf<CfgNode *>(Targets); | 952 Func->deallocateArrayOf<CfgNode *>(Targets); |
| 949 Inst::destroy(Func); | 953 Inst::destroy(Func); |
| 950 } | 954 } |
| 951 | 955 |
| 952 const SizeT Id; | 956 const SizeT Id; |
| 953 const SizeT NumTargets; | 957 const SizeT NumTargets; |
| 954 CfgNode **Targets; | 958 CfgNode **Targets; |
| 955 }; | 959 }; |
| 956 | 960 |
| 957 /// The Target instruction is the base class for all target-specific | 961 /// The Target instruction is the base class for all target-specific |
| 958 /// instructions. | 962 /// instructions. |
| 959 class InstTarget : public Inst { | 963 class InstTarget : public Inst { |
| 960 InstTarget() = delete; | 964 InstTarget() = delete; |
| 961 InstTarget(const InstTarget &) = delete; | 965 InstTarget(const InstTarget &) = delete; |
| 962 InstTarget &operator=(const InstTarget &) = delete; | 966 InstTarget &operator=(const InstTarget &) = delete; |
| 963 | 967 |
| 964 public: | 968 public: |
| 965 uint32_t getEmitInstCount() const override { return 1; } | 969 uint32_t getEmitInstCount() const override { return 1; } |
| 966 void dump(const Cfg *Func) const override; | 970 void dump(const Cfg *Func) const override; |
| 967 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 971 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } |
| 968 | 972 |
| 969 protected: | 973 protected: |
| 970 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 974 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 971 : Inst(Func, Kind, MaxSrcs, Dest) { | 975 : Inst(Func, Kind, MaxSrcs, Dest) { |
| 972 assert(Kind >= Target); | 976 assert(Kind >= Target); |
| 973 assert(Kind <= Target_Max); | 977 assert(Kind <= Target_Max); |
| 974 } | 978 } |
| 975 }; | 979 }; |
| 976 | 980 |
| 977 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); | 981 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 993 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 997 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
| 994 void deleteNode(Ice::Inst *) {} | 998 void deleteNode(Ice::Inst *) {} |
| 995 | 999 |
| 996 private: | 1000 private: |
| 997 mutable ilist_half_node<Ice::Inst> Sentinel; | 1001 mutable ilist_half_node<Ice::Inst> Sentinel; |
| 998 }; | 1002 }; |
| 999 | 1003 |
| 1000 } // end of namespace llvm | 1004 } // end of namespace llvm |
| 1001 | 1005 |
| 1002 #endif // SUBZERO_SRC_ICEINST_H | 1006 #endif // SUBZERO_SRC_ICEINST_H |
| OLD | NEW |