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

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: Don't count a use if used as dest. 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 ShouldHaveRegister,
Jim Stichnoth 2015/08/27 05:03:06 I prefer to prefix enum values with some prefix, l
ascull 2015/08/28 19:26:36 Done.
413 MustHaveRegister,
414 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 {
458 void setWeight(uint32_t NewWeight) { Weight = RegWeight(NewWeight); } 455 return RegWeight(mustHaveReg() ? RegWeight::Inf : mustNotHaveReg()
459 void setWeightInfinite() { setWeight(RegWeight::Inf); } 456 ? RegWeight::Zero
457 : Weight);
458 }
459 void resetUses() { Weight = 0; }
460 void addUse(uint32_t UseWeight) { Weight += UseWeight; }
461
462 void setMustHaveReg() { RegRequirement = MustHaveRegister; }
463 bool mustHaveReg() const { return RegRequirement == MustHaveRegister; }
464 void setMustNotHaveReg() { RegRequirement = MustNotHaveRegister; }
465 bool mustNotHaveReg() const { return RegRequirement == MustNotHaveRegister; }
460 466
461 LiveRange &getLiveRange() { return Live; } 467 LiveRange &getLiveRange() { return Live; }
462 const LiveRange &getLiveRange() const { return Live; } 468 const LiveRange &getLiveRange() const { return Live; }
463 void setLiveRange(const LiveRange &Range) { Live = Range; } 469 void setLiveRange(const LiveRange &Range) { Live = Range; }
464 void resetLiveRange() { Live.reset(); } 470 void resetLiveRange() {
465 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { 471 Live.reset();
472 resetUses();
473 }
474 void addLiveRange(InstNumberT Start, InstNumberT End) {
466 assert(!getIgnoreLiveness()); 475 assert(!getIgnoreLiveness());
467 assert(WeightDelta != RegWeight::Inf);
468 Live.addSegment(Start, End); 476 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 } 477 }
477 void trimLiveRange(InstNumberT Start) { Live.trim(Start); } 478 void trimLiveRange(InstNumberT Start) { Live.trim(Start); }
478 void untrimLiveRange() { Live.untrim(); } 479 void untrimLiveRange() { Live.untrim(); }
479 bool rangeEndsBefore(const Variable *Other) const { 480 bool rangeEndsBefore(const Variable *Other) const {
480 return Live.endsBefore(Other->Live); 481 return Live.endsBefore(Other->Live);
481 } 482 }
482 bool rangeOverlaps(const Variable *Other) const { 483 bool rangeOverlaps(const Variable *Other) const {
483 const bool UseTrimmed = true; 484 const bool UseTrimmed = true;
484 return Live.overlaps(Other->Live, UseTrimmed); 485 return Live.overlaps(Other->Live, UseTrimmed);
485 } 486 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 /// reserved for the stack pointer. 534 /// reserved for the stack pointer.
534 bool IgnoreLiveness = false; 535 bool IgnoreLiveness = false;
535 /// StackOffset is the canonical location on stack (only if 536 /// StackOffset is the canonical location on stack (only if
536 /// RegNum==NoRegister || IsArgument). 537 /// RegNum==NoRegister || IsArgument).
537 int32_t StackOffset = 0; 538 int32_t StackOffset = 0;
538 /// RegNum is the allocated register, or NoRegister if it isn't 539 /// RegNum is the allocated register, or NoRegister if it isn't
539 /// register-allocated. 540 /// register-allocated.
540 int32_t RegNum = NoRegister; 541 int32_t RegNum = NoRegister;
541 /// RegNumTmp is the tentative assignment during register allocation. 542 /// RegNumTmp is the tentative assignment during register allocation.
542 int32_t RegNumTmp = NoRegister; 543 int32_t RegNumTmp = NoRegister;
543 RegWeight Weight = RegWeight(1); // Register allocation priority 544 /// \name Register allocation priority
545 /// @{
546 uint32_t Weight = 0; /// Calculated by use count and loop nest depth.
547 RegRequirement RegRequirement = ShouldHaveRegister;
548 /// @}
544 LiveRange Live; 549 LiveRange Live;
545 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 550 // 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 551 // 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 552 // variable into two machine-size pieces. LoVar is the low-order
548 // machine-size portion, and HiVar is the remaining high-order 553 // machine-size portion, and HiVar is the remaining high-order
549 // portion. TODO: It's wasteful to penalize all variables on all 554 // portion. TODO: It's wasteful to penalize all variables on all
550 // targets this way; use a sparser representation. It's also 555 // targets this way; use a sparser representation. It's also
551 // wasteful for a 64-bit target. 556 // wasteful for a 64-bit target.
552 Variable *LoVar = nullptr; 557 Variable *LoVar = nullptr;
553 Variable *HiVar = nullptr; 558 Variable *HiVar = nullptr;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
656 private: 661 private:
657 const Cfg *Func; 662 const Cfg *Func;
658 MetadataKind Kind; 663 MetadataKind Kind;
659 std::vector<VariableTracking> Metadata; 664 std::vector<VariableTracking> Metadata;
660 const static InstDefList NoDefinitions; 665 const static InstDefList NoDefinitions;
661 }; 666 };
662 667
663 } // end of namespace Ice 668 } // end of namespace Ice
664 669
665 #endif // SUBZERO_SRC_ICEOPERAND_H 670 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« src/IceInst.cpp ('K') | « src/IceLiveness.cpp ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698