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
diff --git a/src/IceInstX8632.cpp b/src/IceInstX8632.cpp
index 1f7508b..0b99c80 100644
--- a/src/IceInstX8632.cpp
+++ b/src/IceInstX8632.cpp
@@ -219,16 +219,6 @@
   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)
     : InstX8632(Func, InstX8632::StoreP, 2, NULL) {
   addSource(Value);
@@ -241,11 +231,6 @@
   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)
     : InstX8632(Func, InstX8632::Movsx, 1, Dest) {
   addSource(Source);
@@ -274,51 +259,6 @@
   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)
     : InstX8632(Func, InstX8632::Ret, Source ? 1 : 0, NULL) {
   if (Source)
@@ -446,6 +386,21 @@
   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
 template <> const char *InstX8632Bswap::Opcode = "bswap";
@@ -457,6 +412,10 @@
 template <> const char *InstX8632Movd::Opcode = "movd";
 template <> const char *InstX8632Sqrtss::Opcode = "sqrtss";
 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
 template <> const char *InstX8632Add::Opcode = "add";
 template <> const char *InstX8632Addps::Opcode = "addps";
@@ -999,7 +958,7 @@
   Str << "\n";
 }
 
-void InstX8632Mov::emit(const Cfg *Func) const {
+template <> void InstX8632Mov::emit(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(getSrcSize() == 1);
   Operand *Src = getSrc(0);
@@ -1035,15 +994,7 @@
   Str << "\n";
 }
 
-void InstX8632Mov::dump(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 {
+template <> void InstX8632Movp::emit(const Cfg *Func) const {
   // TODO(wala,stichnot): movups works with all vector operands, but
   // there exist other instructions (movaps, movdqa, movdqu) that may
   // perform better, depending on the data type and alignment of the
@@ -1057,15 +1008,7 @@
   Str << "\n";
 }
 
-void InstX8632Movp::dump(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 {
+template <> void InstX8632Movq::emit(const Cfg *Func) const {
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(getSrcSize() == 1);
   assert(getDest()->getType() == IceType_i64 ||
@@ -1077,14 +1020,6 @@
   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 {
   Ostream &Str = Func->getContext()->getStrEmit();
   assert(getSrcSize() == 1);