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

Side by Side Diff: src/IceOperand.h

Issue 1312433004: Weight variables by their number of uses for register allocation. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Count uses in VMetadata Created 5 years, 3 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
OLDNEW
1 //===- subzero/src/IceOperand.h - High-level operands -----------*- C++ -*-===// 1 //===- subzero/src/IceOperand.h - High-level operands -----------*- 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 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
325 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register 325 const static uint32_t Zero = 0; /// Force regalloc NOT to give a register
326 void addWeight(uint32_t Delta) { 326 void addWeight(uint32_t Delta) {
327 if (Delta == Inf) 327 if (Delta == Inf)
328 Weight = Inf; 328 Weight = Inf;
329 else if (Weight != Inf) 329 else if (Weight != Inf)
330 Weight += Delta; 330 Weight += Delta;
331 } 331 }
332 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); } 332 void addWeight(const RegWeight &Other) { addWeight(Other.Weight); }
333 void setWeight(uint32_t Val) { Weight = Val; } 333 void setWeight(uint32_t Val) { Weight = Val; }
334 uint32_t getWeight() const { return Weight; } 334 uint32_t getWeight() const { return Weight; }
335 bool isInf() const { return Weight == Inf; }
336 bool isZero() const { return Weight == Zero; }
337 335
338 private: 336 private:
339 uint32_t Weight = 0; 337 uint32_t Weight = 0;
340 }; 338 };
341 Ostream &operator<<(Ostream &Str, const RegWeight &W); 339 Ostream &operator<<(Ostream &Str, const RegWeight &W);
342 bool operator<(const RegWeight &A, const RegWeight &B); 340 bool operator<(const RegWeight &A, const RegWeight &B);
343 bool operator<=(const RegWeight &A, const RegWeight &B); 341 bool operator<=(const RegWeight &A, const RegWeight &B);
344 bool operator==(const RegWeight &A, const RegWeight &B); 342 bool operator==(const RegWeight &A, const RegWeight &B);
345 343
346 /// LiveRange is a set of instruction number intervals representing 344 /// LiveRange is a set of instruction number intervals representing
347 /// a variable's live range. Generally there is one interval per basic 345 /// a variable's live range. Generally there is one interval per basic
348 /// block where the variable is live, but adjacent intervals get 346 /// block where the variable is live, but adjacent intervals get
349 /// coalesced into a single interval. LiveRange also includes a 347 /// coalesced into a single interval.
350 /// weight, in case e.g. we want a live range to have higher weight
351 /// inside a loop.
352 class LiveRange { 348 class LiveRange {
353 public: 349 public:
354 LiveRange() = default; 350 LiveRange() = default;
355 /// Special constructor for building a kill set. The advantage is 351 /// Special constructor for building a kill set. The advantage is
356 /// that we can reserve the right amount of space in advance. 352 /// that we can reserve the right amount of space in advance.
357 explicit LiveRange(const std::vector<InstNumberT> &Kills) { 353 explicit LiveRange(const std::vector<InstNumberT> &Kills) {
358 Range.reserve(Kills.size()); 354 Range.reserve(Kills.size());
359 for (InstNumberT I : Kills) 355 for (InstNumberT I : Kills)
360 addSegment(I, I); 356 addSegment(I, I);
361 } 357 }
362 LiveRange(const LiveRange &) = default; 358 LiveRange(const LiveRange &) = default;
363 LiveRange &operator=(const LiveRange &) = default; 359 LiveRange &operator=(const LiveRange &) = default;
364 360
365 void reset() { 361 void reset() {
366 Range.clear(); 362 Range.clear();
367 Weight.setWeight(0);
368 untrim(); 363 untrim();
369 } 364 }
370 void addSegment(InstNumberT Start, InstNumberT End); 365 void addSegment(InstNumberT Start, InstNumberT End);
371 366
372 bool endsBefore(const LiveRange &Other) const; 367 bool endsBefore(const LiveRange &Other) const;
373 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; 368 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
374 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; 369 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
375 bool containsValue(InstNumberT Value, bool IsDest) const; 370 bool containsValue(InstNumberT Value, bool IsDest) const;
376 bool isEmpty() const { return Range.empty(); } 371 bool isEmpty() const { return Range.empty(); }
377 InstNumberT getStart() const { 372 InstNumberT getStart() const {
378 return Range.empty() ? -1 : Range.begin()->first; 373 return Range.empty() ? -1 : Range.begin()->first;
379 } 374 }
380 InstNumberT getEnd() const { 375 InstNumberT getEnd() const {
381 return Range.empty() ? -1 : Range.rbegin()->second; 376 return Range.empty() ? -1 : Range.rbegin()->second;
382 } 377 }
383 378
384 void untrim() { TrimmedBegin = Range.begin(); } 379 void untrim() { TrimmedBegin = Range.begin(); }
385 void trim(InstNumberT Lower); 380 void trim(InstNumberT Lower);
386 381
387 RegWeight getWeight() const { return Weight; }
388 void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
389 void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
390 void dump(Ostream &Str) const; 382 void dump(Ostream &Str) const;
391 383
392 private: 384 private:
393 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; 385 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
394 /// RangeType is arena-allocated from the Cfg's allocator. 386 /// RangeType is arena-allocated from the Cfg's allocator.
395 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> 387 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
396 RangeType; 388 RangeType;
397 RangeType Range; 389 RangeType Range;
398 RegWeight Weight = RegWeight(0);
399 /// TrimmedBegin is an optimization for the overlaps() computation. 390 /// TrimmedBegin is an optimization for the overlaps() computation.
400 /// Since the linear-scan algorithm always calls it as overlaps(Cur) 391 /// Since the linear-scan algorithm always calls it as overlaps(Cur)
401 /// and Cur advances monotonically according to live range start, we 392 /// and Cur advances monotonically according to live range start, we
402 /// can optimize overlaps() by ignoring all segments that end before 393 /// can optimize overlaps() by ignoring all segments that end before
403 /// the start of Cur's range. The linear-scan code enables this by 394 /// the start of Cur's range. The linear-scan code enables this by
404 /// calling trim() on the ranges of interest as Cur advances. Note 395 /// calling trim() on the ranges of interest as Cur advances. Note
405 /// that linear-scan also has to initialize TrimmedBegin at the 396 /// that linear-scan also has to initialize TrimmedBegin at the
406 /// beginning by calling untrim(). 397 /// beginning by calling untrim().
407 RangeType::const_iterator TrimmedBegin; 398 RangeType::const_iterator TrimmedBegin;
408 }; 399 };
409 400
410 Ostream &operator<<(Ostream &Str, const LiveRange &L); 401 Ostream &operator<<(Ostream &Str, const LiveRange &L);
411 402
412 /// Variable represents an operand that is register-allocated or 403 /// Variable represents an operand that is register-allocated or
413 /// stack-allocated. If it is register-allocated, it will ultimately 404 /// stack-allocated. If it is register-allocated, it will ultimately
414 /// have a non-negative RegNum field. 405 /// have a non-negative RegNum field.
415 class Variable : public Operand { 406 class Variable : public Operand {
416 Variable() = delete; 407 Variable() = delete;
417 Variable(const Variable &) = delete; 408 Variable(const Variable &) = delete;
418 Variable &operator=(const Variable &) = delete; 409 Variable &operator=(const Variable &) = delete;
419 410
411 enum RegRequirement {
412 RR_MayHaveRegister,
413 RR_MustHaveRegister,
414 RR_MustNotHaveRegister,
415 };
416
420 public: 417 public:
421 static Variable *create(Cfg *Func, Type Ty, SizeT Index) { 418 static Variable *create(Cfg *Func, Type Ty, SizeT Index) {
422 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index); 419 return new (Func->allocate<Variable>()) Variable(kVariable, Ty, Index);
423 } 420 }
424 421
425 SizeT getIndex() const { return Number; } 422 SizeT getIndex() const { return Number; }
426 IceString getName(const Cfg *Func) const; 423 IceString getName(const Cfg *Func) const;
427 void setName(Cfg *Func, const IceString &NewName) { 424 void setName(Cfg *Func, const IceString &NewName) {
428 // Make sure that the name can only be set once. 425 // Make sure that the name can only be set once.
429 assert(NameIndex == Cfg::IdentifierIndexInvalid); 426 assert(NameIndex == Cfg::IdentifierIndexInvalid);
(...skipping 17 matching lines...) Expand all
447 int32_t getRegNum() const { return RegNum; } 444 int32_t getRegNum() const { return RegNum; }
448 void setRegNum(int32_t NewRegNum) { 445 void setRegNum(int32_t NewRegNum) {
449 // Regnum shouldn't be set more than once. 446 // Regnum shouldn't be set more than once.
450 assert(!hasReg() || RegNum == NewRegNum); 447 assert(!hasReg() || RegNum == NewRegNum);
451 RegNum = NewRegNum; 448 RegNum = NewRegNum;
452 } 449 }
453 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } 450 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
454 int32_t getRegNumTmp() const { return RegNumTmp; } 451 int32_t getRegNumTmp() const { return RegNumTmp; }
455 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } 452 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
456 453
457 RegWeight getWeight() const { return Weight; } 454 RegWeight getWeight(const Cfg *Func) const;
458 void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); } 455
459 void setWeightInfinite() { setWeight(RegWeight::Inf); } 456 void setMustHaveReg() { RegRequirement = RR_MustHaveRegister; }
457 bool mustHaveReg() const { return RegRequirement == RR_MustHaveRegister; }
458 void setMustNotHaveReg() { RegRequirement = RR_MustNotHaveRegister; }
459 bool mustNotHaveReg() const {
460 return RegRequirement == RR_MustNotHaveRegister;
461 }
460 462
461 LiveRange &getLiveRange() { return Live; } 463 LiveRange &getLiveRange() { return Live; }
462 const LiveRange &getLiveRange() const { return Live; } 464 const LiveRange &getLiveRange() const { return Live; }
463 void setLiveRange(const LiveRange &Range) { Live = Range; } 465 void setLiveRange(const LiveRange &Range) { Live = Range; }
464 void resetLiveRange() { Live.reset(); } 466 void resetLiveRange() { Live.reset(); }
465 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { 467 void addLiveRange(InstNumberT Start, InstNumberT End) {
466 assert(!getIgnoreLiveness()); 468 assert(!getIgnoreLiveness());
467 assert(WeightDelta != RegWeight::Inf);
468 Live.addSegment(Start, End); 469 Live.addSegment(Start, End);
469 if (Weight.isInf())
470 Live.setWeight(RegWeight(RegWeight::Inf));
471 else
472 Live.addWeight(WeightDelta * Weight.getWeight());
473 }
474 void setLiveRangeInfiniteWeight() {
475 Live.setWeight(RegWeight(RegWeight::Inf));
476 } 470 }
477 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } 471 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
478 void untrimLiveRange() { Live.untrim(); } 472 void untrimLiveRange() { Live.untrim(); }
479 bool rangeEndsBefore(const Variable *Other) const { 473 bool rangeEndsBefore(const Variable *Other) const {
480 return Live.endsBefore(Other->Live); 474 return Live.endsBefore(Other->Live);
481 } 475 }
482 bool rangeOverlaps(const Variable *Other) const { 476 bool rangeOverlaps(const Variable *Other) const {
483 const bool UseTrimmed = true; 477 const bool UseTrimmed = true;
484 return Live.overlaps(Other->Live, UseTrimmed); 478 return Live.overlaps(Other->Live, UseTrimmed);
485 } 479 }
486 bool rangeOverlapsStart(const Variable *Other) const { 480 bool rangeOverlapsStart(const Variable *Other) const {
487 const bool UseTrimmed = true; 481 const bool UseTrimmed = true;
488 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); 482 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
489 } 483 }
490 484
491 Variable *getLo() const { return LoVar; } 485 Variable *getLo() const { return LoVar; }
492 Variable *getHi() const { return HiVar; } 486 Variable *getHi() const { return HiVar; }
493 void setLoHi(Variable *Lo, Variable *Hi) { 487 void setLoHi(Variable *Lo, Variable *Hi) {
494 assert(LoVar == nullptr); 488 assert(LoVar == nullptr);
495 assert(HiVar == nullptr); 489 assert(HiVar == nullptr);
496 LoVar = Lo; 490 LoVar = Lo;
497 HiVar = Hi; 491 HiVar = Hi;
498 } 492 }
499 /// Creates a temporary copy of the variable with a different type. 493 /// Creates a temporary copy of the variable with a different type.
500 /// Used primarily for syntactic correctness of textual assembly 494 /// Used primarily for syntactic correctness of textual assembly
501 /// emission. Note that only basic information is copied, in 495 /// emission. Note that only basic information is copied, in
502 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, 496 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
503 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. 497 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal.
jvoung (off chromium) 2015/08/28 20:31:45 can remove Weight field comment too
ascull 2015/08/28 21:22:36 Done.
504 Variable *asType(Type Ty); 498 Variable *asType(Type Ty);
505 499
506 void emit(const Cfg *Func) const override; 500 void emit(const Cfg *Func) const override;
507 using Operand::dump; 501 using Operand::dump;
508 void dump(const Cfg *Func, Ostream &Str) const override; 502 void dump(const Cfg *Func, Ostream &Str) const override;
509 503
510 /// Return reg num of base register, if different from stack/frame register. 504 /// Return reg num of base register, if different from stack/frame register.
511 virtual int32_t getBaseRegNum() const { return NoRegister; } 505 virtual int32_t getBaseRegNum() const { return NoRegister; }
512 506
513 static bool classof(const Operand *Operand) { 507 static bool classof(const Operand *Operand) {
(...skipping 19 matching lines...) Expand all
533 /// reserved for the stack pointer. 527 /// reserved for the stack pointer.
534 bool IgnoreLiveness = false; 528 bool IgnoreLiveness = false;
535 /// StackOffset is the canonical location on stack (only if 529 /// StackOffset is the canonical location on stack (only if
536 /// RegNum==NoRegister || IsArgument). 530 /// RegNum==NoRegister || IsArgument).
537 int32_t StackOffset = 0; 531 int32_t StackOffset = 0;
538 /// RegNum is the allocated register, or NoRegister if it isn't 532 /// RegNum is the allocated register, or NoRegister if it isn't
539 /// register-allocated. 533 /// register-allocated.
540 int32_t RegNum = NoRegister; 534 int32_t RegNum = NoRegister;
541 /// RegNumTmp is the tentative assignment during register allocation. 535 /// RegNumTmp is the tentative assignment during register allocation.
542 int32_t RegNumTmp = NoRegister; 536 int32_t RegNumTmp = NoRegister;
543 RegWeight Weight = RegWeight(1); // Register allocation priority 537 /// \name Register allocation priority
538 /// @{
539 RegRequirement RegRequirement = RR_MayHaveRegister;
540 /// @}
544 LiveRange Live; 541 LiveRange Live;
545 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 542 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
546 // lowering from I64 to I32 on a 32-bit architecture, we split the 543 // lowering from I64 to I32 on a 32-bit architecture, we split the
547 // variable into two machine-size pieces. LoVar is the low-order 544 // variable into two machine-size pieces. LoVar is the low-order
548 // machine-size portion, and HiVar is the remaining high-order 545 // machine-size portion, and HiVar is the remaining high-order
549 // portion. TODO: It's wasteful to penalize all variables on all 546 // portion. TODO: It's wasteful to penalize all variables on all
550 // targets this way; use a sparser representation. It's also 547 // targets this way; use a sparser representation. It's also
551 // wasteful for a 64-bit target. 548 // wasteful for a 64-bit target.
552 Variable *LoVar = nullptr; 549 Variable *LoVar = nullptr;
553 Variable *HiVar = nullptr; 550 Variable *HiVar = nullptr;
(...skipping 24 matching lines...) Expand all
578 }; 575 };
579 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock }; 576 enum MultiBlockState { MBS_Unknown, MBS_SingleBlock, MBS_MultiBlock };
580 VariableTracking() = default; 577 VariableTracking() = default;
581 VariableTracking(const VariableTracking &) = default; 578 VariableTracking(const VariableTracking &) = default;
582 MultiDefState getMultiDef() const { return MultiDef; } 579 MultiDefState getMultiDef() const { return MultiDef; }
583 MultiBlockState getMultiBlock() const { return MultiBlock; } 580 MultiBlockState getMultiBlock() const { return MultiBlock; }
584 const Inst *getFirstDefinition() const; 581 const Inst *getFirstDefinition() const;
585 const Inst *getSingleDefinition() const; 582 const Inst *getSingleDefinition() const;
586 const InstDefList &getLatterDefinitions() const { return Definitions; } 583 const InstDefList &getLatterDefinitions() const { return Definitions; }
587 CfgNode *getNode() const { return SingleUseNode; } 584 CfgNode *getNode() const { return SingleUseNode; }
585 uint32_t getUseWeight() const { return UseWeight; }
588 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node, 586 void markUse(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node,
589 bool IsImplicit); 587 bool IsImplicit);
590 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node); 588 void markDef(MetadataKind TrackingKind, const Inst *Instr, CfgNode *Node);
591 589
592 private: 590 private:
593 MultiDefState MultiDef = MDS_Unknown; 591 MultiDefState MultiDef = MDS_Unknown;
594 MultiBlockState MultiBlock = MBS_Unknown; 592 MultiBlockState MultiBlock = MBS_Unknown;
595 CfgNode *SingleUseNode = nullptr; 593 CfgNode *SingleUseNode = nullptr;
596 CfgNode *SingleDefNode = nullptr; 594 CfgNode *SingleDefNode = nullptr;
597 /// All definitions of the variable are collected here, in increasing 595 /// All definitions of the variable are collected here, in increasing
598 /// order of instruction number. 596 /// order of instruction number.
599 InstDefList Definitions; /// Only used if Kind==VMK_All 597 InstDefList Definitions; /// Only used if Kind==VMK_All
600 const Inst *FirstOrSingleDefinition = 598 const Inst *FirstOrSingleDefinition =
601 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All 599 nullptr; /// Is a copy of Definitions[0] if Kind==VMK_All
600 uint32_t UseWeight = 0;
602 }; 601 };
603 602
604 /// VariablesMetadata analyzes and summarizes the metadata for the 603 /// VariablesMetadata analyzes and summarizes the metadata for the complete set
605 /// complete set of Variables. 604 /// of Variables.
606 class VariablesMetadata { 605 class VariablesMetadata {
607 VariablesMetadata() = delete; 606 VariablesMetadata() = delete;
608 VariablesMetadata(const VariablesMetadata &) = delete; 607 VariablesMetadata(const VariablesMetadata &) = delete;
609 VariablesMetadata &operator=(const VariablesMetadata &) = delete; 608 VariablesMetadata &operator=(const VariablesMetadata &) = delete;
610 609
611 public: 610 public:
612 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {} 611 explicit VariablesMetadata(const Cfg *Func) : Func(Func) {}
613 /// Initialize the state by traversing all instructions/variables in 612 /// Initialize the state by traversing all instructions/variables in
614 /// the CFG. 613 /// the CFG.
615 void init(MetadataKind TrackingKind); 614 void init(MetadataKind TrackingKind);
616 /// Add a single node. This is called by init(), and can be called 615 /// Add a single node. This is called by init(), and can be called
617 /// incrementally from elsewhere, e.g. after edge-splitting. 616 /// incrementally from elsewhere, e.g. after edge-splitting.
618 void addNode(CfgNode *Node); 617 void addNode(CfgNode *Node);
619 /// Returns whether the given Variable is tracked in this object. It 618 /// Returns whether the given Variable is tracked in this object. It should
620 /// should only return false if changes were made to the CFG after 619 /// only return false if changes were made to the CFG after running init(), in
621 /// running init(), in which case the state is stale and the results 620 /// which case the state is stale and the results shouldn't be trusted (but it
622 /// shouldn't be trusted (but it may be OK e.g. for dumping). 621 /// may be OK e.g. for dumping).
623 bool isTracked(const Variable *Var) const { 622 bool isTracked(const Variable *Var) const {
624 return Var->getIndex() < Metadata.size(); 623 return Var->getIndex() < Metadata.size();
625 } 624 }
626 625
627 /// Returns whether the given Variable has multiple definitions. 626 /// Returns whether the given Variable has multiple definitions.
628 bool isMultiDef(const Variable *Var) const; 627 bool isMultiDef(const Variable *Var) const;
629 /// Returns the first definition instruction of the given Variable. 628 /// Returns the first definition instruction of the given Variable. This is
630 /// This is only valid for variables whose definitions are all within 629 /// only valid for variables whose definitions are all within the same block,
631 /// the same block, e.g. T after the lowered sequence "T=B; T+=C; 630 /// e.g. T after the lowered sequence "T=B; T+=C; A=T", for which
632 /// A=T", for which getFirstDefinition(T) would return the "T=B" 631 /// getFirstDefinition(T) would return the "T=B" instruction. For variables
633 /// instruction. For variables with definitions span multiple 632 /// with definitions span multiple blocks, nullptr is returned.
634 /// blocks, nullptr is returned.
635 const Inst *getFirstDefinition(const Variable *Var) const; 633 const Inst *getFirstDefinition(const Variable *Var) const;
636 /// Returns the definition instruction of the given Variable, when 634 /// Returns the definition instruction of the given Variable, when
637 /// the variable has exactly one definition. Otherwise, nullptr is 635 /// the variable has exactly one definition. Otherwise, nullptr is
638 /// returned. 636 /// returned.
639 const Inst *getSingleDefinition(const Variable *Var) const; 637 const Inst *getSingleDefinition(const Variable *Var) const;
640 /// Returns the list of all definition instructions of the given 638 /// Returns the list of all definition instructions of the given Variable.
641 /// Variable.
642 const InstDefList &getLatterDefinitions(const Variable *Var) const; 639 const InstDefList &getLatterDefinitions(const Variable *Var) const;
643 640
644 /// Returns whether the given Variable is live across multiple 641 /// Returns whether the given Variable is live across multiple
645 /// blocks. Mainly, this is used to partition Variables into 642 /// blocks. Mainly, this is used to partition Variables into
646 /// single-block versus multi-block sets for leveraging sparsity in 643 /// single-block versus multi-block sets for leveraging sparsity in
647 /// liveness analysis, and for implementing simple stack slot 644 /// liveness analysis, and for implementing simple stack slot
648 /// coalescing. As a special case, function arguments are always 645 /// coalescing. As a special case, function arguments are always
649 /// considered multi-block because they are live coming into the 646 /// considered multi-block because they are live coming into the
650 /// entry block. 647 /// entry block.
651 bool isMultiBlock(const Variable *Var) const; 648 bool isMultiBlock(const Variable *Var) const;
652 /// Returns the node that the given Variable is used in, assuming 649 /// Returns the node that the given Variable is used in, assuming
653 /// isMultiBlock() returns false. Otherwise, nullptr is returned. 650 /// isMultiBlock() returns false. Otherwise, nullptr is returned.
654 CfgNode *getLocalUseNode(const Variable *Var) const; 651 CfgNode *getLocalUseNode(const Variable *Var) const;
655 652
653 /// Returns the total use weight computed as the sum of uses multiplied by a
654 /// loop nest depth facter for each use.
jvoung (off chromium) 2015/08/28 20:31:45 facter -> factor
ascull 2015/08/28 21:22:36 Done.
655 uint32_t getUseWeight(const Variable *Var) const;
656
656 private: 657 private:
657 const Cfg *Func; 658 const Cfg *Func;
658 MetadataKind Kind; 659 MetadataKind Kind;
659 std::vector<VariableTracking> Metadata; 660 std::vector<VariableTracking> Metadata;
660 const static InstDefList NoDefinitions; 661 const static InstDefList NoDefinitions;
661 }; 662 };
662 663
663 } // end of namespace Ice 664 } // end of namespace Ice
664 665
665 #endif // SUBZERO_SRC_ICEOPERAND_H 666 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698