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

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: 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; } 335 bool isInf() const { return Weight == Inf; }
jvoung (off chromium) 2015/08/26 21:45:46 It looks like the isInf() method isn't used anymor
ascull 2015/08/26 22:06:39 Done.
336 bool isZero() const { return Weight == Zero; } 336 bool isZero() const { return Weight == Zero; }
jvoung (off chromium) 2015/08/26 21:45:46 similar for isZero
ascull 2015/08/26 22:06:39 Done.
337 337
338 private: 338 private:
339 uint32_t Weight = 0; 339 uint32_t Weight = 0;
340 }; 340 };
341 Ostream &operator<<(Ostream &Str, const RegWeight &W); 341 Ostream &operator<<(Ostream &Str, const RegWeight &W);
342 bool operator<(const RegWeight &A, const RegWeight &B); 342 bool operator<(const RegWeight &A, const RegWeight &B);
343 bool operator<=(const RegWeight &A, const RegWeight &B); 343 bool operator<=(const RegWeight &A, const RegWeight &B);
344 bool operator==(const RegWeight &A, const RegWeight &B); 344 bool operator==(const RegWeight &A, const RegWeight &B);
345 345
346 enum RegRequirement {
jvoung (off chromium) 2015/08/26 21:45:47 Should this enum be scoped in RegWeight? (near the
ascull 2015/08/26 22:06:39 It is separate from RegWeight which is an 'infinit
347 ShouldHaveRegister,
348 MustHaveRegister,
349 MustNotHaveRegister,
350 };
351
346 /// LiveRange is a set of instruction number intervals representing 352 /// LiveRange is a set of instruction number intervals representing
347 /// a variable's live range. Generally there is one interval per basic 353 /// a variable's live range. Generally there is one interval per basic
348 /// block where the variable is live, but adjacent intervals get 354 /// block where the variable is live, but adjacent intervals get
349 /// coalesced into a single interval. LiveRange also includes a 355 /// coalesced into a single interval. LiveRange also includes a
350 /// weight, in case e.g. we want a live range to have higher weight 356 /// weight, in case e.g. we want a live range to have higher weight
jvoung (off chromium) 2015/08/26 21:45:46 LiveRange doesn't include the weight field anymore
ascull 2015/08/26 22:06:39 Yes, the weight is managed by the Variable which,
351 /// inside a loop. 357 /// inside a loop.
352 class LiveRange { 358 class LiveRange {
353 public: 359 public:
354 LiveRange() = default; 360 LiveRange() = default;
355 /// Special constructor for building a kill set. The advantage is 361 /// Special constructor for building a kill set. The advantage is
356 /// that we can reserve the right amount of space in advance. 362 /// that we can reserve the right amount of space in advance.
357 explicit LiveRange(const std::vector<InstNumberT> &Kills) { 363 explicit LiveRange(const std::vector<InstNumberT> &Kills) {
358 Range.reserve(Kills.size()); 364 Range.reserve(Kills.size());
359 for (InstNumberT I : Kills) 365 for (InstNumberT I : Kills)
360 addSegment(I, I); 366 addSegment(I, I);
361 } 367 }
362 LiveRange(const LiveRange &) = default; 368 LiveRange(const LiveRange &) = default;
363 LiveRange &operator=(const LiveRange &) = default; 369 LiveRange &operator=(const LiveRange &) = default;
364 370
365 void reset() { 371 void reset() {
366 Range.clear(); 372 Range.clear();
367 Weight.setWeight(0);
368 untrim(); 373 untrim();
369 } 374 }
370 void addSegment(InstNumberT Start, InstNumberT End); 375 void addSegment(InstNumberT Start, InstNumberT End);
371 376
372 bool endsBefore(const LiveRange &Other) const; 377 bool endsBefore(const LiveRange &Other) const;
373 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const; 378 bool overlaps(const LiveRange &Other, bool UseTrimmed = false) const;
374 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const; 379 bool overlapsInst(InstNumberT OtherBegin, bool UseTrimmed = false) const;
375 bool containsValue(InstNumberT Value, bool IsDest) const; 380 bool containsValue(InstNumberT Value, bool IsDest) const;
376 bool isEmpty() const { return Range.empty(); } 381 bool isEmpty() const { return Range.empty(); }
377 InstNumberT getStart() const { 382 InstNumberT getStart() const {
378 return Range.empty() ? -1 : Range.begin()->first; 383 return Range.empty() ? -1 : Range.begin()->first;
379 } 384 }
380 InstNumberT getEnd() const { 385 InstNumberT getEnd() const {
381 return Range.empty() ? -1 : Range.rbegin()->second; 386 return Range.empty() ? -1 : Range.rbegin()->second;
382 } 387 }
383 388
384 void untrim() { TrimmedBegin = Range.begin(); } 389 void untrim() { TrimmedBegin = Range.begin(); }
385 void trim(InstNumberT Lower); 390 void trim(InstNumberT Lower);
386 391
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; 392 void dump(Ostream &Str) const;
391 393
392 private: 394 private:
393 typedef std::pair<InstNumberT, InstNumberT> RangeElementType; 395 typedef std::pair<InstNumberT, InstNumberT> RangeElementType;
394 /// RangeType is arena-allocated from the Cfg's allocator. 396 /// RangeType is arena-allocated from the Cfg's allocator.
395 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>> 397 typedef std::vector<RangeElementType, CfgLocalAllocator<RangeElementType>>
396 RangeType; 398 RangeType;
397 RangeType Range; 399 RangeType Range;
398 RegWeight Weight = RegWeight(0);
399 /// TrimmedBegin is an optimization for the overlaps() computation. 400 /// TrimmedBegin is an optimization for the overlaps() computation.
400 /// Since the linear-scan algorithm always calls it as overlaps(Cur) 401 /// Since the linear-scan algorithm always calls it as overlaps(Cur)
401 /// and Cur advances monotonically according to live range start, we 402 /// and Cur advances monotonically according to live range start, we
402 /// can optimize overlaps() by ignoring all segments that end before 403 /// can optimize overlaps() by ignoring all segments that end before
403 /// the start of Cur's range. The linear-scan code enables this by 404 /// 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 405 /// calling trim() on the ranges of interest as Cur advances. Note
405 /// that linear-scan also has to initialize TrimmedBegin at the 406 /// that linear-scan also has to initialize TrimmedBegin at the
406 /// beginning by calling untrim(). 407 /// beginning by calling untrim().
407 RangeType::const_iterator TrimmedBegin; 408 RangeType::const_iterator TrimmedBegin;
408 }; 409 };
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 int32_t getRegNum() const { return RegNum; } 448 int32_t getRegNum() const { return RegNum; }
448 void setRegNum(int32_t NewRegNum) { 449 void setRegNum(int32_t NewRegNum) {
449 // Regnum shouldn't be set more than once. 450 // Regnum shouldn't be set more than once.
450 assert(!hasReg() || RegNum == NewRegNum); 451 assert(!hasReg() || RegNum == NewRegNum);
451 RegNum = NewRegNum; 452 RegNum = NewRegNum;
452 } 453 }
453 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } 454 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
454 int32_t getRegNumTmp() const { return RegNumTmp; } 455 int32_t getRegNumTmp() const { return RegNumTmp; }
455 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } 456 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
456 457
457 RegWeight getWeight() const { return Weight; } 458 RegWeight getWeight() const {
458 void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); } 459 return RegWeight(mustHaveReg() ? RegWeight::Inf : mustNotHaveReg()
459 void setWeightInfinite() { setWeight(RegWeight::Inf); } 460 ? RegWeight::Zero
461 : UseWeight);
462 }
463 void resetUses() { UseWeight = 0; }
464 void addUse(uint32_t Weight) { UseWeight += Weight; }
465
466 void setMustHaveReg() { RegRequirement = MustHaveRegister; }
467 bool mustHaveReg() const { return RegRequirement == MustHaveRegister; }
468 void setMustNotHaveReg() { RegRequirement = MustNotHaveRegister; }
469 bool mustNotHaveReg() const { return RegRequirement == MustNotHaveRegister; }
460 470
461 LiveRange &getLiveRange() { return Live; } 471 LiveRange &getLiveRange() { return Live; }
462 const LiveRange &getLiveRange() const { return Live; } 472 const LiveRange &getLiveRange() const { return Live; }
463 void setLiveRange(const LiveRange &Range) { Live = Range; } 473 void setLiveRange(const LiveRange &Range) { Live = Range; }
464 void resetLiveRange() { Live.reset(); } 474 void resetLiveRange() {
475 Live.reset();
476 resetUses();
477 }
465 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { 478 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
466 assert(!getIgnoreLiveness()); 479 assert(!getIgnoreLiveness());
467 assert(WeightDelta != RegWeight::Inf); 480 assert(WeightDelta != RegWeight::Inf);
jvoung (off chromium) 2015/08/26 21:45:46 WeightDelta is only used in assert builds now and
ascull 2015/08/26 22:06:39 Done.
468 Live.addSegment(Start, End); 481 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 } 482 }
477 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } 483 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
478 void untrimLiveRange() { Live.untrim(); } 484 void untrimLiveRange() { Live.untrim(); }
479 bool rangeEndsBefore(const Variable *Other) const { 485 bool rangeEndsBefore(const Variable *Other) const {
480 return Live.endsBefore(Other->Live); 486 return Live.endsBefore(Other->Live);
481 } 487 }
482 bool rangeOverlaps(const Variable *Other) const { 488 bool rangeOverlaps(const Variable *Other) const {
483 const bool UseTrimmed = true; 489 const bool UseTrimmed = true;
484 return Live.overlaps(Other->Live, UseTrimmed); 490 return Live.overlaps(Other->Live, UseTrimmed);
485 } 491 }
486 bool rangeOverlapsStart(const Variable *Other) const { 492 bool rangeOverlapsStart(const Variable *Other) const {
487 const bool UseTrimmed = true; 493 const bool UseTrimmed = true;
488 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed); 494 return Live.overlapsInst(Other->Live.getStart(), UseTrimmed);
489 } 495 }
490 496
491 Variable *getLo() const { return LoVar; } 497 Variable *getLo() const { return LoVar; }
492 Variable *getHi() const { return HiVar; } 498 Variable *getHi() const { return HiVar; }
493 void setLoHi(Variable *Lo, Variable *Hi) { 499 void setLoHi(Variable *Lo, Variable *Hi) {
494 assert(LoVar == nullptr); 500 assert(LoVar == nullptr);
495 assert(HiVar == nullptr); 501 assert(HiVar == nullptr);
496 LoVar = Lo; 502 LoVar = Lo;
497 HiVar = Hi; 503 HiVar = Hi;
498 } 504 }
499 /// Creates a temporary copy of the variable with a different type. 505 /// Creates a temporary copy of the variable with a different type.
500 /// Used primarily for syntactic correctness of textual assembly 506 /// Used primarily for syntactic correctness of textual assembly
501 /// emission. Note that only basic information is copied, in 507 /// emission. Note that only basic information is copied, in
502 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness, 508 /// particular not IsArgument, IsImplicitArgument, IgnoreLiveness,
503 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal. 509 /// RegNumTmp, Weight, Live, LoVar, HiVar, VarsReal.
jvoung (off chromium) 2015/08/26 21:45:46 Weight -> UseWeight ?
ascull 2015/08/26 22:06:39 UseWeight -> Weight. Missed this refactor.
504 Variable *asType(Type Ty); 510 Variable *asType(Type Ty);
505 511
506 void emit(const Cfg *Func) const override; 512 void emit(const Cfg *Func) const override;
507 using Operand::dump; 513 using Operand::dump;
508 void dump(const Cfg *Func, Ostream &Str) const override; 514 void dump(const Cfg *Func, Ostream &Str) const override;
509 515
510 /// Return reg num of base register, if different from stack/frame register. 516 /// Return reg num of base register, if different from stack/frame register.
511 virtual int32_t getBaseRegNum() const { return NoRegister; } 517 virtual int32_t getBaseRegNum() const { return NoRegister; }
512 518
513 static bool classof(const Operand *Operand) { 519 static bool classof(const Operand *Operand) {
(...skipping 19 matching lines...) Expand all
533 /// reserved for the stack pointer. 539 /// reserved for the stack pointer.
534 bool IgnoreLiveness = false; 540 bool IgnoreLiveness = false;
535 /// StackOffset is the canonical location on stack (only if 541 /// StackOffset is the canonical location on stack (only if
536 /// RegNum==NoRegister || IsArgument). 542 /// RegNum==NoRegister || IsArgument).
537 int32_t StackOffset = 0; 543 int32_t StackOffset = 0;
538 /// RegNum is the allocated register, or NoRegister if it isn't 544 /// RegNum is the allocated register, or NoRegister if it isn't
539 /// register-allocated. 545 /// register-allocated.
540 int32_t RegNum = NoRegister; 546 int32_t RegNum = NoRegister;
541 /// RegNumTmp is the tentative assignment during register allocation. 547 /// RegNumTmp is the tentative assignment during register allocation.
542 int32_t RegNumTmp = NoRegister; 548 int32_t RegNumTmp = NoRegister;
543 RegWeight Weight = RegWeight(1); // Register allocation priority 549 /// \name Register allocation priority
550 /// @{
551 uint32_t UseWeight = 0; /// Calculated by use count and loop nest depth.
552 RegRequirement RegRequirement = ShouldHaveRegister;
553 /// @}
544 LiveRange Live; 554 LiveRange Live;
545 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 555 // 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 556 // 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 557 // variable into two machine-size pieces. LoVar is the low-order
548 // machine-size portion, and HiVar is the remaining high-order 558 // machine-size portion, and HiVar is the remaining high-order
549 // portion. TODO: It's wasteful to penalize all variables on all 559 // portion. TODO: It's wasteful to penalize all variables on all
550 // targets this way; use a sparser representation. It's also 560 // targets this way; use a sparser representation. It's also
551 // wasteful for a 64-bit target. 561 // wasteful for a 64-bit target.
552 Variable *LoVar = nullptr; 562 Variable *LoVar = nullptr;
553 Variable *HiVar = nullptr; 563 Variable *HiVar = nullptr;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 private: 666 private:
657 const Cfg *Func; 667 const Cfg *Func;
658 MetadataKind Kind; 668 MetadataKind Kind;
659 std::vector<VariableTracking> Metadata; 669 std::vector<VariableTracking> Metadata;
660 const static InstDefList NoDefinitions; 670 const static InstDefList NoDefinitions;
661 }; 671 };
662 672
663 } // end of namespace Ice 673 } // end of namespace Ice
664 674
665 #endif // SUBZERO_SRC_ICEOPERAND_H 675 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698