Commit e58178ab by Matt Wala

Subzero: Factor our commonalities between mov-like instructions.

Introduce a base class for mov, movq, and movp instruction classes. BUG=none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/466733005
parent 105b7044
...@@ -219,16 +219,6 @@ InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem) ...@@ -219,16 +219,6 @@ InstX8632Store::InstX8632Store(Cfg *Func, Operand *Value, OperandX8632 *Mem)
addSource(Mem); addSource(Mem);
} }
InstX8632Mov::InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, InstX8632::Mov, 1, Dest) {
addSource(Source);
}
InstX8632Movp::InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, InstX8632::Movp, 1, Dest) {
addSource(Source);
}
InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem) InstX8632StoreP::InstX8632StoreP(Cfg *Func, Operand *Value, OperandX8632 *Mem)
: InstX8632(Func, InstX8632::StoreP, 2, NULL) { : InstX8632(Func, InstX8632::StoreP, 2, NULL) {
addSource(Value); addSource(Value);
...@@ -241,11 +231,6 @@ InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem) ...@@ -241,11 +231,6 @@ InstX8632StoreQ::InstX8632StoreQ(Cfg *Func, Operand *Value, OperandX8632 *Mem)
addSource(Mem); addSource(Mem);
} }
InstX8632Movq::InstX8632Movq(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, InstX8632::Movq, 1, Dest) {
addSource(Source);
}
InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source) InstX8632Movsx::InstX8632Movsx(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, InstX8632::Movsx, 1, Dest) { : InstX8632(Func, InstX8632::Movsx, 1, Dest) {
addSource(Source); addSource(Source);
...@@ -274,51 +259,6 @@ InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source, ...@@ -274,51 +259,6 @@ InstX8632Push::InstX8632Push(Cfg *Func, Operand *Source,
addSource(Source); addSource(Source);
} }
bool InstX8632Mov::isRedundantAssign() const {
// TODO(stichnot): The isRedundantAssign() implementations for
// InstX8632Mov, InstX8632Movp, and InstX8632Movq are
// identical. Consolidate them.
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL)
return false;
if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
// TODO: On x86-64, instructions like "mov eax, eax" are used to
// clear the upper 32 bits of rax. We need to recognize and
// preserve these.
return true;
}
if (!getDest()->hasReg() && !Src->hasReg() &&
Dest->getStackOffset() == Src->getStackOffset())
return true;
return false;
}
bool InstX8632Movp::isRedundantAssign() const {
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL)
return false;
if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
return true;
}
if (!getDest()->hasReg() && !Src->hasReg() &&
Dest->getStackOffset() == Src->getStackOffset())
return true;
return false;
}
bool InstX8632Movq::isRedundantAssign() const {
Variable *Src = llvm::dyn_cast<Variable>(getSrc(0));
if (Src == NULL)
return false;
if (getDest()->hasReg() && getDest()->getRegNum() == Src->getRegNum()) {
return true;
}
if (!getDest()->hasReg() && !Src->hasReg() &&
Dest->getStackOffset() == Src->getStackOffset())
return true;
return false;
}
InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source) InstX8632Ret::InstX8632Ret(Cfg *Func, Variable *Source)
: InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) { : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) {
if (Source) if (Source)
...@@ -446,6 +386,21 @@ void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func, ...@@ -446,6 +386,21 @@ void emitTwoAddress(const char *Opcode, const Inst *Inst, const Cfg *Func,
Str << "\n"; Str << "\n";
} }
bool checkForRedundantAssign(const Variable *Dest, const Operand *Source) {
const Variable *Src = llvm::dyn_cast<const Variable>(Source);
if (Src == NULL)
return false;
if (Dest->hasReg() && Dest->getRegNum() == Src->getRegNum()) {
// TODO: On x86-64, instructions like "mov eax, eax" are used to
// clear the upper 32 bits of rax. We need to recognize and
// preserve these.
return true;
}
if (!Dest->hasReg() && !Src->hasReg() &&
Dest->getStackOffset() == Src->getStackOffset())
return true;
return false;
}
// In-place ops // In-place ops
template <> const char *InstX8632Bswap::Opcode = "bswap"; template <> const char *InstX8632Bswap::Opcode = "bswap";
...@@ -457,6 +412,10 @@ template <> const char *InstX8632Lea::Opcode = "lea"; ...@@ -457,6 +412,10 @@ template <> const char *InstX8632Lea::Opcode = "lea";
template <> const char *InstX8632Movd::Opcode = "movd"; template <> const char *InstX8632Movd::Opcode = "movd";
template <> const char *InstX8632Sqrtss::Opcode = "sqrtss"; template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq"; template <> const char *InstX8632Cbwdq::Opcode = "cbw/cwd/cdq";
// Mov-like ops
template <> const char *InstX8632Mov::Opcode = "mov";
template <> const char *InstX8632Movp::Opcode = "movups";
template <> const char *InstX8632Movq::Opcode = "movq";
// Binary ops // Binary ops
template <> const char *InstX8632Add::Opcode = "add"; template <> const char *InstX8632Add::Opcode = "add";
template <> const char *InstX8632Addps::Opcode = "addps"; template <> const char *InstX8632Addps::Opcode = "addps";
...@@ -999,7 +958,7 @@ template <> void InstX8632Lea::emit(const Cfg *Func) const { ...@@ -999,7 +958,7 @@ template <> void InstX8632Lea::emit(const Cfg *Func) const {
Str << "\n"; Str << "\n";
} }
void InstX8632Mov::emit(const Cfg *Func) const { template <> void InstX8632Mov::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
Operand *Src = getSrc(0); Operand *Src = getSrc(0);
...@@ -1035,15 +994,7 @@ void InstX8632Mov::emit(const Cfg *Func) const { ...@@ -1035,15 +994,7 @@ void InstX8632Mov::emit(const Cfg *Func) const {
Str << "\n"; Str << "\n";
} }
void InstX8632Mov::dump(const Cfg *Func) const { template <> void InstX8632Movp::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "mov." << getDest()->getType() << " ";
dumpDest(Func);
Str << ", ";
dumpSources(Func);
}
void InstX8632Movp::emit(const Cfg *Func) const {
// TODO(wala,stichnot): movups works with all vector operands, but // TODO(wala,stichnot): movups works with all vector operands, but
// there exist other instructions (movaps, movdqa, movdqu) that may // there exist other instructions (movaps, movdqa, movdqu) that may
// perform better, depending on the data type and alignment of the // perform better, depending on the data type and alignment of the
...@@ -1057,15 +1008,7 @@ void InstX8632Movp::emit(const Cfg *Func) const { ...@@ -1057,15 +1008,7 @@ void InstX8632Movp::emit(const Cfg *Func) const {
Str << "\n"; Str << "\n";
} }
void InstX8632Movp::dump(const Cfg *Func) const { template <> void InstX8632Movq::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "movups." << getDest()->getType() << " ";
dumpDest(Func);
Str << ", ";
dumpSources(Func);
}
void InstX8632Movq::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
assert(getDest()->getType() == IceType_i64 || assert(getDest()->getType() == IceType_i64 ||
...@@ -1077,14 +1020,6 @@ void InstX8632Movq::emit(const Cfg *Func) const { ...@@ -1077,14 +1020,6 @@ void InstX8632Movq::emit(const Cfg *Func) const {
Str << "\n"; Str << "\n";
} }
void InstX8632Movq::dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << "movq." << getDest()->getType() << " ";
dumpDest(Func);
Str << ", ";
dumpSources(Func);
}
void InstX8632Movsx::emit(const Cfg *Func) const { void InstX8632Movsx::emit(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrEmit(); Ostream &Str = Func->getContext()->getStrEmit();
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
......
...@@ -571,6 +571,41 @@ private: ...@@ -571,6 +571,41 @@ private:
static const char *Opcode; static const char *Opcode;
}; };
bool checkForRedundantAssign(const Variable *Dest, const Operand *Source);
// Base class for assignment instructions
template <InstX8632::InstKindX8632 K>
class InstX8632Movlike : public InstX8632 {
public:
static InstX8632Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632Movlike>())
InstX8632Movlike(Func, Dest, Source);
}
virtual bool isRedundantAssign() const {
return checkForRedundantAssign(getDest(), getSrc(0));
}
virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const {
Ostream &Str = Func->getContext()->getStrDump();
Str << Opcode << "." << getDest()->getType() << " ";
dumpDest(Func);
Str << ", ";
dumpSources(Func);
}
static bool classof(const Inst *Inst) { return isClassof(Inst, K); }
private:
InstX8632Movlike(Cfg *Func, Variable *Dest, Operand *Source)
: InstX8632(Func, K, 1, Dest) {
addSource(Source);
}
InstX8632Movlike(const InstX8632Movlike &) LLVM_DELETED_FUNCTION;
InstX8632Movlike &operator=(const InstX8632Movlike &) LLVM_DELETED_FUNCTION;
virtual ~InstX8632Movlike() {}
static const char *Opcode;
};
typedef InstX8632Inplaceop<InstX8632::Bswap> InstX8632Bswap; typedef InstX8632Inplaceop<InstX8632::Bswap> InstX8632Bswap;
typedef InstX8632Inplaceop<InstX8632::Neg> InstX8632Neg; typedef InstX8632Inplaceop<InstX8632::Neg> InstX8632Neg;
typedef InstX8632Unaryop<InstX8632::Bsf> InstX8632Bsf; typedef InstX8632Unaryop<InstX8632::Bsf> InstX8632Bsf;
...@@ -580,6 +615,13 @@ typedef InstX8632Unaryop<InstX8632::Movd> InstX8632Movd; ...@@ -580,6 +615,13 @@ typedef InstX8632Unaryop<InstX8632::Movd> InstX8632Movd;
typedef InstX8632Unaryop<InstX8632::Sqrtss> InstX8632Sqrtss; typedef InstX8632Unaryop<InstX8632::Sqrtss> InstX8632Sqrtss;
// Cbwdq instruction - wrapper for cbw, cwd, and cdq // Cbwdq instruction - wrapper for cbw, cwd, and cdq
typedef InstX8632Unaryop<InstX8632::Cbwdq> InstX8632Cbwdq; typedef InstX8632Unaryop<InstX8632::Cbwdq> InstX8632Cbwdq;
// Move/assignment instruction - wrapper for mov/movss/movsd.
typedef InstX8632Movlike<InstX8632::Mov> InstX8632Mov;
// Move packed - copy 128 bit values between XMM registers, or mem128
// and XMM registers.
typedef InstX8632Movlike<InstX8632::Movp> InstX8632Movp;
// Movq - copy between XMM registers, or mem64 and XMM registers.
typedef InstX8632Movlike<InstX8632::Movq> InstX8632Movq;
typedef InstX8632Binop<InstX8632::Add> InstX8632Add; typedef InstX8632Binop<InstX8632::Add> InstX8632Add;
typedef InstX8632Binop<InstX8632::Addps> InstX8632Addps; typedef InstX8632Binop<InstX8632::Addps> InstX8632Addps;
typedef InstX8632Binop<InstX8632::Adc> InstX8632Adc; typedef InstX8632Binop<InstX8632::Adc> InstX8632Adc;
...@@ -943,45 +985,6 @@ private: ...@@ -943,45 +985,6 @@ private:
virtual ~InstX8632Store() {} virtual ~InstX8632Store() {}
}; };
// Move/assignment instruction - wrapper for mov/movss/movsd.
class InstX8632Mov : public InstX8632 {
public:
static InstX8632Mov *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632Mov>())
InstX8632Mov(Func, Dest, Source);
}
virtual bool isRedundantAssign() const;
virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return isClassof(Inst, Mov); }
private:
InstX8632Mov(Cfg *Func, Variable *Dest, Operand *Source);
InstX8632Mov(const InstX8632Mov &) LLVM_DELETED_FUNCTION;
InstX8632Mov &operator=(const InstX8632Mov &) LLVM_DELETED_FUNCTION;
virtual ~InstX8632Mov() {}
};
// Move packed - copy 128 bit values between XMM registers or mem128 and
// XMM registers
class InstX8632Movp : public InstX8632 {
public:
static InstX8632Movp *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632Movp>())
InstX8632Movp(Func, Dest, Source);
}
virtual bool isRedundantAssign() const;
virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return isClassof(Inst, Movp); }
private:
InstX8632Movp(Cfg *Func, Variable *Dest, Operand *Source);
InstX8632Movp(const InstX8632Movp &) LLVM_DELETED_FUNCTION;
InstX8632Movp &operator=(const InstX8632Movp &) LLVM_DELETED_FUNCTION;
virtual ~InstX8632Movp() {}
};
class InstX8632StoreP : public InstX8632 { class InstX8632StoreP : public InstX8632 {
public: public:
static InstX8632StoreP *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) { static InstX8632StoreP *create(Cfg *Func, Operand *Value, OperandX8632 *Mem) {
...@@ -1019,25 +1022,6 @@ private: ...@@ -1019,25 +1022,6 @@ private:
virtual ~InstX8632StoreQ() {} virtual ~InstX8632StoreQ() {}
}; };
// Movq - copy between XMM registers, or mem64 and XMM registers.
class InstX8632Movq : public InstX8632 {
public:
static InstX8632Movq *create(Cfg *Func, Variable *Dest, Operand *Source) {
return new (Func->allocate<InstX8632Movq>())
InstX8632Movq(Func, Dest, Source);
}
virtual bool isRedundantAssign() const;
virtual void emit(const Cfg *Func) const;
virtual void dump(const Cfg *Func) const;
static bool classof(const Inst *Inst) { return isClassof(Inst, Movq); }
private:
InstX8632Movq(Cfg *Func, Variable *Dest, Operand *Source);
InstX8632Movq(const InstX8632Movq &) LLVM_DELETED_FUNCTION;
InstX8632Movq &operator=(const InstX8632Movq &) LLVM_DELETED_FUNCTION;
virtual ~InstX8632Movq() {}
};
// Movsx - copy from a narrower integer type to a wider integer // Movsx - copy from a narrower integer type to a wider integer
// type, with sign extension. // type, with sign extension.
class InstX8632Movsx : public InstX8632 { class InstX8632Movsx : public InstX8632 {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment