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

Side by Side Diff: src/IceOperand.h

Issue 597003004: Subzero: Automatically infer regalloc preferences and overlap. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Code review changes Created 6 years, 2 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 | « src/IceInstX8632.def ('k') | src/IceOperand.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/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 // This file declares the Operand class and its target-independent 10 // This file declares the Operand class and its target-independent
(...skipping 367 matching lines...) Expand 10 before | Expand all | Expand 10 after
378 RegNum = NewRegNum; 378 RegNum = NewRegNum;
379 } 379 }
380 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; } 380 bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
381 int32_t getRegNumTmp() const { return RegNumTmp; } 381 int32_t getRegNumTmp() const { return RegNumTmp; }
382 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; } 382 void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
383 383
384 RegWeight getWeight() const { return Weight; } 384 RegWeight getWeight() const { return Weight; }
385 void setWeight(uint32_t NewWeight) { Weight = NewWeight; } 385 void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
386 void setWeightInfinite() { Weight = RegWeight::Inf; } 386 void setWeightInfinite() { Weight = RegWeight::Inf; }
387 387
388 Variable *getPreferredRegister() const { return RegisterPreference; }
389 bool getRegisterOverlap() const { return AllowRegisterOverlap; }
390 void setPreferredRegister(Variable *Prefer, bool Overlap) {
391 RegisterPreference = Prefer;
392 AllowRegisterOverlap = Overlap;
393 }
394
395 const LiveRange &getLiveRange() const { return Live; } 388 const LiveRange &getLiveRange() const { return Live; }
396 void setLiveRange(const LiveRange &Range) { Live = Range; } 389 void setLiveRange(const LiveRange &Range) { Live = Range; }
397 void resetLiveRange() { Live.reset(); } 390 void resetLiveRange() { Live.reset(); }
398 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) { 391 void addLiveRange(InstNumberT Start, InstNumberT End, uint32_t WeightDelta) {
399 assert(WeightDelta != RegWeight::Inf); 392 assert(WeightDelta != RegWeight::Inf);
400 Live.addSegment(Start, End); 393 Live.addSegment(Start, End);
401 if (Weight.isInf()) 394 if (Weight.isInf())
402 Live.setWeight(RegWeight::Inf); 395 Live.setWeight(RegWeight::Inf);
403 else 396 else
404 Live.addWeight(WeightDelta * Weight.getWeight()); 397 Live.addWeight(WeightDelta * Weight.getWeight());
405 } 398 }
406 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); } 399 void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
407 400
408 Variable *getLo() const { return LoVar; } 401 Variable *getLo() const { return LoVar; }
409 Variable *getHi() const { return HiVar; } 402 Variable *getHi() const { return HiVar; }
410 void setLoHi(Variable *Lo, Variable *Hi) { 403 void setLoHi(Variable *Lo, Variable *Hi) {
411 assert(LoVar == NULL); 404 assert(LoVar == NULL);
412 assert(HiVar == NULL); 405 assert(HiVar == NULL);
413 LoVar = Lo; 406 LoVar = Lo;
414 HiVar = Hi; 407 HiVar = Hi;
415 } 408 }
416 // Creates a temporary copy of the variable with a different type. 409 // Creates a temporary copy of the variable with a different type.
417 // Used primarily for syntactic correctness of textual assembly 410 // Used primarily for syntactic correctness of textual assembly
418 // emission. Note that only basic information is copied, in 411 // emission. Note that only basic information is copied, in
419 // particular not DefInst, IsArgument, Weight, RegisterPreference, 412 // particular not DefInst, IsArgument, Weight, LoVar, HiVar,
420 // AllowRegisterOverlap, LoVar, HiVar, VarsReal. 413 // VarsReal.
421 Variable asType(Type Ty); 414 Variable asType(Type Ty);
422 415
423 virtual void emit(const Cfg *Func) const; 416 virtual void emit(const Cfg *Func) const;
424 using Operand::dump; 417 using Operand::dump;
425 virtual void dump(const Cfg *Func, Ostream &Str) const; 418 virtual void dump(const Cfg *Func, Ostream &Str) const;
426 419
427 static bool classof(const Operand *Operand) { 420 static bool classof(const Operand *Operand) {
428 OperandKind Kind = Operand->getKind(); 421 OperandKind Kind = Operand->getKind();
429 return Kind >= kVariable && Kind <= kVariable_Num; 422 return Kind >= kVariable && Kind <= kVariable_Num;
430 } 423 }
431 424
432 // The destructor is public because of the asType() method. 425 // The destructor is public because of the asType() method.
433 virtual ~Variable() {} 426 virtual ~Variable() {}
434 427
435 protected: 428 protected:
436 Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name) 429 Variable(OperandKind K, Type Ty, SizeT Index, const IceString &Name)
437 : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false), 430 : Operand(K, Ty), Number(Index), Name(Name), IsArgument(false),
438 IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister), 431 IsImplicitArgument(false), StackOffset(0), RegNum(NoRegister),
439 RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL), 432 RegNumTmp(NoRegister), Weight(1), LoVar(NULL), HiVar(NULL) {
440 AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
441 Vars = VarsReal; 433 Vars = VarsReal;
442 Vars[0] = this; 434 Vars[0] = this;
443 NumVars = 1; 435 NumVars = 1;
444 } 436 }
445 // Number is unique across all variables, and is used as a 437 // Number is unique across all variables, and is used as a
446 // (bit)vector index for liveness analysis. 438 // (bit)vector index for liveness analysis.
447 const SizeT Number; 439 const SizeT Number;
448 // Name is optional. 440 // Name is optional.
449 IceString Name; 441 IceString Name;
450 bool IsArgument; 442 bool IsArgument;
451 bool IsImplicitArgument; 443 bool IsImplicitArgument;
452 // StackOffset is the canonical location on stack (only if 444 // StackOffset is the canonical location on stack (only if
453 // RegNum<0 || IsArgument). 445 // RegNum==NoRegister || IsArgument).
454 int32_t StackOffset; 446 int32_t StackOffset;
455 // RegNum is the allocated register, or NoRegister if it isn't 447 // RegNum is the allocated register, or NoRegister if it isn't
456 // register-allocated. 448 // register-allocated.
457 int32_t RegNum; 449 int32_t RegNum;
458 // RegNumTmp is the tentative assignment during register allocation. 450 // RegNumTmp is the tentative assignment during register allocation.
459 int32_t RegNumTmp; 451 int32_t RegNumTmp;
460 RegWeight Weight; // Register allocation priority 452 RegWeight Weight; // Register allocation priority
461 // RegisterPreference says that if possible, the register allocator
462 // should prefer the register that was assigned to this linked
463 // variable. It also allows a spill slot to share its stack
464 // location with another variable, if that variable does not get
465 // register-allocated and therefore has a stack location.
466 Variable *RegisterPreference;
467 // AllowRegisterOverlap says that it is OK to honor
468 // RegisterPreference and "share" a register even if the two live
469 // ranges overlap.
470 bool AllowRegisterOverlap;
471 LiveRange Live; 453 LiveRange Live;
472 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When 454 // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
473 // lowering from I64 to I32 on a 32-bit architecture, we split the 455 // lowering from I64 to I32 on a 32-bit architecture, we split the
474 // variable into two machine-size pieces. LoVar is the low-order 456 // variable into two machine-size pieces. LoVar is the low-order
475 // machine-size portion, and HiVar is the remaining high-order 457 // machine-size portion, and HiVar is the remaining high-order
476 // portion. TODO: It's wasteful to penalize all variables on all 458 // portion. TODO: It's wasteful to penalize all variables on all
477 // targets this way; use a sparser representation. It's also 459 // targets this way; use a sparser representation. It's also
478 // wasteful for a 64-bit target. 460 // wasteful for a 64-bit target.
479 Variable *LoVar; 461 Variable *LoVar;
480 Variable *HiVar; 462 Variable *HiVar;
481 // VarsReal (and Operand::Vars) are set up such that Vars[0] == 463 // VarsReal (and Operand::Vars) are set up such that Vars[0] ==
482 // this. 464 // this.
483 Variable *VarsReal[1]; 465 Variable *VarsReal[1];
484 }; 466 };
485 467
486 // VariableTracking tracks the metadata for a single variable. 468 typedef std::vector<const Inst *> InstDefList;
469
470 // VariableTracking tracks the metadata for a single variable. It is
471 // only meant to be used internally by VariablesMetadata.
487 class VariableTracking { 472 class VariableTracking {
488 public: 473 public:
489 enum MultiDefState { 474 enum MultiDefState {
490 // TODO(stichnot): Consider using just a simple counter. 475 // TODO(stichnot): Consider using just a simple counter.
491 MDS_Unknown, 476 MDS_Unknown,
492 MDS_SingleDef, 477 MDS_SingleDef,
493 MDS_MultiDef 478 MDS_MultiDefSingleBlock,
479 MDS_MultiDefMultiBlock
494 }; 480 };
495 enum MultiBlockState { 481 enum MultiBlockState {
496 MBS_Unknown, 482 MBS_Unknown,
497 MBS_SingleBlock, 483 MBS_SingleBlock,
498 MBS_MultiBlock 484 MBS_MultiBlock
499 }; 485 };
500 VariableTracking() 486 VariableTracking()
501 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL), 487 : MultiDef(MDS_Unknown), MultiBlock(MBS_Unknown), SingleUseNode(NULL),
502 SingleDefInst(NULL) {} 488 SingleDefNode(NULL) {}
503 MultiDefState getMultiDef() const { return MultiDef; } 489 MultiDefState getMultiDef() const { return MultiDef; }
504 MultiBlockState getMultiBlock() const { return MultiBlock; } 490 MultiBlockState getMultiBlock() const { return MultiBlock; }
505 const Inst *getDefinition() const { return SingleDefInst; } 491 const Inst *getFirstDefinition() const;
492 const Inst *getSingleDefinition() const;
493 const InstDefList &getDefinitions() const { return Definitions; }
506 const CfgNode *getNode() const { return SingleUseNode; } 494 const CfgNode *getNode() const { return SingleUseNode; }
507 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef, 495 void markUse(const Inst *Instr, const CfgNode *Node, bool IsFromDef,
508 bool IsImplicit); 496 bool IsImplicit);
509 void markDef(const Inst *Instr, const CfgNode *Node); 497 void markDef(const Inst *Instr, const CfgNode *Node);
510 498
511 private: 499 private:
512 VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION; 500 VariableTracking &operator=(const VariableTracking &) LLVM_DELETED_FUNCTION;
513 MultiDefState MultiDef; 501 MultiDefState MultiDef;
514 MultiBlockState MultiBlock; 502 MultiBlockState MultiBlock;
515 const CfgNode *SingleUseNode; 503 const CfgNode *SingleUseNode;
516 const Inst *SingleDefInst; 504 const CfgNode *SingleDefNode;
505 // All definitions of the variable are collected here, in the order
506 // encountered. Definitions in the same basic block are in
507 // instruction order, but there's no guarantee for the basic block
508 // order.
509 InstDefList Definitions;
517 }; 510 };
518 511
519 // VariablesMetadata analyzes and summarizes the metadata for the 512 // VariablesMetadata analyzes and summarizes the metadata for the
520 // complete set of Variables. 513 // complete set of Variables.
521 class VariablesMetadata { 514 class VariablesMetadata {
522 public: 515 public:
523 VariablesMetadata(const Cfg *Func) : Func(Func) {} 516 VariablesMetadata(const Cfg *Func) : Func(Func) {}
517 // Initialize the state by traversing all instructions/variables in
518 // the CFG.
524 void init(); 519 void init();
520 // Returns whether the given Variable is tracked in this object. It
521 // should only return false if changes were made to the CFG after
522 // running init(), in which case the state is stale and the results
523 // shouldn't be trusted (but it may be OK e.g. for dumping).
525 bool isTracked(const Variable *Var) const { 524 bool isTracked(const Variable *Var) const {
526 return Var->getIndex() < Metadata.size(); 525 return Var->getIndex() < Metadata.size();
527 } 526 }
527
528 // Returns whether the given Variable has multiple definitions.
528 bool isMultiDef(const Variable *Var) const; 529 bool isMultiDef(const Variable *Var) const;
529 const Inst *getDefinition(const Variable *Var) const; 530 // Returns the first definition instruction of the given Variable.
531 // This is only valid for variables whose definitions are all within
532 // the same block, e.g. T after the lowered sequence "T=B; T+=C;
533 // A=T", for which getFirstDefinition(T) would return the "T=B"
534 // instruction. For variables with definitions span multiple
535 // blocks, NULL is returned.
536 const Inst *getFirstDefinition(const Variable *Var) const;
537 // Returns the definition instruction of the given Variable, when
538 // the variable has exactly one definition. Otherwise, NULL is
539 // returned.
540 const Inst *getSingleDefinition(const Variable *Var) const;
541 // Returns the list of all definition instructions of the given
542 // Variable.
543 const InstDefList &getDefinitions(const Variable *Var) const;
544
545 // Returns whether the given Variable is live across multiple
546 // blocks. Mainly, this is used to partition Variables into
547 // single-block versus multi-block sets for leveraging sparsity in
548 // liveness analysis, and for implementing simple stack slot
549 // coalescing. As a special case, function arguments are always
550 // considered multi-block because they are live coming into the
551 // entry block.
530 bool isMultiBlock(const Variable *Var) const; 552 bool isMultiBlock(const Variable *Var) const;
553 // Returns the node that the given Variable is used in, assuming
554 // isMultiBlock() returns false. Otherwise, NULL is returned.
531 const CfgNode *getLocalUseNode(const Variable *Var) const; 555 const CfgNode *getLocalUseNode(const Variable *Var) const;
532 556
533 private: 557 private:
534 const Cfg *Func; 558 const Cfg *Func;
535 std::vector<VariableTracking> Metadata; 559 std::vector<VariableTracking> Metadata;
560 const static InstDefList NoDefinitions;
536 VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION; 561 VariablesMetadata(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
537 VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION; 562 VariablesMetadata &operator=(const VariablesMetadata &) LLVM_DELETED_FUNCTION;
538 }; 563 };
539 564
540 } // end of namespace Ice 565 } // end of namespace Ice
541 566
542 #endif // SUBZERO_SRC_ICEOPERAND_H 567 #endif // SUBZERO_SRC_ICEOPERAND_H
OLDNEW
« no previous file with comments | « src/IceInstX8632.def ('k') | src/IceOperand.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698