Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: src/IceInst.h

Issue 1904233002: Subzero: Fix over-aggressive bool folding. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/IceIntrinsics.h » ('j') | src/IceIntrinsics.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/IceIntrinsics.h » ('j') | src/IceIntrinsics.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698