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 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { | 128 virtual bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) { |
129 (void)OldNode; | 129 (void)OldNode; |
130 (void)NewNode; | 130 (void)NewNode; |
131 return false; | 131 return false; |
132 } | 132 } |
133 | 133 |
134 /// Returns true if the instruction is equivalent to a simple | 134 /// Returns true if the instruction is equivalent to a simple |
135 /// "var_dest=var_src" assignment where the dest and src are both variables. | 135 /// "var_dest=var_src" assignment where the dest and src are both variables. |
136 virtual bool isVarAssign() const { return false; } | 136 virtual bool isVarAssign() const { return false; } |
137 | 137 |
138 /// Returns true if the instruction has a possible side effect of changing | |
139 /// memory, in which case a memory load should not be reordered with respect | |
140 /// to this instruction. We make it return true by default for safety when | |
141 /// new ICE instructions are defined. | |
142 virtual bool isMemoryWrite() const { return true; } | |
John
2016/04/21 22:50:01
what's wrong with = 0, and forcing each new classe
Jim Stichnoth
2016/04/21 23:31:35
Done.
Jim Stichnoth
2016/04/21 23:32:41
Whoops, what I meant was, that would be nice excep
| |
143 | |
138 void livenessLightweight(Cfg *Func, LivenessBV &Live); | 144 void livenessLightweight(Cfg *Func, LivenessBV &Live); |
139 /// Calculates liveness for this instruction. Returns true if this instruction | 145 /// Calculates liveness for this instruction. Returns true if this instruction |
140 /// is (tentatively) still live and should be retained, and false if this | 146 /// is (tentatively) still live and should be retained, and false if this |
141 /// instruction is (tentatively) dead and should be deleted. The decision is | 147 /// instruction is (tentatively) dead and should be deleted. The decision is |
142 /// tentative until the liveness dataflow algorithm has converged, and then a | 148 /// tentative until the liveness dataflow algorithm has converged, and then a |
143 /// separate pass permanently deletes dead instructions. | 149 /// separate pass permanently deletes dead instructions. |
144 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, | 150 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, |
145 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); | 151 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); |
146 | 152 |
147 /// Get the number of native instructions that this instruction ultimately | 153 /// Get the number of native instructions that this instruction ultimately |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
252 public: | 258 public: |
253 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, | 259 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, |
254 uint32_t AlignInBytes) { | 260 uint32_t AlignInBytes) { |
255 return new (Func->allocate<InstAlloca>()) | 261 return new (Func->allocate<InstAlloca>()) |
256 InstAlloca(Func, Dest, ByteCount, AlignInBytes); | 262 InstAlloca(Func, Dest, ByteCount, AlignInBytes); |
257 } | 263 } |
258 uint32_t getAlignInBytes() const { return AlignInBytes; } | 264 uint32_t getAlignInBytes() const { return AlignInBytes; } |
259 Operand *getSizeInBytes() const { return getSrc(0); } | 265 Operand *getSizeInBytes() const { return getSrc(0); } |
260 bool getKnownFrameOffset() const { return KnownFrameOffset; } | 266 bool getKnownFrameOffset() const { return KnownFrameOffset; } |
261 void setKnownFrameOffset() { KnownFrameOffset = true; } | 267 void setKnownFrameOffset() { KnownFrameOffset = true; } |
268 bool isMemoryWrite() const final { return false; } | |
Eric Holk
2016/04/21 22:09:43
What's the reasoning for making these final?
John
2016/04/21 22:50:01
I tend to prefer using final for classes only. If
Jim Stichnoth
2016/04/21 22:50:28
We seem to do that quite regularly in Subzero so I
Jim Stichnoth
2016/04/21 23:31:35
Done.
| |
262 void dump(const Cfg *Func) const override; | 269 void dump(const Cfg *Func) const override; |
263 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } | 270 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } |
264 | 271 |
265 private: | 272 private: |
266 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, | 273 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, |
267 uint32_t AlignInBytes); | 274 uint32_t AlignInBytes); |
268 | 275 |
269 const uint32_t AlignInBytes; | 276 const uint32_t AlignInBytes; |
270 bool KnownFrameOffset = false; | 277 bool KnownFrameOffset = false; |
271 }; | 278 }; |
(...skipping 17 matching lines...) Expand all Loading... | |
289 Operand *Source1, Operand *Source2) { | 296 Operand *Source1, Operand *Source2) { |
290 return new (Func->allocate<InstArithmetic>()) | 297 return new (Func->allocate<InstArithmetic>()) |
291 InstArithmetic(Func, Op, Dest, Source1, Source2); | 298 InstArithmetic(Func, Op, Dest, Source1, Source2); |
292 } | 299 } |
293 OpKind getOp() const { return Op; } | 300 OpKind getOp() const { return Op; } |
294 | 301 |
295 virtual const char *getInstName() const override; | 302 virtual const char *getInstName() const override; |
296 | 303 |
297 static const char *getOpName(OpKind Op); | 304 static const char *getOpName(OpKind Op); |
298 bool isCommutative() const; | 305 bool isCommutative() const; |
306 bool isMemoryWrite() const final { return false; } | |
299 void dump(const Cfg *Func) const override; | 307 void dump(const Cfg *Func) const override; |
300 static bool classof(const Inst *Instr) { | 308 static bool classof(const Inst *Instr) { |
301 return Instr->getKind() == Arithmetic; | 309 return Instr->getKind() == Arithmetic; |
302 } | 310 } |
303 | 311 |
304 private: | 312 private: |
305 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, | 313 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, |
306 Operand *Source2); | 314 Operand *Source2); |
307 | 315 |
308 const OpKind Op; | 316 const OpKind Op; |
309 }; | 317 }; |
310 | 318 |
311 /// Assignment instruction. The source operand is captured in getSrc(0). This is | 319 /// Assignment instruction. The source operand is captured in getSrc(0). This is |
312 /// not part of the LLVM bitcode, but is a useful abstraction for some of the | 320 /// not part of the LLVM bitcode, but is a useful abstraction for some of the |
313 /// lowering. E.g., if Phi instruction lowering happens before target lowering, | 321 /// lowering. E.g., if Phi instruction lowering happens before target lowering, |
314 /// or for representing an Inttoptr instruction, or as an intermediate step for | 322 /// or for representing an Inttoptr instruction, or as an intermediate step for |
315 /// lowering a Load instruction. | 323 /// lowering a Load instruction. |
316 class InstAssign : public InstHighLevel { | 324 class InstAssign : public InstHighLevel { |
317 InstAssign() = delete; | 325 InstAssign() = delete; |
318 InstAssign(const InstAssign &) = delete; | 326 InstAssign(const InstAssign &) = delete; |
319 InstAssign &operator=(const InstAssign &) = delete; | 327 InstAssign &operator=(const InstAssign &) = delete; |
320 | 328 |
321 public: | 329 public: |
322 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 330 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
323 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); | 331 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
324 } | 332 } |
325 bool isVarAssign() const override; | 333 bool isVarAssign() const override; |
334 bool isMemoryWrite() const final { return false; } | |
326 void dump(const Cfg *Func) const override; | 335 void dump(const Cfg *Func) const override; |
327 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } | 336 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } |
328 | 337 |
329 private: | 338 private: |
330 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 339 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
331 }; | 340 }; |
332 | 341 |
333 /// Branch instruction. This represents both conditional and unconditional | 342 /// Branch instruction. This represents both conditional and unconditional |
334 /// branches. | 343 /// branches. |
335 class InstBr : public InstHighLevel { | 344 class InstBr : public InstHighLevel { |
(...skipping 20 matching lines...) Expand all Loading... | |
356 } | 365 } |
357 CfgNode *getTargetTrue() const { return TargetTrue; } | 366 CfgNode *getTargetTrue() const { return TargetTrue; } |
358 CfgNode *getTargetFalse() const { return TargetFalse; } | 367 CfgNode *getTargetFalse() const { return TargetFalse; } |
359 CfgNode *getTargetUnconditional() const { | 368 CfgNode *getTargetUnconditional() const { |
360 assert(isUnconditional()); | 369 assert(isUnconditional()); |
361 return getTargetFalse(); | 370 return getTargetFalse(); |
362 } | 371 } |
363 NodeList getTerminatorEdges() const override; | 372 NodeList getTerminatorEdges() const override; |
364 bool isUnconditionalBranch() const override { return isUnconditional(); } | 373 bool isUnconditionalBranch() const override { return isUnconditional(); } |
365 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 374 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
375 bool isMemoryWrite() const final { return false; } | |
366 void dump(const Cfg *Func) const override; | 376 void dump(const Cfg *Func) const override; |
367 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } | 377 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } |
368 | 378 |
369 private: | 379 private: |
370 /// Conditional branch | 380 /// Conditional branch |
371 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); | 381 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); |
372 /// Unconditional branch | 382 /// Unconditional branch |
373 InstBr(Cfg *Func, CfgNode *Target); | 383 InstBr(Cfg *Func, CfgNode *Target); |
374 | 384 |
375 CfgNode *TargetFalse; /// Doubles as unconditional branch target | 385 CfgNode *TargetFalse; /// Doubles as unconditional branch target |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
436 }; | 446 }; |
437 | 447 |
438 static const char *getCastName(OpKind Kind); | 448 static const char *getCastName(OpKind Kind); |
439 | 449 |
440 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, | 450 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
441 Operand *Source) { | 451 Operand *Source) { |
442 return new (Func->allocate<InstCast>()) | 452 return new (Func->allocate<InstCast>()) |
443 InstCast(Func, CastKind, Dest, Source); | 453 InstCast(Func, CastKind, Dest, Source); |
444 } | 454 } |
445 OpKind getCastKind() const { return CastKind; } | 455 OpKind getCastKind() const { return CastKind; } |
456 bool isMemoryWrite() const final { return false; } | |
446 void dump(const Cfg *Func) const override; | 457 void dump(const Cfg *Func) const override; |
447 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } | 458 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } |
448 | 459 |
449 private: | 460 private: |
450 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 461 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
451 | 462 |
452 const OpKind CastKind; | 463 const OpKind CastKind; |
453 }; | 464 }; |
454 | 465 |
455 /// ExtractElement instruction. | 466 /// ExtractElement instruction. |
456 class InstExtractElement : public InstHighLevel { | 467 class InstExtractElement : public InstHighLevel { |
457 InstExtractElement() = delete; | 468 InstExtractElement() = delete; |
458 InstExtractElement(const InstExtractElement &) = delete; | 469 InstExtractElement(const InstExtractElement &) = delete; |
459 InstExtractElement &operator=(const InstExtractElement &) = delete; | 470 InstExtractElement &operator=(const InstExtractElement &) = delete; |
460 | 471 |
461 public: | 472 public: |
462 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 473 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
463 Operand *Source2) { | 474 Operand *Source2) { |
464 return new (Func->allocate<InstExtractElement>()) | 475 return new (Func->allocate<InstExtractElement>()) |
465 InstExtractElement(Func, Dest, Source1, Source2); | 476 InstExtractElement(Func, Dest, Source1, Source2); |
466 } | 477 } |
467 | 478 |
479 bool isMemoryWrite() const final { return false; } | |
468 void dump(const Cfg *Func) const override; | 480 void dump(const Cfg *Func) const override; |
469 static bool classof(const Inst *Instr) { | 481 static bool classof(const Inst *Instr) { |
470 return Instr->getKind() == ExtractElement; | 482 return Instr->getKind() == ExtractElement; |
471 } | 483 } |
472 | 484 |
473 private: | 485 private: |
474 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 486 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
475 Operand *Source2); | 487 Operand *Source2); |
476 }; | 488 }; |
477 | 489 |
(...skipping 11 matching lines...) Expand all Loading... | |
489 #undef X | 501 #undef X |
490 _num | 502 _num |
491 }; | 503 }; |
492 | 504 |
493 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 505 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
494 Operand *Source1, Operand *Source2) { | 506 Operand *Source1, Operand *Source2) { |
495 return new (Func->allocate<InstFcmp>()) | 507 return new (Func->allocate<InstFcmp>()) |
496 InstFcmp(Func, Condition, Dest, Source1, Source2); | 508 InstFcmp(Func, Condition, Dest, Source1, Source2); |
497 } | 509 } |
498 FCond getCondition() const { return Condition; } | 510 FCond getCondition() const { return Condition; } |
511 bool isMemoryWrite() const final { return false; } | |
499 void dump(const Cfg *Func) const override; | 512 void dump(const Cfg *Func) const override; |
500 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } | 513 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } |
501 | 514 |
502 private: | 515 private: |
503 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 516 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
504 Operand *Source2); | 517 Operand *Source2); |
505 | 518 |
506 const FCond Condition; | 519 const FCond Condition; |
507 }; | 520 }; |
508 | 521 |
(...skipping 11 matching lines...) Expand all Loading... | |
520 #undef X | 533 #undef X |
521 _num | 534 _num |
522 }; | 535 }; |
523 | 536 |
524 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 537 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
525 Operand *Source1, Operand *Source2) { | 538 Operand *Source1, Operand *Source2) { |
526 return new (Func->allocate<InstIcmp>()) | 539 return new (Func->allocate<InstIcmp>()) |
527 InstIcmp(Func, Condition, Dest, Source1, Source2); | 540 InstIcmp(Func, Condition, Dest, Source1, Source2); |
528 } | 541 } |
529 ICond getCondition() const { return Condition; } | 542 ICond getCondition() const { return Condition; } |
543 bool isMemoryWrite() const final { return false; } | |
530 void dump(const Cfg *Func) const override; | 544 void dump(const Cfg *Func) const override; |
531 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } | 545 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } |
532 | 546 |
533 private: | 547 private: |
534 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 548 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
535 Operand *Source2); | 549 Operand *Source2); |
536 | 550 |
537 const ICond Condition; | 551 const ICond Condition; |
538 }; | 552 }; |
539 | 553 |
540 /// InsertElement instruction. | 554 /// InsertElement instruction. |
541 class InstInsertElement : public InstHighLevel { | 555 class InstInsertElement : public InstHighLevel { |
542 InstInsertElement() = delete; | 556 InstInsertElement() = delete; |
543 InstInsertElement(const InstInsertElement &) = delete; | 557 InstInsertElement(const InstInsertElement &) = delete; |
544 InstInsertElement &operator=(const InstInsertElement &) = delete; | 558 InstInsertElement &operator=(const InstInsertElement &) = delete; |
545 | 559 |
546 public: | 560 public: |
547 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 561 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
548 Operand *Source2, Operand *Source3) { | 562 Operand *Source2, Operand *Source3) { |
549 return new (Func->allocate<InstInsertElement>()) | 563 return new (Func->allocate<InstInsertElement>()) |
550 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 564 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
551 } | 565 } |
552 | 566 |
567 bool isMemoryWrite() const final { return false; } | |
553 void dump(const Cfg *Func) const override; | 568 void dump(const Cfg *Func) const override; |
554 static bool classof(const Inst *Instr) { | 569 static bool classof(const Inst *Instr) { |
555 return Instr->getKind() == InsertElement; | 570 return Instr->getKind() == InsertElement; |
556 } | 571 } |
557 | 572 |
558 private: | 573 private: |
559 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 574 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
560 Operand *Source2, Operand *Source3); | 575 Operand *Source2, Operand *Source3); |
561 }; | 576 }; |
562 | 577 |
563 /// Call to an intrinsic function. The call target is captured as getSrc(0), and | 578 /// Call to an intrinsic function. The call target is captured as getSrc(0), and |
564 /// arg I is captured as getSrc(I+1). | 579 /// arg I is captured as getSrc(I+1). |
565 class InstIntrinsicCall : public InstCall { | 580 class InstIntrinsicCall : public InstCall { |
566 InstIntrinsicCall() = delete; | 581 InstIntrinsicCall() = delete; |
567 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | 582 InstIntrinsicCall(const InstIntrinsicCall &) = delete; |
568 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | 583 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; |
569 | 584 |
570 public: | 585 public: |
571 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 586 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
572 Operand *CallTarget, | 587 Operand *CallTarget, |
573 const Intrinsics::IntrinsicInfo &Info) { | 588 const Intrinsics::IntrinsicInfo &Info) { |
574 return new (Func->allocate<InstIntrinsicCall>()) | 589 return new (Func->allocate<InstIntrinsicCall>()) |
575 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 590 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
576 } | 591 } |
577 static bool classof(const Inst *Instr) { | 592 static bool classof(const Inst *Instr) { |
578 return Instr->getKind() == IntrinsicCall; | 593 return Instr->getKind() == IntrinsicCall; |
579 } | 594 } |
580 | 595 |
581 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 596 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
597 bool isMemoryWrite() const final { return getIntrinsicInfo().IsMemoryWrite; } | |
582 | 598 |
583 private: | 599 private: |
584 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 600 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
585 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 601 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
586 : InstCall(Func, NumArgs, Dest, CallTarget, false, false, | 602 : InstCall(Func, NumArgs, Dest, CallTarget, false, false, |
587 Info.HasSideEffects, Inst::IntrinsicCall), | 603 Info.HasSideEffects, Inst::IntrinsicCall), |
588 Info(Info) {} | 604 Info(Info) {} |
589 | 605 |
590 const Intrinsics::IntrinsicInfo Info; | 606 const Intrinsics::IntrinsicInfo Info; |
591 }; | 607 }; |
592 | 608 |
593 /// Load instruction. The source address is captured in getSrc(0). | 609 /// Load instruction. The source address is captured in getSrc(0). |
594 class InstLoad : public InstHighLevel { | 610 class InstLoad : public InstHighLevel { |
595 InstLoad() = delete; | 611 InstLoad() = delete; |
596 InstLoad(const InstLoad &) = delete; | 612 InstLoad(const InstLoad &) = delete; |
597 InstLoad &operator=(const InstLoad &) = delete; | 613 InstLoad &operator=(const InstLoad &) = delete; |
598 | 614 |
599 public: | 615 public: |
600 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 616 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
601 uint32_t Align = 1) { | 617 uint32_t Align = 1) { |
602 // TODO(kschimpf) Stop ignoring alignment specification. | 618 // TODO(kschimpf) Stop ignoring alignment specification. |
603 (void)Align; | 619 (void)Align; |
604 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); | 620 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
605 } | 621 } |
606 Operand *getSourceAddress() const { return getSrc(0); } | 622 Operand *getSourceAddress() const { return getSrc(0); } |
623 bool isMemoryWrite() const final { return false; } | |
607 void dump(const Cfg *Func) const override; | 624 void dump(const Cfg *Func) const override; |
608 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } | 625 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } |
609 | 626 |
610 private: | 627 private: |
611 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 628 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
612 }; | 629 }; |
613 | 630 |
614 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi | 631 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi |
615 /// source operand is getSrc(I). | 632 /// source operand is getSrc(I). |
616 class InstPhi : public InstHighLevel { | 633 class InstPhi : public InstHighLevel { |
617 InstPhi() = delete; | 634 InstPhi() = delete; |
618 InstPhi(const InstPhi &) = delete; | 635 InstPhi(const InstPhi &) = delete; |
619 InstPhi &operator=(const InstPhi &) = delete; | 636 InstPhi &operator=(const InstPhi &) = delete; |
620 | 637 |
621 public: | 638 public: |
622 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 639 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
623 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 640 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
624 } | 641 } |
625 void addArgument(Operand *Source, CfgNode *Label); | 642 void addArgument(Operand *Source, CfgNode *Label); |
626 Operand *getOperandForTarget(CfgNode *Target) const; | 643 Operand *getOperandForTarget(CfgNode *Target) const; |
627 void clearOperandForTarget(CfgNode *Target); | 644 void clearOperandForTarget(CfgNode *Target); |
628 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } | 645 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } |
629 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } | 646 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } |
630 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 647 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
631 Liveness *Liveness); | 648 Liveness *Liveness); |
632 Inst *lower(Cfg *Func); | 649 Inst *lower(Cfg *Func); |
650 bool isMemoryWrite() const final { return false; } | |
633 void dump(const Cfg *Func) const override; | 651 void dump(const Cfg *Func) const override; |
634 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } | 652 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } |
635 | 653 |
636 private: | 654 private: |
637 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 655 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
638 void destroy(Cfg *Func) override { | 656 void destroy(Cfg *Func) override { |
639 Func->deallocateArrayOf<CfgNode *>(Labels); | 657 Func->deallocateArrayOf<CfgNode *>(Labels); |
640 Inst::destroy(Func); | 658 Inst::destroy(Func); |
641 } | 659 } |
642 | 660 |
(...skipping 14 matching lines...) Expand all Loading... | |
657 public: | 675 public: |
658 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { | 676 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { |
659 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); | 677 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); |
660 } | 678 } |
661 bool hasRetValue() const { return getSrcSize(); } | 679 bool hasRetValue() const { return getSrcSize(); } |
662 Operand *getRetValue() const { | 680 Operand *getRetValue() const { |
663 assert(hasRetValue()); | 681 assert(hasRetValue()); |
664 return getSrc(0); | 682 return getSrc(0); |
665 } | 683 } |
666 NodeList getTerminatorEdges() const override { return NodeList(); } | 684 NodeList getTerminatorEdges() const override { return NodeList(); } |
685 bool isMemoryWrite() const final { return false; } | |
667 void dump(const Cfg *Func) const override; | 686 void dump(const Cfg *Func) const override; |
668 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } | 687 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } |
669 | 688 |
670 private: | 689 private: |
671 InstRet(Cfg *Func, Operand *RetValue); | 690 InstRet(Cfg *Func, Operand *RetValue); |
672 }; | 691 }; |
673 | 692 |
674 /// Select instruction. The condition, true, and false operands are captured. | 693 /// Select instruction. The condition, true, and false operands are captured. |
675 class InstSelect : public InstHighLevel { | 694 class InstSelect : public InstHighLevel { |
676 InstSelect() = delete; | 695 InstSelect() = delete; |
677 InstSelect(const InstSelect &) = delete; | 696 InstSelect(const InstSelect &) = delete; |
678 InstSelect &operator=(const InstSelect &) = delete; | 697 InstSelect &operator=(const InstSelect &) = delete; |
679 | 698 |
680 public: | 699 public: |
681 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 700 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
682 Operand *SourceTrue, Operand *SourceFalse) { | 701 Operand *SourceTrue, Operand *SourceFalse) { |
683 return new (Func->allocate<InstSelect>()) | 702 return new (Func->allocate<InstSelect>()) |
684 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 703 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
685 } | 704 } |
686 Operand *getCondition() const { return getSrc(0); } | 705 Operand *getCondition() const { return getSrc(0); } |
687 Operand *getTrueOperand() const { return getSrc(1); } | 706 Operand *getTrueOperand() const { return getSrc(1); } |
688 Operand *getFalseOperand() const { return getSrc(2); } | 707 Operand *getFalseOperand() const { return getSrc(2); } |
708 bool isMemoryWrite() const final { return false; } | |
689 void dump(const Cfg *Func) const override; | 709 void dump(const Cfg *Func) const override; |
690 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } | 710 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } |
691 | 711 |
692 private: | 712 private: |
693 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 713 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
694 Operand *Source2); | 714 Operand *Source2); |
695 }; | 715 }; |
696 | 716 |
697 /// Store instruction. The address operand is captured, along with the data | 717 /// Store instruction. The address operand is captured, along with the data |
698 /// operand to be stored into the address. | 718 /// operand to be stored into the address. |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
738 assert(I < NumCases); | 758 assert(I < NumCases); |
739 return Values[I]; | 759 return Values[I]; |
740 } | 760 } |
741 CfgNode *getLabel(SizeT I) const { | 761 CfgNode *getLabel(SizeT I) const { |
742 assert(I < NumCases); | 762 assert(I < NumCases); |
743 return Labels[I]; | 763 return Labels[I]; |
744 } | 764 } |
745 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); | 765 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); |
746 NodeList getTerminatorEdges() const override; | 766 NodeList getTerminatorEdges() const override; |
747 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 767 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
768 bool isMemoryWrite() const final { return false; } | |
748 void dump(const Cfg *Func) const override; | 769 void dump(const Cfg *Func) const override; |
749 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } | 770 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } |
750 | 771 |
751 private: | 772 private: |
752 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); | 773 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); |
753 void destroy(Cfg *Func) override { | 774 void destroy(Cfg *Func) override { |
754 Func->deallocateArrayOf<uint64_t>(Values); | 775 Func->deallocateArrayOf<uint64_t>(Values); |
755 Func->deallocateArrayOf<CfgNode *>(Labels); | 776 Func->deallocateArrayOf<CfgNode *>(Labels); |
756 Inst::destroy(Func); | 777 Inst::destroy(Func); |
757 } | 778 } |
758 | 779 |
759 CfgNode *LabelDefault; | 780 CfgNode *LabelDefault; |
760 SizeT NumCases; /// not including the default case | 781 SizeT NumCases; /// not including the default case |
761 uint64_t *Values; /// size is NumCases | 782 uint64_t *Values; /// size is NumCases |
762 CfgNode **Labels; /// size is NumCases | 783 CfgNode **Labels; /// size is NumCases |
763 }; | 784 }; |
764 | 785 |
765 /// Unreachable instruction. This is a terminator instruction with no operands. | 786 /// Unreachable instruction. This is a terminator instruction with no operands. |
766 class InstUnreachable : public InstHighLevel { | 787 class InstUnreachable : public InstHighLevel { |
767 InstUnreachable() = delete; | 788 InstUnreachable() = delete; |
768 InstUnreachable(const InstUnreachable &) = delete; | 789 InstUnreachable(const InstUnreachable &) = delete; |
769 InstUnreachable &operator=(const InstUnreachable &) = delete; | 790 InstUnreachable &operator=(const InstUnreachable &) = delete; |
770 | 791 |
771 public: | 792 public: |
772 static InstUnreachable *create(Cfg *Func) { | 793 static InstUnreachable *create(Cfg *Func) { |
773 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); | 794 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
774 } | 795 } |
775 NodeList getTerminatorEdges() const override { return NodeList(); } | 796 NodeList getTerminatorEdges() const override { return NodeList(); } |
797 bool isMemoryWrite() const final { return false; } | |
776 void dump(const Cfg *Func) const override; | 798 void dump(const Cfg *Func) const override; |
777 static bool classof(const Inst *Instr) { | 799 static bool classof(const Inst *Instr) { |
778 return Instr->getKind() == Unreachable; | 800 return Instr->getKind() == Unreachable; |
779 } | 801 } |
780 | 802 |
781 private: | 803 private: |
782 explicit InstUnreachable(Cfg *Func); | 804 explicit InstUnreachable(Cfg *Func); |
783 }; | 805 }; |
784 | 806 |
785 /// BundleLock instruction. There are no operands. Contains an option | 807 /// BundleLock instruction. There are no operands. Contains an option |
786 /// indicating whether align_to_end is specified. | 808 /// indicating whether align_to_end is specified. |
787 class InstBundleLock : public InstHighLevel { | 809 class InstBundleLock : public InstHighLevel { |
788 InstBundleLock() = delete; | 810 InstBundleLock() = delete; |
789 InstBundleLock(const InstBundleLock &) = delete; | 811 InstBundleLock(const InstBundleLock &) = delete; |
790 InstBundleLock &operator=(const InstBundleLock &) = delete; | 812 InstBundleLock &operator=(const InstBundleLock &) = delete; |
791 | 813 |
792 public: | 814 public: |
793 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; | 815 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; |
794 static InstBundleLock *create(Cfg *Func, Option BundleOption) { | 816 static InstBundleLock *create(Cfg *Func, Option BundleOption) { |
795 return new (Func->allocate<InstBundleLock>()) | 817 return new (Func->allocate<InstBundleLock>()) |
796 InstBundleLock(Func, BundleOption); | 818 InstBundleLock(Func, BundleOption); |
797 } | 819 } |
798 void emit(const Cfg *Func) const override; | 820 void emit(const Cfg *Func) const override; |
799 void emitIAS(const Cfg * /* Func */) const override {} | 821 void emitIAS(const Cfg * /* Func */) const override {} |
822 bool isMemoryWrite() const final { return false; } | |
800 void dump(const Cfg *Func) const override; | 823 void dump(const Cfg *Func) const override; |
801 Option getOption() const { return BundleOption; } | 824 Option getOption() const { return BundleOption; } |
802 static bool classof(const Inst *Instr) { | 825 static bool classof(const Inst *Instr) { |
803 return Instr->getKind() == BundleLock; | 826 return Instr->getKind() == BundleLock; |
804 } | 827 } |
805 | 828 |
806 private: | 829 private: |
807 Option BundleOption; | 830 Option BundleOption; |
808 InstBundleLock(Cfg *Func, Option BundleOption); | 831 InstBundleLock(Cfg *Func, Option BundleOption); |
809 }; | 832 }; |
810 | 833 |
811 /// BundleUnlock instruction. There are no operands. | 834 /// BundleUnlock instruction. There are no operands. |
812 class InstBundleUnlock : public InstHighLevel { | 835 class InstBundleUnlock : public InstHighLevel { |
813 InstBundleUnlock() = delete; | 836 InstBundleUnlock() = delete; |
814 InstBundleUnlock(const InstBundleUnlock &) = delete; | 837 InstBundleUnlock(const InstBundleUnlock &) = delete; |
815 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; | 838 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; |
816 | 839 |
817 public: | 840 public: |
818 static InstBundleUnlock *create(Cfg *Func) { | 841 static InstBundleUnlock *create(Cfg *Func) { |
819 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); | 842 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); |
820 } | 843 } |
821 void emit(const Cfg *Func) const override; | 844 void emit(const Cfg *Func) const override; |
822 void emitIAS(const Cfg * /* Func */) const override {} | 845 void emitIAS(const Cfg * /* Func */) const override {} |
846 bool isMemoryWrite() const final { return false; } | |
823 void dump(const Cfg *Func) const override; | 847 void dump(const Cfg *Func) const override; |
824 static bool classof(const Inst *Instr) { | 848 static bool classof(const Inst *Instr) { |
825 return Instr->getKind() == BundleUnlock; | 849 return Instr->getKind() == BundleUnlock; |
826 } | 850 } |
827 | 851 |
828 private: | 852 private: |
829 explicit InstBundleUnlock(Cfg *Func); | 853 explicit InstBundleUnlock(Cfg *Func); |
830 }; | 854 }; |
831 | 855 |
832 /// FakeDef instruction. This creates a fake definition of a variable, which is | 856 /// FakeDef instruction. This creates a fake definition of a variable, which is |
(...skipping 12 matching lines...) Expand all Loading... | |
845 InstFakeDef(const InstFakeDef &) = delete; | 869 InstFakeDef(const InstFakeDef &) = delete; |
846 InstFakeDef &operator=(const InstFakeDef &) = delete; | 870 InstFakeDef &operator=(const InstFakeDef &) = delete; |
847 | 871 |
848 public: | 872 public: |
849 static InstFakeDef *create(Cfg *Func, Variable *Dest, | 873 static InstFakeDef *create(Cfg *Func, Variable *Dest, |
850 Variable *Src = nullptr) { | 874 Variable *Src = nullptr) { |
851 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 875 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
852 } | 876 } |
853 void emit(const Cfg *Func) const override; | 877 void emit(const Cfg *Func) const override; |
854 void emitIAS(const Cfg * /* Func */) const override {} | 878 void emitIAS(const Cfg * /* Func */) const override {} |
879 bool isMemoryWrite() const final { return false; } | |
855 void dump(const Cfg *Func) const override; | 880 void dump(const Cfg *Func) const override; |
856 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } | 881 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } |
857 | 882 |
858 private: | 883 private: |
859 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 884 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
860 }; | 885 }; |
861 | 886 |
862 /// FakeUse instruction. This creates a fake use of a variable, to keep the | 887 /// FakeUse instruction. This creates a fake use of a variable, to keep the |
863 /// instruction that produces that variable from being dead-code eliminated. | 888 /// instruction that produces that variable from being dead-code eliminated. |
864 /// This is useful in a variety of lowering situations. The FakeUse instruction | 889 /// This is useful in a variety of lowering situations. The FakeUse instruction |
865 /// has no dest, so it can itself never be dead-code eliminated. A weight can | 890 /// has no dest, so it can itself never be dead-code eliminated. A weight can |
866 /// be provided to provide extra bias to the register allocator - for simplicity | 891 /// be provided to provide extra bias to the register allocator - for simplicity |
867 /// of implementation, weight=N is handled by holding N copies of the variable | 892 /// of implementation, weight=N is handled by holding N copies of the variable |
868 /// as source operands. | 893 /// as source operands. |
869 class InstFakeUse : public InstHighLevel { | 894 class InstFakeUse : public InstHighLevel { |
870 InstFakeUse() = delete; | 895 InstFakeUse() = delete; |
871 InstFakeUse(const InstFakeUse &) = delete; | 896 InstFakeUse(const InstFakeUse &) = delete; |
872 InstFakeUse &operator=(const InstFakeUse &) = delete; | 897 InstFakeUse &operator=(const InstFakeUse &) = delete; |
873 | 898 |
874 public: | 899 public: |
875 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { | 900 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { |
876 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); | 901 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); |
877 } | 902 } |
878 void emit(const Cfg *Func) const override; | 903 void emit(const Cfg *Func) const override; |
879 void emitIAS(const Cfg * /* Func */) const override {} | 904 void emitIAS(const Cfg * /* Func */) const override {} |
905 bool isMemoryWrite() const final { return false; } | |
880 void dump(const Cfg *Func) const override; | 906 void dump(const Cfg *Func) const override; |
881 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } | 907 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } |
882 | 908 |
883 private: | 909 private: |
884 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); | 910 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); |
885 }; | 911 }; |
886 | 912 |
887 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial | 913 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial |
888 /// live range at this instruction for each (implicit) variable. The primary use | 914 /// live range at this instruction for each (implicit) variable. The primary use |
889 /// is to indicate that scratch registers are killed after a call, so that the | 915 /// is to indicate that scratch registers are killed after a call, so that the |
890 /// register allocator won't assign a scratch register to a variable whose live | 916 /// register allocator won't assign a scratch register to a variable whose live |
891 /// range spans a call. | 917 /// range spans a call. |
892 /// | 918 /// |
893 /// The FakeKill instruction also holds a pointer to the instruction that kills | 919 /// The FakeKill instruction also holds a pointer to the instruction that kills |
894 /// the set of variables, so that if that linked instruction gets dead-code | 920 /// the set of variables, so that if that linked instruction gets dead-code |
895 /// eliminated, the FakeKill instruction will as well. | 921 /// eliminated, the FakeKill instruction will as well. |
896 class InstFakeKill : public InstHighLevel { | 922 class InstFakeKill : public InstHighLevel { |
897 InstFakeKill() = delete; | 923 InstFakeKill() = delete; |
898 InstFakeKill(const InstFakeKill &) = delete; | 924 InstFakeKill(const InstFakeKill &) = delete; |
899 InstFakeKill &operator=(const InstFakeKill &) = delete; | 925 InstFakeKill &operator=(const InstFakeKill &) = delete; |
900 | 926 |
901 public: | 927 public: |
902 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { | 928 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { |
903 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); | 929 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); |
904 } | 930 } |
905 const Inst *getLinked() const { return Linked; } | 931 const Inst *getLinked() const { return Linked; } |
906 void emit(const Cfg *Func) const override; | 932 void emit(const Cfg *Func) const override; |
907 void emitIAS(const Cfg * /* Func */) const override {} | 933 void emitIAS(const Cfg * /* Func */) const override {} |
934 bool isMemoryWrite() const final { return false; } | |
Eric Holk
2016/04/21 22:09:43
Since all the other instructions have isMemoryWrit
Jim Stichnoth
2016/04/21 22:50:28
Done.
| |
908 void dump(const Cfg *Func) const override; | 935 void dump(const Cfg *Func) const override; |
909 static bool classof(const Inst *Instr) { | 936 static bool classof(const Inst *Instr) { |
910 return Instr->getKind() == FakeKill; | 937 return Instr->getKind() == FakeKill; |
911 } | 938 } |
912 | 939 |
913 private: | 940 private: |
914 InstFakeKill(Cfg *Func, const Inst *Linked); | 941 InstFakeKill(Cfg *Func, const Inst *Linked); |
915 | 942 |
916 /// This instruction is ignored if Linked->isDeleted() is true. | 943 /// This instruction is ignored if Linked->isDeleted() is true. |
917 const Inst *Linked; | 944 const Inst *Linked; |
(...skipping 16 matching lines...) Expand all Loading... | |
934 assert(TargetIndex < NumTargets); | 961 assert(TargetIndex < NumTargets); |
935 Targets[TargetIndex] = Target; | 962 Targets[TargetIndex] = Target; |
936 } | 963 } |
937 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; | 964 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
938 SizeT getId() const { return Id; } | 965 SizeT getId() const { return Id; } |
939 SizeT getNumTargets() const { return NumTargets; } | 966 SizeT getNumTargets() const { return NumTargets; } |
940 CfgNode *getTarget(SizeT I) const { | 967 CfgNode *getTarget(SizeT I) const { |
941 assert(I < NumTargets); | 968 assert(I < NumTargets); |
942 return Targets[I]; | 969 return Targets[I]; |
943 } | 970 } |
971 bool isMemoryWrite() const final { return false; } | |
944 void dump(const Cfg *Func) const override; | 972 void dump(const Cfg *Func) const override; |
945 static bool classof(const Inst *Instr) { | 973 static bool classof(const Inst *Instr) { |
946 return Instr->getKind() == JumpTable; | 974 return Instr->getKind() == JumpTable; |
947 } | 975 } |
948 // Creates a JumpTableData struct (used for ELF emission) that represents this | 976 // Creates a JumpTableData struct (used for ELF emission) that represents this |
949 // InstJumpTable. | 977 // InstJumpTable. |
950 JumpTableData toJumpTableData(Assembler *Asm) const; | 978 JumpTableData toJumpTableData(Assembler *Asm) const; |
951 | 979 |
952 // InstJumpTable is just a placeholder for the switch targets, and it does not | 980 // InstJumpTable is just a placeholder for the switch targets, and it does not |
953 // need to emit any code, so we redefine emit and emitIAS to do nothing. | 981 // need to emit any code, so we redefine emit and emitIAS to do nothing. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1039 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 1067 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
1040 void deleteNode(Ice::Inst *) {} | 1068 void deleteNode(Ice::Inst *) {} |
1041 | 1069 |
1042 private: | 1070 private: |
1043 mutable ilist_half_node<Ice::Inst> Sentinel; | 1071 mutable ilist_half_node<Ice::Inst> Sentinel; |
1044 }; | 1072 }; |
1045 | 1073 |
1046 } // end of namespace llvm | 1074 } // end of namespace llvm |
1047 | 1075 |
1048 #endif // SUBZERO_SRC_ICEINST_H | 1076 #endif // SUBZERO_SRC_ICEINST_H |
OLD | NEW |