| 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; }
|
|
|
|
|