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

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: Hack for pure virtual method 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/IceInst.cpp » ('j') | no next file with comments »
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. It should really be pure virtual, but we can't
141 /// because of g++ and llvm::ilist<>, so we implement it as
142 /// report_fatal_error().
143 virtual bool isMemoryWrite() const;
144
138 void livenessLightweight(Cfg *Func, LivenessBV &Live); 145 void livenessLightweight(Cfg *Func, LivenessBV &Live);
139 /// Calculates liveness for this instruction. Returns true if this instruction 146 /// Calculates liveness for this instruction. Returns true if this instruction
140 /// is (tentatively) still live and should be retained, and false if this 147 /// is (tentatively) still live and should be retained, and false if this
141 /// instruction is (tentatively) dead and should be deleted. The decision is 148 /// instruction is (tentatively) dead and should be deleted. The decision is
142 /// tentative until the liveness dataflow algorithm has converged, and then a 149 /// tentative until the liveness dataflow algorithm has converged, and then a
143 /// separate pass permanently deletes dead instructions. 150 /// separate pass permanently deletes dead instructions.
144 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness, 151 bool liveness(InstNumberT InstNumber, LivenessBV &Live, Liveness *Liveness,
145 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd); 152 LiveBeginEndMap *LiveBegin, LiveBeginEndMap *LiveEnd);
146 153
147 /// Get the number of native instructions that this instruction ultimately 154 /// Get the number of native instructions that this instruction ultimately
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
252 public: 259 public:
253 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount, 260 static InstAlloca *create(Cfg *Func, Variable *Dest, Operand *ByteCount,
254 uint32_t AlignInBytes) { 261 uint32_t AlignInBytes) {
255 return new (Func->allocate<InstAlloca>()) 262 return new (Func->allocate<InstAlloca>())
256 InstAlloca(Func, Dest, ByteCount, AlignInBytes); 263 InstAlloca(Func, Dest, ByteCount, AlignInBytes);
257 } 264 }
258 uint32_t getAlignInBytes() const { return AlignInBytes; } 265 uint32_t getAlignInBytes() const { return AlignInBytes; }
259 Operand *getSizeInBytes() const { return getSrc(0); } 266 Operand *getSizeInBytes() const { return getSrc(0); }
260 bool getKnownFrameOffset() const { return KnownFrameOffset; } 267 bool getKnownFrameOffset() const { return KnownFrameOffset; }
261 void setKnownFrameOffset() { KnownFrameOffset = true; } 268 void setKnownFrameOffset() { KnownFrameOffset = true; }
269 bool isMemoryWrite() const override { return false; }
262 void dump(const Cfg *Func) const override; 270 void dump(const Cfg *Func) const override;
263 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } 271 static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; }
264 272
265 private: 273 private:
266 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount, 274 InstAlloca(Cfg *Func, Variable *Dest, Operand *ByteCount,
267 uint32_t AlignInBytes); 275 uint32_t AlignInBytes);
268 276
269 const uint32_t AlignInBytes; 277 const uint32_t AlignInBytes;
270 bool KnownFrameOffset = false; 278 bool KnownFrameOffset = false;
271 }; 279 };
(...skipping 17 matching lines...) Expand all
289 Operand *Source1, Operand *Source2) { 297 Operand *Source1, Operand *Source2) {
290 return new (Func->allocate<InstArithmetic>()) 298 return new (Func->allocate<InstArithmetic>())
291 InstArithmetic(Func, Op, Dest, Source1, Source2); 299 InstArithmetic(Func, Op, Dest, Source1, Source2);
292 } 300 }
293 OpKind getOp() const { return Op; } 301 OpKind getOp() const { return Op; }
294 302
295 virtual const char *getInstName() const override; 303 virtual const char *getInstName() const override;
296 304
297 static const char *getOpName(OpKind Op); 305 static const char *getOpName(OpKind Op);
298 bool isCommutative() const; 306 bool isCommutative() const;
307 bool isMemoryWrite() const override { return false; }
299 void dump(const Cfg *Func) const override; 308 void dump(const Cfg *Func) const override;
300 static bool classof(const Inst *Instr) { 309 static bool classof(const Inst *Instr) {
301 return Instr->getKind() == Arithmetic; 310 return Instr->getKind() == Arithmetic;
302 } 311 }
303 312
304 private: 313 private:
305 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, 314 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1,
306 Operand *Source2); 315 Operand *Source2);
307 316
308 const OpKind Op; 317 const OpKind Op;
309 }; 318 };
310 319
311 /// Assignment instruction. The source operand is captured in getSrc(0). This is 320 /// 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 321 /// 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, 322 /// lowering. E.g., if Phi instruction lowering happens before target lowering,
314 /// or for representing an Inttoptr instruction, or as an intermediate step for 323 /// or for representing an Inttoptr instruction, or as an intermediate step for
315 /// lowering a Load instruction. 324 /// lowering a Load instruction.
316 class InstAssign : public InstHighLevel { 325 class InstAssign : public InstHighLevel {
317 InstAssign() = delete; 326 InstAssign() = delete;
318 InstAssign(const InstAssign &) = delete; 327 InstAssign(const InstAssign &) = delete;
319 InstAssign &operator=(const InstAssign &) = delete; 328 InstAssign &operator=(const InstAssign &) = delete;
320 329
321 public: 330 public:
322 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { 331 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) {
323 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); 332 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source);
324 } 333 }
325 bool isVarAssign() const override; 334 bool isVarAssign() const override;
335 bool isMemoryWrite() const override { return false; }
326 void dump(const Cfg *Func) const override; 336 void dump(const Cfg *Func) const override;
327 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } 337 static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; }
328 338
329 private: 339 private:
330 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); 340 InstAssign(Cfg *Func, Variable *Dest, Operand *Source);
331 }; 341 };
332 342
333 /// Branch instruction. This represents both conditional and unconditional 343 /// Branch instruction. This represents both conditional and unconditional
334 /// branches. 344 /// branches.
335 class InstBr : public InstHighLevel { 345 class InstBr : public InstHighLevel {
(...skipping 20 matching lines...) Expand all
356 } 366 }
357 CfgNode *getTargetTrue() const { return TargetTrue; } 367 CfgNode *getTargetTrue() const { return TargetTrue; }
358 CfgNode *getTargetFalse() const { return TargetFalse; } 368 CfgNode *getTargetFalse() const { return TargetFalse; }
359 CfgNode *getTargetUnconditional() const { 369 CfgNode *getTargetUnconditional() const {
360 assert(isUnconditional()); 370 assert(isUnconditional());
361 return getTargetFalse(); 371 return getTargetFalse();
362 } 372 }
363 NodeList getTerminatorEdges() const override; 373 NodeList getTerminatorEdges() const override;
364 bool isUnconditionalBranch() const override { return isUnconditional(); } 374 bool isUnconditionalBranch() const override { return isUnconditional(); }
365 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 375 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
376 bool isMemoryWrite() const override { return false; }
366 void dump(const Cfg *Func) const override; 377 void dump(const Cfg *Func) const override;
367 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } 378 static bool classof(const Inst *Instr) { return Instr->getKind() == Br; }
368 379
369 private: 380 private:
370 /// Conditional branch 381 /// Conditional branch
371 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); 382 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse);
372 /// Unconditional branch 383 /// Unconditional branch
373 InstBr(Cfg *Func, CfgNode *Target); 384 InstBr(Cfg *Func, CfgNode *Target);
374 385
375 CfgNode *TargetFalse; /// Doubles as unconditional branch target 386 CfgNode *TargetFalse; /// Doubles as unconditional branch target
(...skipping 19 matching lines...) Expand all
395 return new (Func->allocate<InstCall>()) 406 return new (Func->allocate<InstCall>())
396 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall, 407 InstCall(Func, NumArgs, Dest, CallTarget, HasTailCall,
397 IsTargetHelperCall, HasSideEffects, Kind); 408 IsTargetHelperCall, HasSideEffects, Kind);
398 } 409 }
399 void addArg(Operand *Arg) { addSource(Arg); } 410 void addArg(Operand *Arg) { addSource(Arg); }
400 Operand *getCallTarget() const { return getSrc(0); } 411 Operand *getCallTarget() const { return getSrc(0); }
401 Operand *getArg(SizeT I) const { return getSrc(I + 1); } 412 Operand *getArg(SizeT I) const { return getSrc(I + 1); }
402 SizeT getNumArgs() const { return getSrcSize() - 1; } 413 SizeT getNumArgs() const { return getSrcSize() - 1; }
403 bool isTailcall() const { return HasTailCall; } 414 bool isTailcall() const { return HasTailCall; }
404 bool isTargetHelperCall() const { return IsTargetHelperCall; } 415 bool isTargetHelperCall() const { return IsTargetHelperCall; }
416 bool isMemoryWrite() const override { return true; }
405 void dump(const Cfg *Func) const override; 417 void dump(const Cfg *Func) const override;
406 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } 418 static bool classof(const Inst *Instr) { return Instr->getKind() == Call; }
407 Type getReturnType() const; 419 Type getReturnType() const;
408 420
409 protected: 421 protected:
410 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, 422 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget,
411 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff, 423 bool HasTailCall, bool IsTargetHelperCall, bool HasSideEff,
412 InstKind Kind) 424 InstKind Kind)
413 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall), 425 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall),
414 IsTargetHelperCall(IsTargetHelperCall) { 426 IsTargetHelperCall(IsTargetHelperCall) {
(...skipping 21 matching lines...) Expand all
436 }; 448 };
437 449
438 static const char *getCastName(OpKind Kind); 450 static const char *getCastName(OpKind Kind);
439 451
440 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, 452 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest,
441 Operand *Source) { 453 Operand *Source) {
442 return new (Func->allocate<InstCast>()) 454 return new (Func->allocate<InstCast>())
443 InstCast(Func, CastKind, Dest, Source); 455 InstCast(Func, CastKind, Dest, Source);
444 } 456 }
445 OpKind getCastKind() const { return CastKind; } 457 OpKind getCastKind() const { return CastKind; }
458 bool isMemoryWrite() const override { return false; }
446 void dump(const Cfg *Func) const override; 459 void dump(const Cfg *Func) const override;
447 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } 460 static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; }
448 461
449 private: 462 private:
450 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); 463 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source);
451 464
452 const OpKind CastKind; 465 const OpKind CastKind;
453 }; 466 };
454 467
455 /// ExtractElement instruction. 468 /// ExtractElement instruction.
456 class InstExtractElement : public InstHighLevel { 469 class InstExtractElement : public InstHighLevel {
457 InstExtractElement() = delete; 470 InstExtractElement() = delete;
458 InstExtractElement(const InstExtractElement &) = delete; 471 InstExtractElement(const InstExtractElement &) = delete;
459 InstExtractElement &operator=(const InstExtractElement &) = delete; 472 InstExtractElement &operator=(const InstExtractElement &) = delete;
460 473
461 public: 474 public:
462 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 475 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
463 Operand *Source2) { 476 Operand *Source2) {
464 return new (Func->allocate<InstExtractElement>()) 477 return new (Func->allocate<InstExtractElement>())
465 InstExtractElement(Func, Dest, Source1, Source2); 478 InstExtractElement(Func, Dest, Source1, Source2);
466 } 479 }
467 480
481 bool isMemoryWrite() const override { return false; }
468 void dump(const Cfg *Func) const override; 482 void dump(const Cfg *Func) const override;
469 static bool classof(const Inst *Instr) { 483 static bool classof(const Inst *Instr) {
470 return Instr->getKind() == ExtractElement; 484 return Instr->getKind() == ExtractElement;
471 } 485 }
472 486
473 private: 487 private:
474 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, 488 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1,
475 Operand *Source2); 489 Operand *Source2);
476 }; 490 };
477 491
(...skipping 11 matching lines...) Expand all
489 #undef X 503 #undef X
490 _num 504 _num
491 }; 505 };
492 506
493 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, 507 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest,
494 Operand *Source1, Operand *Source2) { 508 Operand *Source1, Operand *Source2) {
495 return new (Func->allocate<InstFcmp>()) 509 return new (Func->allocate<InstFcmp>())
496 InstFcmp(Func, Condition, Dest, Source1, Source2); 510 InstFcmp(Func, Condition, Dest, Source1, Source2);
497 } 511 }
498 FCond getCondition() const { return Condition; } 512 FCond getCondition() const { return Condition; }
513 bool isMemoryWrite() const override { return false; }
499 void dump(const Cfg *Func) const override; 514 void dump(const Cfg *Func) const override;
500 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } 515 static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; }
501 516
502 private: 517 private:
503 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, 518 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1,
504 Operand *Source2); 519 Operand *Source2);
505 520
506 const FCond Condition; 521 const FCond Condition;
507 }; 522 };
508 523
(...skipping 11 matching lines...) Expand all
520 #undef X 535 #undef X
521 _num 536 _num
522 }; 537 };
523 538
524 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, 539 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest,
525 Operand *Source1, Operand *Source2) { 540 Operand *Source1, Operand *Source2) {
526 return new (Func->allocate<InstIcmp>()) 541 return new (Func->allocate<InstIcmp>())
527 InstIcmp(Func, Condition, Dest, Source1, Source2); 542 InstIcmp(Func, Condition, Dest, Source1, Source2);
528 } 543 }
529 ICond getCondition() const { return Condition; } 544 ICond getCondition() const { return Condition; }
545 bool isMemoryWrite() const override { return false; }
530 void dump(const Cfg *Func) const override; 546 void dump(const Cfg *Func) const override;
531 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } 547 static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; }
532 548
533 private: 549 private:
534 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, 550 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1,
535 Operand *Source2); 551 Operand *Source2);
536 552
537 const ICond Condition; 553 const ICond Condition;
538 }; 554 };
539 555
540 /// InsertElement instruction. 556 /// InsertElement instruction.
541 class InstInsertElement : public InstHighLevel { 557 class InstInsertElement : public InstHighLevel {
542 InstInsertElement() = delete; 558 InstInsertElement() = delete;
543 InstInsertElement(const InstInsertElement &) = delete; 559 InstInsertElement(const InstInsertElement &) = delete;
544 InstInsertElement &operator=(const InstInsertElement &) = delete; 560 InstInsertElement &operator=(const InstInsertElement &) = delete;
545 561
546 public: 562 public:
547 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, 563 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1,
548 Operand *Source2, Operand *Source3) { 564 Operand *Source2, Operand *Source3) {
549 return new (Func->allocate<InstInsertElement>()) 565 return new (Func->allocate<InstInsertElement>())
550 InstInsertElement(Func, Dest, Source1, Source2, Source3); 566 InstInsertElement(Func, Dest, Source1, Source2, Source3);
551 } 567 }
552 568
569 bool isMemoryWrite() const override { return false; }
553 void dump(const Cfg *Func) const override; 570 void dump(const Cfg *Func) const override;
554 static bool classof(const Inst *Instr) { 571 static bool classof(const Inst *Instr) {
555 return Instr->getKind() == InsertElement; 572 return Instr->getKind() == InsertElement;
556 } 573 }
557 574
558 private: 575 private:
559 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, 576 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1,
560 Operand *Source2, Operand *Source3); 577 Operand *Source2, Operand *Source3);
561 }; 578 };
562 579
563 /// Call to an intrinsic function. The call target is captured as getSrc(0), and 580 /// Call to an intrinsic function. The call target is captured as getSrc(0), and
564 /// arg I is captured as getSrc(I+1). 581 /// arg I is captured as getSrc(I+1).
565 class InstIntrinsicCall : public InstCall { 582 class InstIntrinsicCall : public InstCall {
566 InstIntrinsicCall() = delete; 583 InstIntrinsicCall() = delete;
567 InstIntrinsicCall(const InstIntrinsicCall &) = delete; 584 InstIntrinsicCall(const InstIntrinsicCall &) = delete;
568 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; 585 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete;
569 586
570 public: 587 public:
571 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, 588 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest,
572 Operand *CallTarget, 589 Operand *CallTarget,
573 const Intrinsics::IntrinsicInfo &Info) { 590 const Intrinsics::IntrinsicInfo &Info) {
574 return new (Func->allocate<InstIntrinsicCall>()) 591 return new (Func->allocate<InstIntrinsicCall>())
575 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); 592 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info);
576 } 593 }
577 static bool classof(const Inst *Instr) { 594 static bool classof(const Inst *Instr) {
578 return Instr->getKind() == IntrinsicCall; 595 return Instr->getKind() == IntrinsicCall;
579 } 596 }
580 597
581 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } 598 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; }
599 bool isMemoryWrite() const override {
600 return getIntrinsicInfo().IsMemoryWrite;
601 }
582 602
583 private: 603 private:
584 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, 604 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest,
585 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) 605 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info)
586 : InstCall(Func, NumArgs, Dest, CallTarget, false, false, 606 : InstCall(Func, NumArgs, Dest, CallTarget, false, false,
587 Info.HasSideEffects, Inst::IntrinsicCall), 607 Info.HasSideEffects, Inst::IntrinsicCall),
588 Info(Info) {} 608 Info(Info) {}
589 609
590 const Intrinsics::IntrinsicInfo Info; 610 const Intrinsics::IntrinsicInfo Info;
591 }; 611 };
592 612
593 /// Load instruction. The source address is captured in getSrc(0). 613 /// Load instruction. The source address is captured in getSrc(0).
594 class InstLoad : public InstHighLevel { 614 class InstLoad : public InstHighLevel {
595 InstLoad() = delete; 615 InstLoad() = delete;
596 InstLoad(const InstLoad &) = delete; 616 InstLoad(const InstLoad &) = delete;
597 InstLoad &operator=(const InstLoad &) = delete; 617 InstLoad &operator=(const InstLoad &) = delete;
598 618
599 public: 619 public:
600 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, 620 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr,
601 uint32_t Align = 1) { 621 uint32_t Align = 1) {
602 // TODO(kschimpf) Stop ignoring alignment specification. 622 // TODO(kschimpf) Stop ignoring alignment specification.
603 (void)Align; 623 (void)Align;
604 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); 624 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr);
605 } 625 }
606 Operand *getSourceAddress() const { return getSrc(0); } 626 Operand *getSourceAddress() const { return getSrc(0); }
627 bool isMemoryWrite() const override { return false; }
607 void dump(const Cfg *Func) const override; 628 void dump(const Cfg *Func) const override;
608 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } 629 static bool classof(const Inst *Instr) { return Instr->getKind() == Load; }
609 630
610 private: 631 private:
611 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); 632 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr);
612 }; 633 };
613 634
614 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi 635 /// Phi instruction. For incoming edge I, the node is Labels[I] and the Phi
615 /// source operand is getSrc(I). 636 /// source operand is getSrc(I).
616 class InstPhi : public InstHighLevel { 637 class InstPhi : public InstHighLevel {
617 InstPhi() = delete; 638 InstPhi() = delete;
618 InstPhi(const InstPhi &) = delete; 639 InstPhi(const InstPhi &) = delete;
619 InstPhi &operator=(const InstPhi &) = delete; 640 InstPhi &operator=(const InstPhi &) = delete;
620 641
621 public: 642 public:
622 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { 643 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) {
623 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); 644 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest);
624 } 645 }
625 void addArgument(Operand *Source, CfgNode *Label); 646 void addArgument(Operand *Source, CfgNode *Label);
626 Operand *getOperandForTarget(CfgNode *Target) const; 647 Operand *getOperandForTarget(CfgNode *Target) const;
627 void clearOperandForTarget(CfgNode *Target); 648 void clearOperandForTarget(CfgNode *Target);
628 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } 649 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; }
629 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; } 650 void setLabel(SizeT Index, CfgNode *Label) { Labels[Index] = Label; }
630 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, 651 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target,
631 Liveness *Liveness); 652 Liveness *Liveness);
632 Inst *lower(Cfg *Func); 653 Inst *lower(Cfg *Func);
654 bool isMemoryWrite() const override { return false; }
633 void dump(const Cfg *Func) const override; 655 void dump(const Cfg *Func) const override;
634 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } 656 static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; }
635 657
636 private: 658 private:
637 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); 659 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest);
638 void destroy(Cfg *Func) override { 660 void destroy(Cfg *Func) override {
639 Func->deallocateArrayOf<CfgNode *>(Labels); 661 Func->deallocateArrayOf<CfgNode *>(Labels);
640 Inst::destroy(Func); 662 Inst::destroy(Func);
641 } 663 }
642 664
(...skipping 14 matching lines...) Expand all
657 public: 679 public:
658 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { 680 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) {
659 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); 681 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue);
660 } 682 }
661 bool hasRetValue() const { return getSrcSize(); } 683 bool hasRetValue() const { return getSrcSize(); }
662 Operand *getRetValue() const { 684 Operand *getRetValue() const {
663 assert(hasRetValue()); 685 assert(hasRetValue());
664 return getSrc(0); 686 return getSrc(0);
665 } 687 }
666 NodeList getTerminatorEdges() const override { return NodeList(); } 688 NodeList getTerminatorEdges() const override { return NodeList(); }
689 bool isMemoryWrite() const override { return false; }
667 void dump(const Cfg *Func) const override; 690 void dump(const Cfg *Func) const override;
668 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } 691 static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; }
669 692
670 private: 693 private:
671 InstRet(Cfg *Func, Operand *RetValue); 694 InstRet(Cfg *Func, Operand *RetValue);
672 }; 695 };
673 696
674 /// Select instruction. The condition, true, and false operands are captured. 697 /// Select instruction. The condition, true, and false operands are captured.
675 class InstSelect : public InstHighLevel { 698 class InstSelect : public InstHighLevel {
676 InstSelect() = delete; 699 InstSelect() = delete;
677 InstSelect(const InstSelect &) = delete; 700 InstSelect(const InstSelect &) = delete;
678 InstSelect &operator=(const InstSelect &) = delete; 701 InstSelect &operator=(const InstSelect &) = delete;
679 702
680 public: 703 public:
681 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, 704 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition,
682 Operand *SourceTrue, Operand *SourceFalse) { 705 Operand *SourceTrue, Operand *SourceFalse) {
683 return new (Func->allocate<InstSelect>()) 706 return new (Func->allocate<InstSelect>())
684 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); 707 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse);
685 } 708 }
686 Operand *getCondition() const { return getSrc(0); } 709 Operand *getCondition() const { return getSrc(0); }
687 Operand *getTrueOperand() const { return getSrc(1); } 710 Operand *getTrueOperand() const { return getSrc(1); }
688 Operand *getFalseOperand() const { return getSrc(2); } 711 Operand *getFalseOperand() const { return getSrc(2); }
712 bool isMemoryWrite() const override { return false; }
689 void dump(const Cfg *Func) const override; 713 void dump(const Cfg *Func) const override;
690 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } 714 static bool classof(const Inst *Instr) { return Instr->getKind() == Select; }
691 715
692 private: 716 private:
693 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, 717 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1,
694 Operand *Source2); 718 Operand *Source2);
695 }; 719 };
696 720
697 /// Store instruction. The address operand is captured, along with the data 721 /// Store instruction. The address operand is captured, along with the data
698 /// operand to be stored into the address. 722 /// operand to be stored into the address.
699 class InstStore : public InstHighLevel { 723 class InstStore : public InstHighLevel {
700 InstStore() = delete; 724 InstStore() = delete;
701 InstStore(const InstStore &) = delete; 725 InstStore(const InstStore &) = delete;
702 InstStore &operator=(const InstStore &) = delete; 726 InstStore &operator=(const InstStore &) = delete;
703 727
704 public: 728 public:
705 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, 729 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr,
706 uint32_t Align = 1) { 730 uint32_t Align = 1) {
707 // TODO(kschimpf) Stop ignoring alignment specification. 731 // TODO(kschimpf) Stop ignoring alignment specification.
708 (void)Align; 732 (void)Align;
709 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); 733 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr);
710 } 734 }
711 Operand *getAddr() const { return getSrc(1); } 735 Operand *getAddr() const { return getSrc(1); }
712 Operand *getData() const { return getSrc(0); } 736 Operand *getData() const { return getSrc(0); }
713 Variable *getRmwBeacon() const; 737 Variable *getRmwBeacon() const;
714 void setRmwBeacon(Variable *Beacon); 738 void setRmwBeacon(Variable *Beacon);
739 bool isMemoryWrite() const override { return true; }
715 void dump(const Cfg *Func) const override; 740 void dump(const Cfg *Func) const override;
716 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } 741 static bool classof(const Inst *Instr) { return Instr->getKind() == Store; }
717 742
718 private: 743 private:
719 InstStore(Cfg *Func, Operand *Data, Operand *Addr); 744 InstStore(Cfg *Func, Operand *Data, Operand *Addr);
720 }; 745 };
721 746
722 /// Switch instruction. The single source operand is captured as getSrc(0). 747 /// Switch instruction. The single source operand is captured as getSrc(0).
723 class InstSwitch : public InstHighLevel { 748 class InstSwitch : public InstHighLevel {
724 InstSwitch() = delete; 749 InstSwitch() = delete;
(...skipping 13 matching lines...) Expand all
738 assert(I < NumCases); 763 assert(I < NumCases);
739 return Values[I]; 764 return Values[I];
740 } 765 }
741 CfgNode *getLabel(SizeT I) const { 766 CfgNode *getLabel(SizeT I) const {
742 assert(I < NumCases); 767 assert(I < NumCases);
743 return Labels[I]; 768 return Labels[I];
744 } 769 }
745 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); 770 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label);
746 NodeList getTerminatorEdges() const override; 771 NodeList getTerminatorEdges() const override;
747 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 772 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
773 bool isMemoryWrite() const override { return false; }
748 void dump(const Cfg *Func) const override; 774 void dump(const Cfg *Func) const override;
749 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } 775 static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; }
750 776
751 private: 777 private:
752 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); 778 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault);
753 void destroy(Cfg *Func) override { 779 void destroy(Cfg *Func) override {
754 Func->deallocateArrayOf<uint64_t>(Values); 780 Func->deallocateArrayOf<uint64_t>(Values);
755 Func->deallocateArrayOf<CfgNode *>(Labels); 781 Func->deallocateArrayOf<CfgNode *>(Labels);
756 Inst::destroy(Func); 782 Inst::destroy(Func);
757 } 783 }
758 784
759 CfgNode *LabelDefault; 785 CfgNode *LabelDefault;
760 SizeT NumCases; /// not including the default case 786 SizeT NumCases; /// not including the default case
761 uint64_t *Values; /// size is NumCases 787 uint64_t *Values; /// size is NumCases
762 CfgNode **Labels; /// size is NumCases 788 CfgNode **Labels; /// size is NumCases
763 }; 789 };
764 790
765 /// Unreachable instruction. This is a terminator instruction with no operands. 791 /// Unreachable instruction. This is a terminator instruction with no operands.
766 class InstUnreachable : public InstHighLevel { 792 class InstUnreachable : public InstHighLevel {
767 InstUnreachable() = delete; 793 InstUnreachable() = delete;
768 InstUnreachable(const InstUnreachable &) = delete; 794 InstUnreachable(const InstUnreachable &) = delete;
769 InstUnreachable &operator=(const InstUnreachable &) = delete; 795 InstUnreachable &operator=(const InstUnreachable &) = delete;
770 796
771 public: 797 public:
772 static InstUnreachable *create(Cfg *Func) { 798 static InstUnreachable *create(Cfg *Func) {
773 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); 799 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func);
774 } 800 }
775 NodeList getTerminatorEdges() const override { return NodeList(); } 801 NodeList getTerminatorEdges() const override { return NodeList(); }
802 bool isMemoryWrite() const override { return false; }
776 void dump(const Cfg *Func) const override; 803 void dump(const Cfg *Func) const override;
777 static bool classof(const Inst *Instr) { 804 static bool classof(const Inst *Instr) {
778 return Instr->getKind() == Unreachable; 805 return Instr->getKind() == Unreachable;
779 } 806 }
780 807
781 private: 808 private:
782 explicit InstUnreachable(Cfg *Func); 809 explicit InstUnreachable(Cfg *Func);
783 }; 810 };
784 811
785 /// BundleLock instruction. There are no operands. Contains an option 812 /// BundleLock instruction. There are no operands. Contains an option
786 /// indicating whether align_to_end is specified. 813 /// indicating whether align_to_end is specified.
787 class InstBundleLock : public InstHighLevel { 814 class InstBundleLock : public InstHighLevel {
788 InstBundleLock() = delete; 815 InstBundleLock() = delete;
789 InstBundleLock(const InstBundleLock &) = delete; 816 InstBundleLock(const InstBundleLock &) = delete;
790 InstBundleLock &operator=(const InstBundleLock &) = delete; 817 InstBundleLock &operator=(const InstBundleLock &) = delete;
791 818
792 public: 819 public:
793 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd }; 820 enum Option { Opt_None, Opt_AlignToEnd, Opt_PadToEnd };
794 static InstBundleLock *create(Cfg *Func, Option BundleOption) { 821 static InstBundleLock *create(Cfg *Func, Option BundleOption) {
795 return new (Func->allocate<InstBundleLock>()) 822 return new (Func->allocate<InstBundleLock>())
796 InstBundleLock(Func, BundleOption); 823 InstBundleLock(Func, BundleOption);
797 } 824 }
798 void emit(const Cfg *Func) const override; 825 void emit(const Cfg *Func) const override;
799 void emitIAS(const Cfg * /* Func */) const override {} 826 void emitIAS(const Cfg * /* Func */) const override {}
827 bool isMemoryWrite() const override { return false; }
800 void dump(const Cfg *Func) const override; 828 void dump(const Cfg *Func) const override;
801 Option getOption() const { return BundleOption; } 829 Option getOption() const { return BundleOption; }
802 static bool classof(const Inst *Instr) { 830 static bool classof(const Inst *Instr) {
803 return Instr->getKind() == BundleLock; 831 return Instr->getKind() == BundleLock;
804 } 832 }
805 833
806 private: 834 private:
807 Option BundleOption; 835 Option BundleOption;
808 InstBundleLock(Cfg *Func, Option BundleOption); 836 InstBundleLock(Cfg *Func, Option BundleOption);
809 }; 837 };
810 838
811 /// BundleUnlock instruction. There are no operands. 839 /// BundleUnlock instruction. There are no operands.
812 class InstBundleUnlock : public InstHighLevel { 840 class InstBundleUnlock : public InstHighLevel {
813 InstBundleUnlock() = delete; 841 InstBundleUnlock() = delete;
814 InstBundleUnlock(const InstBundleUnlock &) = delete; 842 InstBundleUnlock(const InstBundleUnlock &) = delete;
815 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; 843 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete;
816 844
817 public: 845 public:
818 static InstBundleUnlock *create(Cfg *Func) { 846 static InstBundleUnlock *create(Cfg *Func) {
819 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); 847 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func);
820 } 848 }
821 void emit(const Cfg *Func) const override; 849 void emit(const Cfg *Func) const override;
822 void emitIAS(const Cfg * /* Func */) const override {} 850 void emitIAS(const Cfg * /* Func */) const override {}
851 bool isMemoryWrite() const override { return false; }
823 void dump(const Cfg *Func) const override; 852 void dump(const Cfg *Func) const override;
824 static bool classof(const Inst *Instr) { 853 static bool classof(const Inst *Instr) {
825 return Instr->getKind() == BundleUnlock; 854 return Instr->getKind() == BundleUnlock;
826 } 855 }
827 856
828 private: 857 private:
829 explicit InstBundleUnlock(Cfg *Func); 858 explicit InstBundleUnlock(Cfg *Func);
830 }; 859 };
831 860
832 /// FakeDef instruction. This creates a fake definition of a variable, which is 861 /// FakeDef instruction. This creates a fake definition of a variable, which is
(...skipping 12 matching lines...) Expand all
845 InstFakeDef(const InstFakeDef &) = delete; 874 InstFakeDef(const InstFakeDef &) = delete;
846 InstFakeDef &operator=(const InstFakeDef &) = delete; 875 InstFakeDef &operator=(const InstFakeDef &) = delete;
847 876
848 public: 877 public:
849 static InstFakeDef *create(Cfg *Func, Variable *Dest, 878 static InstFakeDef *create(Cfg *Func, Variable *Dest,
850 Variable *Src = nullptr) { 879 Variable *Src = nullptr) {
851 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); 880 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src);
852 } 881 }
853 void emit(const Cfg *Func) const override; 882 void emit(const Cfg *Func) const override;
854 void emitIAS(const Cfg * /* Func */) const override {} 883 void emitIAS(const Cfg * /* Func */) const override {}
884 bool isMemoryWrite() const override { return false; }
855 void dump(const Cfg *Func) const override; 885 void dump(const Cfg *Func) const override;
856 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } 886 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; }
857 887
858 private: 888 private:
859 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); 889 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src);
860 }; 890 };
861 891
862 /// FakeUse instruction. This creates a fake use of a variable, to keep the 892 /// FakeUse instruction. This creates a fake use of a variable, to keep the
863 /// instruction that produces that variable from being dead-code eliminated. 893 /// instruction that produces that variable from being dead-code eliminated.
864 /// This is useful in a variety of lowering situations. The FakeUse instruction 894 /// 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 895 /// 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 896 /// 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 897 /// of implementation, weight=N is handled by holding N copies of the variable
868 /// as source operands. 898 /// as source operands.
869 class InstFakeUse : public InstHighLevel { 899 class InstFakeUse : public InstHighLevel {
870 InstFakeUse() = delete; 900 InstFakeUse() = delete;
871 InstFakeUse(const InstFakeUse &) = delete; 901 InstFakeUse(const InstFakeUse &) = delete;
872 InstFakeUse &operator=(const InstFakeUse &) = delete; 902 InstFakeUse &operator=(const InstFakeUse &) = delete;
873 903
874 public: 904 public:
875 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) { 905 static InstFakeUse *create(Cfg *Func, Variable *Src, uint32_t Weight = 1) {
876 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight); 906 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src, Weight);
877 } 907 }
878 void emit(const Cfg *Func) const override; 908 void emit(const Cfg *Func) const override;
879 void emitIAS(const Cfg * /* Func */) const override {} 909 void emitIAS(const Cfg * /* Func */) const override {}
910 bool isMemoryWrite() const override { return false; }
880 void dump(const Cfg *Func) const override; 911 void dump(const Cfg *Func) const override;
881 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } 912 static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; }
882 913
883 private: 914 private:
884 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight); 915 InstFakeUse(Cfg *Func, Variable *Src, uint32_t Weight);
885 }; 916 };
886 917
887 /// FakeKill instruction. This "kills" a set of variables by modeling a trivial 918 /// 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 919 /// 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 920 /// 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 921 /// register allocator won't assign a scratch register to a variable whose live
891 /// range spans a call. 922 /// range spans a call.
892 /// 923 ///
893 /// The FakeKill instruction also holds a pointer to the instruction that kills 924 /// 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 925 /// the set of variables, so that if that linked instruction gets dead-code
895 /// eliminated, the FakeKill instruction will as well. 926 /// eliminated, the FakeKill instruction will as well.
896 class InstFakeKill : public InstHighLevel { 927 class InstFakeKill : public InstHighLevel {
897 InstFakeKill() = delete; 928 InstFakeKill() = delete;
898 InstFakeKill(const InstFakeKill &) = delete; 929 InstFakeKill(const InstFakeKill &) = delete;
899 InstFakeKill &operator=(const InstFakeKill &) = delete; 930 InstFakeKill &operator=(const InstFakeKill &) = delete;
900 931
901 public: 932 public:
902 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { 933 static InstFakeKill *create(Cfg *Func, const Inst *Linked) {
903 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); 934 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked);
904 } 935 }
905 const Inst *getLinked() const { return Linked; } 936 const Inst *getLinked() const { return Linked; }
906 void emit(const Cfg *Func) const override; 937 void emit(const Cfg *Func) const override;
907 void emitIAS(const Cfg * /* Func */) const override {} 938 void emitIAS(const Cfg * /* Func */) const override {}
939 bool isMemoryWrite() const override { return false; }
908 void dump(const Cfg *Func) const override; 940 void dump(const Cfg *Func) const override;
909 static bool classof(const Inst *Instr) { 941 static bool classof(const Inst *Instr) {
910 return Instr->getKind() == FakeKill; 942 return Instr->getKind() == FakeKill;
911 } 943 }
912 944
913 private: 945 private:
914 InstFakeKill(Cfg *Func, const Inst *Linked); 946 InstFakeKill(Cfg *Func, const Inst *Linked);
915 947
916 /// This instruction is ignored if Linked->isDeleted() is true. 948 /// This instruction is ignored if Linked->isDeleted() is true.
917 const Inst *Linked; 949 const Inst *Linked;
(...skipping 16 matching lines...) Expand all
934 assert(TargetIndex < NumTargets); 966 assert(TargetIndex < NumTargets);
935 Targets[TargetIndex] = Target; 967 Targets[TargetIndex] = Target;
936 } 968 }
937 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; 969 bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
938 SizeT getId() const { return Id; } 970 SizeT getId() const { return Id; }
939 SizeT getNumTargets() const { return NumTargets; } 971 SizeT getNumTargets() const { return NumTargets; }
940 CfgNode *getTarget(SizeT I) const { 972 CfgNode *getTarget(SizeT I) const {
941 assert(I < NumTargets); 973 assert(I < NumTargets);
942 return Targets[I]; 974 return Targets[I];
943 } 975 }
976 bool isMemoryWrite() const override { return false; }
944 void dump(const Cfg *Func) const override; 977 void dump(const Cfg *Func) const override;
945 static bool classof(const Inst *Instr) { 978 static bool classof(const Inst *Instr) {
946 return Instr->getKind() == JumpTable; 979 return Instr->getKind() == JumpTable;
947 } 980 }
948 // Creates a JumpTableData struct (used for ELF emission) that represents this 981 // Creates a JumpTableData struct (used for ELF emission) that represents this
949 // InstJumpTable. 982 // InstJumpTable.
950 JumpTableData toJumpTableData(Assembler *Asm) const; 983 JumpTableData toJumpTableData(Assembler *Asm) const;
951 984
952 // InstJumpTable is just a placeholder for the switch targets, and it does not 985 // 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. 986 // need to emit any code, so we redefine emit and emitIAS to do nothing.
(...skipping 27 matching lines...) Expand all
981 /// 1014 ///
982 /// On x86, this assembles into an INT 3 instruction. 1015 /// On x86, this assembles into an INT 3 instruction.
983 /// 1016 ///
984 /// This instruction is primarily meant for debugging the code generator. 1017 /// This instruction is primarily meant for debugging the code generator.
985 class InstBreakpoint : public InstHighLevel { 1018 class InstBreakpoint : public InstHighLevel {
986 public: 1019 public:
987 InstBreakpoint() = delete; 1020 InstBreakpoint() = delete;
988 InstBreakpoint(const InstBreakpoint &) = delete; 1021 InstBreakpoint(const InstBreakpoint &) = delete;
989 InstBreakpoint &operator=(const InstBreakpoint &) = delete; 1022 InstBreakpoint &operator=(const InstBreakpoint &) = delete;
990 1023
991 InstBreakpoint(Cfg *Func); 1024 explicit InstBreakpoint(Cfg *Func);
1025 bool isMemoryWrite() const override { return false; }
992 1026
993 public: 1027 public:
994 static InstBreakpoint *create(Cfg *Func) { 1028 static InstBreakpoint *create(Cfg *Func) {
995 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func); 1029 return new (Func->allocate<InstBreakpoint>()) InstBreakpoint(Func);
996 } 1030 }
997 1031
998 static bool classof(const Inst *Instr) { 1032 static bool classof(const Inst *Instr) {
999 return Instr->getKind() == Breakpoint; 1033 return Instr->getKind() == Breakpoint;
1000 } 1034 }
1001 }; 1035 };
1002 1036
1003 /// The Target instruction is the base class for all target-specific 1037 /// The Target instruction is the base class for all target-specific
1004 /// instructions. 1038 /// instructions.
1005 class InstTarget : public Inst { 1039 class InstTarget : public Inst {
1006 InstTarget() = delete; 1040 InstTarget() = delete;
1007 InstTarget(const InstTarget &) = delete; 1041 InstTarget(const InstTarget &) = delete;
1008 InstTarget &operator=(const InstTarget &) = delete; 1042 InstTarget &operator=(const InstTarget &) = delete;
1009 1043
1010 public: 1044 public:
1011 uint32_t getEmitInstCount() const override { return 1; } 1045 uint32_t getEmitInstCount() const override { return 1; }
1046 bool isMemoryWrite() const override {
1047 return true; // conservative answer
1048 }
1012 void dump(const Cfg *Func) const override; 1049 void dump(const Cfg *Func) const override;
1013 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } 1050 static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; }
1014 1051
1015 protected: 1052 protected:
1016 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 1053 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
1017 : Inst(Func, Kind, MaxSrcs, Dest) { 1054 : Inst(Func, Kind, MaxSrcs, Dest) {
1018 assert(Kind >= Target); 1055 assert(Kind >= Target);
1019 assert(Kind <= Target_Max); 1056 assert(Kind <= Target_Max);
1020 } 1057 }
1021 }; 1058 };
(...skipping 17 matching lines...) Expand all
1039 static void noteHead(Ice::Inst *, Ice::Inst *) {} 1076 static void noteHead(Ice::Inst *, Ice::Inst *) {}
1040 void deleteNode(Ice::Inst *) {} 1077 void deleteNode(Ice::Inst *) {}
1041 1078
1042 private: 1079 private:
1043 mutable ilist_half_node<Ice::Inst> Sentinel; 1080 mutable ilist_half_node<Ice::Inst> Sentinel;
1044 }; 1081 };
1045 1082
1046 } // end of namespace llvm 1083 } // end of namespace llvm
1047 1084
1048 #endif // SUBZERO_SRC_ICEINST_H 1085 #endif // SUBZERO_SRC_ICEINST_H
OLDNEW
« no previous file with comments | « no previous file | src/IceInst.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698