| Index: src/IceOperand.h
|
| diff --git a/src/IceOperand.h b/src/IceOperand.h
|
| index ef4413f874ff1720c3b9a1faf71941bb370cf282..39b53d6a7bb1af41d11c33a51c5b92ec0bc988c4 100644
|
| --- a/src/IceOperand.h
|
| +++ b/src/IceOperand.h
|
| @@ -81,8 +81,10 @@ private:
|
| class Constant : public Operand {
|
| public:
|
| uint32_t getPoolEntryID() const { return PoolEntryID; }
|
| - virtual void emit(const Cfg *Func) const = 0;
|
| - virtual void dump(const Cfg *Func) const = 0;
|
| + virtual void emit(const Cfg *Func) const { emit(Func->getContext()); }
|
| + virtual void dump(const Cfg *Func) const { dump(Func->getContext()); }
|
| + virtual void emit(GlobalContext *Ctx) const = 0;
|
| + virtual void dump(GlobalContext *Ctx) const = 0;
|
|
|
| static bool classof(const Operand *Operand) {
|
| OperandKind Kind = Operand->getKind();
|
| @@ -116,12 +118,14 @@ public:
|
| ConstantPrimitive(Ty, Value, PoolEntryID);
|
| }
|
| T getValue() const { return Value; }
|
| - virtual void emit(const Cfg *Func) const {
|
| - Ostream &Str = Func->getContext()->getStrEmit();
|
| + using Constant::emit;
|
| + virtual void emit(GlobalContext *Ctx) const {
|
| + Ostream &Str = Ctx->getStrEmit();
|
| Str << getValue();
|
| }
|
| - virtual void dump(const Cfg *Func) const {
|
| - Ostream &Str = Func->getContext()->getStrDump();
|
| + using Constant::dump;
|
| + virtual void dump(GlobalContext *Ctx) const {
|
| + Ostream &Str = Ctx->getStrDump();
|
| Str << getValue();
|
| }
|
|
|
| @@ -178,8 +182,10 @@ public:
|
| IceString getName() const { return Name; }
|
| void setSuppressMangling(bool Value) { SuppressMangling = Value; }
|
| bool getSuppressMangling() const { return SuppressMangling; }
|
| - virtual void emit(const Cfg *Func) const;
|
| - virtual void dump(const Cfg *Func) const;
|
| + using Constant::emit;
|
| + using Constant::dump;
|
| + virtual void emit(GlobalContext *Ctx) const;
|
| + virtual void dump(GlobalContext *Ctx) const;
|
|
|
| static bool classof(const Operand *Operand) {
|
| OperandKind Kind = Operand->getKind();
|
| @@ -228,6 +234,52 @@ bool operator<(const RegWeight &A, const RegWeight &B);
|
| bool operator<=(const RegWeight &A, const RegWeight &B);
|
| bool operator==(const RegWeight &A, const RegWeight &B);
|
|
|
| +// LiveRange is a set of instruction number intervals representing
|
| +// a variable's live range. Generally there is one interval per basic
|
| +// block where the variable is live, but adjacent intervals get
|
| +// coalesced into a single interval. LiveRange also includes a
|
| +// weight, in case e.g. we want a live range to have higher weight
|
| +// inside a loop.
|
| +class LiveRange {
|
| +public:
|
| + LiveRange() : Weight(0) {}
|
| +
|
| + void reset() {
|
| + Range.clear();
|
| + Weight.setWeight(0);
|
| + }
|
| + void addSegment(int32_t Start, int32_t End);
|
| +
|
| + bool endsBefore(const LiveRange &Other) const;
|
| + bool overlaps(const LiveRange &Other) const;
|
| + bool containsValue(int32_t Value) const;
|
| + bool isEmpty() const { return Range.empty(); }
|
| + int32_t getStart() const { return Range.empty() ? -1 : Range.begin()->first; }
|
| +
|
| + RegWeight getWeight() const { return Weight; }
|
| + void setWeight(const RegWeight &NewWeight) { Weight = NewWeight; }
|
| + void addWeight(uint32_t Delta) { Weight.addWeight(Delta); }
|
| + void dump(Ostream &Str) const;
|
| +
|
| + // Defining USE_SET uses std::set to hold the segments instead of
|
| + // std::list. Using std::list will be slightly faster, but is more
|
| + // restrictive because new segments cannot be added in the middle.
|
| +
|
| + //#define USE_SET
|
| +
|
| +private:
|
| + typedef std::pair<int32_t, int32_t> RangeElementType;
|
| +#ifdef USE_SET
|
| + typedef std::set<RangeElementType> RangeType;
|
| +#else
|
| + typedef std::list<RangeElementType> RangeType;
|
| +#endif
|
| + RangeType Range;
|
| + RegWeight Weight;
|
| +};
|
| +
|
| +Ostream &operator<<(Ostream &Str, const LiveRange &L);
|
| +
|
| // Variable represents an operand that is register-allocated or
|
| // stack-allocated. If it is register-allocated, it will ultimately
|
| // have a non-negative RegNum field.
|
| @@ -263,6 +315,9 @@ public:
|
| assert(!hasReg() || RegNum == NewRegNum);
|
| RegNum = NewRegNum;
|
| }
|
| + bool hasRegTmp() const { return getRegNumTmp() != NoRegister; }
|
| + int32_t getRegNumTmp() const { return RegNumTmp; }
|
| + void setRegNumTmp(int32_t NewRegNum) { RegNumTmp = NewRegNum; }
|
|
|
| RegWeight getWeight() const { return Weight; }
|
| void setWeight(uint32_t NewWeight) { Weight = NewWeight; }
|
| @@ -275,6 +330,19 @@ public:
|
| AllowRegisterOverlap = Overlap;
|
| }
|
|
|
| + const LiveRange &getLiveRange() const { return Live; }
|
| + void setLiveRange(const LiveRange &Range) { Live = Range; }
|
| + void resetLiveRange() { Live.reset(); }
|
| + void addLiveRange(int32_t Start, int32_t End, uint32_t WeightDelta) {
|
| + assert(WeightDelta != RegWeight::Inf);
|
| + Live.addSegment(Start, End);
|
| + if (Weight.isInf())
|
| + Live.setWeight(RegWeight::Inf);
|
| + else
|
| + Live.addWeight(WeightDelta * Weight.getWeight());
|
| + }
|
| + void setLiveRangeInfiniteWeight() { Live.setWeight(RegWeight::Inf); }
|
| +
|
| Variable *getLo() const { return LoVar; }
|
| Variable *getHi() const { return HiVar; }
|
| void setLoHi(Variable *Lo, Variable *Hi) {
|
| @@ -304,8 +372,8 @@ private:
|
| Variable(Type Ty, const CfgNode *Node, SizeT Index, const IceString &Name)
|
| : Operand(kVariable, Ty), Number(Index), Name(Name), DefInst(NULL),
|
| DefNode(Node), IsArgument(false), StackOffset(0), RegNum(NoRegister),
|
| - Weight(1), RegisterPreference(NULL), AllowRegisterOverlap(false),
|
| - LoVar(NULL), HiVar(NULL) {
|
| + RegNumTmp(NoRegister), Weight(1), RegisterPreference(NULL),
|
| + AllowRegisterOverlap(false), LoVar(NULL), HiVar(NULL) {
|
| Vars = VarsReal;
|
| Vars[0] = this;
|
| NumVars = 1;
|
| @@ -334,6 +402,8 @@ private:
|
| // RegNum is the allocated register, or NoRegister if it isn't
|
| // register-allocated.
|
| int32_t RegNum;
|
| + // RegNumTmp is the tentative assignment during register allocation.
|
| + int32_t RegNumTmp;
|
| RegWeight Weight; // Register allocation priority
|
| // RegisterPreference says that if possible, the register allocator
|
| // should prefer the register that was assigned to this linked
|
| @@ -345,6 +415,7 @@ private:
|
| // RegisterPreference and "share" a register even if the two live
|
| // ranges overlap.
|
| bool AllowRegisterOverlap;
|
| + LiveRange Live;
|
| // LoVar and HiVar are needed for lowering from 64 to 32 bits. When
|
| // lowering from I64 to I32 on a 32-bit architecture, we split the
|
| // variable into two machine-size pieces. LoVar is the low-order
|
|
|