Chromium Code Reviews| Index: src/IceInst.h |
| diff --git a/src/IceInst.h b/src/IceInst.h |
| index 57f8b9e98d0f64fdcdcb1d311479002cf6b92f8f..195604b99793f6175e26b63bc5d50d76b234bbee 100644 |
| --- a/src/IceInst.h |
| +++ b/src/IceInst.h |
| @@ -47,7 +47,12 @@ public: |
| Ret, |
| Select, |
| Store, |
| - Switch |
| + Switch, |
| + FakeDef, // not part of LLVM/PNaCl bitcode |
| + FakeUse, // not part of LLVM/PNaCl bitcode |
| + FakeKill, // not part of LLVM/PNaCl bitcode |
| + Target // target-specific low-level ICE |
| + // Anything >= Target is an InstTarget subclass. |
| }; |
| InstKind getKind() const { return Kind; } |
| @@ -83,10 +88,13 @@ public: |
| // basic blocks, i.e. used in a different block from their definition. |
| void updateVars(CfgNode *Node); |
| + virtual void emit(const Cfg *Func) const; |
| virtual void dump(const Cfg *Func) const; |
| void dumpDecorated(const Cfg *Func) const; |
| + void emitSources(const Cfg *Func) const; |
| void dumpSources(const Cfg *Func) const; |
| void dumpDest(const Cfg *Func) const; |
| + virtual bool isRedundantAssign() const { return false; } |
| virtual ~Inst() {} |
| @@ -154,6 +162,7 @@ public: |
| ICEINSTARITHMETIC_TABLE |
| #undef X |
| }; |
| + |
| static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, |
| Operand *Source1, Operand *Source2) { |
| return new (Func->allocateInst<InstArithmetic>()) |
| @@ -279,6 +288,7 @@ public: |
| ICEINSTCAST_TABLE |
| #undef X |
| }; |
| + |
| static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
| Operand *Source) { |
| return new (Func->allocateInst<InstCast>()) |
| @@ -305,6 +315,7 @@ public: |
| ICEINSTFCMP_TABLE |
| #undef X |
| }; |
| + |
| static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
| Operand *Source1, Operand *Source2) { |
| return new (Func->allocateInst<InstFcmp>()) |
| @@ -331,7 +342,9 @@ public: |
| #define X(tag, str) tag, |
| ICEINSTICMP_TABLE |
| #undef X |
| + None // not part of LLVM; used for unconditional branch |
|
JF
2014/05/04 23:54:58
Isn't that True?
Jim Stichnoth
2014/05/05 07:03:55
Weird, I don't know why this was there. :) It's g
|
| }; |
| + |
| static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
| Operand *Source1, Operand *Source2) { |
| return new (Func->allocateInst<InstIcmp>()) |
| @@ -376,6 +389,8 @@ public: |
| return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
| } |
| void addArgument(Operand *Source, CfgNode *Label); |
| + Operand *getOperandForTarget(CfgNode *Target) const; |
| + Inst *lower(Cfg *Func, CfgNode *Node); |
| virtual void dump(const Cfg *Func) const; |
| static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } |
| @@ -522,6 +537,104 @@ private: |
| virtual ~InstUnreachable() {} |
| }; |
| +// FakeDef instruction. This creates a fake definition of a variable, |
| +// which is how we represent the case when an instruction produces |
| +// multiple results. This doesn't happen with high-level ICE |
| +// instructions, but might with lowered instructions. For example, |
| +// this would be a way to represent condition flags being modified by |
| +// an instruction. |
| +// |
| +// It's generally useful to set the optional source operand to be the |
| +// dest variable of the instruction that actually produces the FakeDef |
| +// dest. Otherwise, the original instruction could be dead-code |
| +// eliminated if its dest operand is unused, and therefore the FakeDef |
| +// dest wouldn't be properly initialized. |
| +class InstFakeDef : public Inst { |
| +public: |
| + static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { |
| + return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
| + } |
| + virtual void emit(const Cfg *Func) const; |
| + virtual void dump(const Cfg *Func) const; |
| + static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
| + |
| +private: |
| + InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
| + InstFakeDef(const InstFakeDef &) LLVM_DELETED_FUNCTION; |
| + InstFakeDef &operator=(const InstFakeDef &) LLVM_DELETED_FUNCTION; |
| + virtual ~InstFakeDef() {} |
| +}; |
| + |
| +// FakeUse instruction. This creates a fake use of a variable, to |
| +// keep the instruction that produces that variable from being |
| +// dead-code eliminated. This is useful in a variety of lowering |
| +// situations. The FakeUse instruction has no dest, so it can itself |
| +// never be dead-code eliminated. |
| +class InstFakeUse : public Inst { |
| +public: |
| + static InstFakeUse *create(Cfg *Func, Variable *Src) { |
| + return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); |
| + } |
| + virtual void emit(const Cfg *Func) const; |
| + virtual void dump(const Cfg *Func) const; |
| + static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
| + |
| +private: |
| + InstFakeUse(Cfg *Func, Variable *Src); |
| + InstFakeUse(const InstFakeUse &) LLVM_DELETED_FUNCTION; |
| + InstFakeUse &operator=(const InstFakeUse &) LLVM_DELETED_FUNCTION; |
| + virtual ~InstFakeUse() {} |
| +}; |
| + |
| +// FakeKill instruction. This "kills" a set of variables by adding a |
| +// trivial live range at this instruction to each variable. The |
| +// primary use is to indicate that scratch registers are killed after |
| +// a call, so that the register allocator won't assign a scratch |
| +// register to a variable whose live range spans a call. |
| +// |
| +// The FakeKill instruction also holds a pointer to the instruction |
| +// that kills the set of variables, so that if that linked instruction |
| +// gets dead-code eliminated, the FakeKill instruction will as well. |
| +class InstFakeKill : public Inst { |
| +public: |
| + static InstFakeKill *create(Cfg *Func, const VarList &KilledRegs, |
| + const Inst *Linked) { |
| + return new (Func->allocateInst<InstFakeKill>()) |
| + InstFakeKill(Func, KilledRegs, Linked); |
| + } |
| + const Inst *getLinked() const { return Linked; } |
| + virtual void emit(const Cfg *Func) const; |
| + virtual void dump(const Cfg *Func) const; |
| + static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
| + |
| +private: |
| + InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked); |
| + InstFakeKill(const InstFakeKill &) LLVM_DELETED_FUNCTION; |
| + InstFakeKill &operator=(const InstFakeKill &) LLVM_DELETED_FUNCTION; |
| + virtual ~InstFakeKill() {} |
| + |
| + // This instruction is ignored if Linked->isDeleted() is true. |
| + const Inst *Linked; |
| +}; |
| + |
| +// The Target instruction is the base class for all target-specific |
| +// instructions. |
| +class InstTarget : public Inst { |
| +public: |
| + virtual void emit(const Cfg *Func) const = 0; |
| + virtual void dump(const Cfg *Func) const; |
| + static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
| + |
| +protected: |
| + InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| + : Inst(Func, Kind, MaxSrcs, Dest) { |
| + assert(Kind >= Target); |
| + } |
| + InstTarget(const InstTarget &) LLVM_DELETED_FUNCTION; |
| + InstTarget &operator=(const InstTarget &) LLVM_DELETED_FUNCTION; |
| + virtual ~InstTarget() {} |
| +}; |
| + |
| } // end of namespace Ice |
| #endif // SUBZERO_SRC_ICEINST_H |