Chromium Code Reviews| Index: src/IceInst.h |
| diff --git a/src/IceInst.h b/src/IceInst.h |
| index db273aa500c7f17e8eadb38bae559aaabe9d7a8c..2e025a455dbade05be90d07a2d6eebfee249b47d 100644 |
| --- a/src/IceInst.h |
| +++ b/src/IceInst.h |
| @@ -135,6 +135,12 @@ public: |
| /// "var_dest=var_src" assignment where the dest and src are both variables. |
| virtual bool isVarAssign() const { return false; } |
| + /// Returns true if the instruction has a possible side effect of changing |
| + /// memory, in which case a memory load should not be reordered with respect |
| + /// to this instruction. We make it return true by default for safety when |
| + /// new ICE instructions are defined. |
| + virtual bool isMemoryWrite() const { return true; } |
|
John
2016/04/21 22:50:01
what's wrong with = 0, and forcing each new classe
Jim Stichnoth
2016/04/21 23:31:35
Done.
Jim Stichnoth
2016/04/21 23:32:41
Whoops, what I meant was, that would be nice excep
|
| + |
| void livenessLightweight(Cfg *Func, LivenessBV &Live); |
| /// Calculates liveness for this instruction. Returns true if this instruction |
| /// is (tentatively) still live and should be retained, and false if this |
| @@ -259,6 +265,7 @@ public: |
| Operand *getSizeInBytes() const { return getSrc(0); } |
| bool getKnownFrameOffset() const { return KnownFrameOffset; } |
| void setKnownFrameOffset() { KnownFrameOffset = true; } |
| + bool isMemoryWrite() const final { return false; } |
|
Eric Holk
2016/04/21 22:09:43
What's the reasoning for making these final?
John
2016/04/21 22:50:01
I tend to prefer using final for classes only. If
Jim Stichnoth
2016/04/21 22:50:28
We seem to do that quite regularly in Subzero so I
Jim Stichnoth
2016/04/21 23:31:35
Done.
|
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } |
| @@ -296,6 +303,7 @@ public: |
| static const char *getOpName(OpKind Op); |
| bool isCommutative() const; |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == Arithmetic; |
| @@ -323,6 +331,7 @@ public: |
| return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
| } |
| bool isVarAssign() const override; |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } |
| @@ -363,6 +372,7 @@ public: |
| NodeList getTerminatorEdges() const override; |
| bool isUnconditionalBranch() const override { return isUnconditional(); } |
| bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } |
| @@ -443,6 +453,7 @@ public: |
| InstCast(Func, CastKind, Dest, Source); |
| } |
| OpKind getCastKind() const { return CastKind; } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } |
| @@ -465,6 +476,7 @@ public: |
| InstExtractElement(Func, Dest, Source1, Source2); |
| } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == ExtractElement; |
| @@ -496,6 +508,7 @@ public: |
| InstFcmp(Func, Condition, Dest, Source1, Source2); |
| } |
| FCond getCondition() const { return Condition; } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } |
| @@ -527,6 +540,7 @@ public: |
| InstIcmp(Func, Condition, Dest, Source1, Source2); |
| } |
| ICond getCondition() const { return Condition; } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } |
| @@ -550,6 +564,7 @@ public: |
| InstInsertElement(Func, Dest, Source1, Source2, Source3); |
| } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == InsertElement; |
| @@ -579,6 +594,7 @@ public: |
| } |
| Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
| + bool isMemoryWrite() const final { return getIntrinsicInfo().IsMemoryWrite; } |
| private: |
| InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| @@ -604,6 +620,7 @@ public: |
| return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
| } |
| Operand *getSourceAddress() const { return getSrc(0); } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } |
| @@ -630,6 +647,7 @@ public: |
| void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
| Liveness *Liveness); |
| Inst *lower(Cfg *Func); |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } |
| @@ -664,6 +682,7 @@ public: |
| return getSrc(0); |
| } |
| NodeList getTerminatorEdges() const override { return NodeList(); } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } |
| @@ -686,6 +705,7 @@ public: |
| Operand *getCondition() const { return getSrc(0); } |
| Operand *getTrueOperand() const { return getSrc(1); } |
| Operand *getFalseOperand() const { return getSrc(2); } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } |
| @@ -745,6 +765,7 @@ public: |
| void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); |
| NodeList getTerminatorEdges() const override; |
| bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } |
| @@ -773,6 +794,7 @@ public: |
| return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
| } |
| NodeList getTerminatorEdges() const override { return NodeList(); } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == Unreachable; |
| @@ -797,6 +819,7 @@ public: |
| } |
| void emit(const Cfg *Func) const override; |
| void emitIAS(const Cfg * /* Func */) const override {} |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| Option getOption() const { return BundleOption; } |
| static bool classof(const Inst *Instr) { |
| @@ -820,6 +843,7 @@ public: |
| } |
| void emit(const Cfg *Func) const override; |
| void emitIAS(const Cfg * /* Func */) const override {} |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == BundleUnlock; |
| @@ -852,6 +876,7 @@ public: |
| } |
| void emit(const Cfg *Func) const override; |
| void emitIAS(const Cfg * /* Func */) const override {} |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } |
| @@ -877,6 +902,7 @@ public: |
| } |
| void emit(const Cfg *Func) const override; |
| void emitIAS(const Cfg * /* Func */) const override {} |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } |
| @@ -905,6 +931,7 @@ public: |
| const Inst *getLinked() const { return Linked; } |
| void emit(const Cfg *Func) const override; |
| void emitIAS(const Cfg * /* Func */) const override {} |
| + bool isMemoryWrite() const final { return false; } |
|
Eric Holk
2016/04/21 22:09:43
Since all the other instructions have isMemoryWrit
Jim Stichnoth
2016/04/21 22:50:28
Done.
|
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == FakeKill; |
| @@ -941,6 +968,7 @@ public: |
| assert(I < NumTargets); |
| return Targets[I]; |
| } |
| + bool isMemoryWrite() const final { return false; } |
| void dump(const Cfg *Func) const override; |
| static bool classof(const Inst *Instr) { |
| return Instr->getKind() == JumpTable; |