Index: src/IceInst.h |
diff --git a/src/IceInst.h b/src/IceInst.h |
index db273aa500c7f17e8eadb38bae559aaabe9d7a8c..0ce267ff07793fe334de3183eb0f5ae8c81f9047 100644 |
--- a/src/IceInst.h |
+++ b/src/IceInst.h |
@@ -135,6 +135,13 @@ 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. It should really be pure virtual, but we can't |
+ /// because of g++ and llvm::ilist<>, so we implement it as |
+ /// report_fatal_error(). |
+ virtual bool isMemoryWrite() const; |
+ |
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 +266,7 @@ public: |
Operand *getSizeInBytes() const { return getSrc(0); } |
bool getKnownFrameOffset() const { return KnownFrameOffset; } |
void setKnownFrameOffset() { KnownFrameOffset = true; } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Alloca; } |
@@ -296,6 +304,7 @@ public: |
static const char *getOpName(OpKind Op); |
bool isCommutative() const; |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == Arithmetic; |
@@ -323,6 +332,7 @@ public: |
return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
} |
bool isVarAssign() const override; |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Assign; } |
@@ -363,6 +373,7 @@ public: |
NodeList getTerminatorEdges() const override; |
bool isUnconditionalBranch() const override { return isUnconditional(); } |
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Br; } |
@@ -402,6 +413,7 @@ public: |
SizeT getNumArgs() const { return getSrcSize() - 1; } |
bool isTailcall() const { return HasTailCall; } |
bool isTargetHelperCall() const { return IsTargetHelperCall; } |
+ bool isMemoryWrite() const override { return true; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Call; } |
Type getReturnType() const; |
@@ -443,6 +455,7 @@ public: |
InstCast(Func, CastKind, Dest, Source); |
} |
OpKind getCastKind() const { return CastKind; } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Cast; } |
@@ -465,6 +478,7 @@ public: |
InstExtractElement(Func, Dest, Source1, Source2); |
} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == ExtractElement; |
@@ -496,6 +510,7 @@ public: |
InstFcmp(Func, Condition, Dest, Source1, Source2); |
} |
FCond getCondition() const { return Condition; } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Fcmp; } |
@@ -527,6 +542,7 @@ public: |
InstIcmp(Func, Condition, Dest, Source1, Source2); |
} |
ICond getCondition() const { return Condition; } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Icmp; } |
@@ -550,6 +566,7 @@ public: |
InstInsertElement(Func, Dest, Source1, Source2, Source3); |
} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == InsertElement; |
@@ -579,6 +596,9 @@ public: |
} |
Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
+ bool isMemoryWrite() const override { |
+ return getIntrinsicInfo().IsMemoryWrite; |
+ } |
private: |
InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
@@ -604,6 +624,7 @@ public: |
return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
} |
Operand *getSourceAddress() const { return getSrc(0); } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Load; } |
@@ -630,6 +651,7 @@ public: |
void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
Liveness *Liveness); |
Inst *lower(Cfg *Func); |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Phi; } |
@@ -664,6 +686,7 @@ public: |
return getSrc(0); |
} |
NodeList getTerminatorEdges() const override { return NodeList(); } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Ret; } |
@@ -686,6 +709,7 @@ public: |
Operand *getCondition() const { return getSrc(0); } |
Operand *getTrueOperand() const { return getSrc(1); } |
Operand *getFalseOperand() const { return getSrc(2); } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Select; } |
@@ -712,6 +736,7 @@ public: |
Operand *getData() const { return getSrc(0); } |
Variable *getRmwBeacon() const; |
void setRmwBeacon(Variable *Beacon); |
+ bool isMemoryWrite() const override { return true; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Store; } |
@@ -745,6 +770,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 override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == Switch; } |
@@ -773,6 +799,7 @@ public: |
return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
} |
NodeList getTerminatorEdges() const override { return NodeList(); } |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == Unreachable; |
@@ -797,6 +824,7 @@ public: |
} |
void emit(const Cfg *Func) const override; |
void emitIAS(const Cfg * /* Func */) const override {} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
Option getOption() const { return BundleOption; } |
static bool classof(const Inst *Instr) { |
@@ -820,6 +848,7 @@ public: |
} |
void emit(const Cfg *Func) const override; |
void emitIAS(const Cfg * /* Func */) const override {} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == BundleUnlock; |
@@ -852,6 +881,7 @@ public: |
} |
void emit(const Cfg *Func) const override; |
void emitIAS(const Cfg * /* Func */) const override {} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == FakeDef; } |
@@ -877,6 +907,7 @@ public: |
} |
void emit(const Cfg *Func) const override; |
void emitIAS(const Cfg * /* Func */) const override {} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() == FakeUse; } |
@@ -905,6 +936,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 override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == FakeKill; |
@@ -941,6 +973,7 @@ public: |
assert(I < NumTargets); |
return Targets[I]; |
} |
+ bool isMemoryWrite() const override { return false; } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { |
return Instr->getKind() == JumpTable; |
@@ -988,7 +1021,8 @@ public: |
InstBreakpoint(const InstBreakpoint &) = delete; |
InstBreakpoint &operator=(const InstBreakpoint &) = delete; |
- InstBreakpoint(Cfg *Func); |
+ explicit InstBreakpoint(Cfg *Func); |
+ bool isMemoryWrite() const override { return false; } |
public: |
static InstBreakpoint *create(Cfg *Func) { |
@@ -1009,6 +1043,9 @@ class InstTarget : public Inst { |
public: |
uint32_t getEmitInstCount() const override { return 1; } |
+ bool isMemoryWrite() const override { |
+ return true; // conservative answer |
+ } |
void dump(const Cfg *Func) const override; |
static bool classof(const Inst *Instr) { return Instr->getKind() >= Target; } |