Refactor vector register moves.

Eliminates code duplication, and moves between identical S registers
are elided.

Change-Id: Iec5d626c72f3c521a199a755e8804e26a5b4a782
Reviewed-on: https://chromium-review.googlesource.com/697946
Reviewed-by: Jim Stichnoth <[email protected]>
diff --git a/src/IceAssemblerARM32.cpp b/src/IceAssemblerARM32.cpp
index 4b1fcb9..6f96985 100644
--- a/src/IceAssemblerARM32.cpp
+++ b/src/IceAssemblerARM32.cpp
@@ -1114,6 +1114,19 @@
   emitInst(Encoding);
 }
 
+void AssemblerARM32::emitMoveDD(IValueT Dd, IValueT Dm) {
+  // VMOV (register) - ARMv7-A/R section A8.6.327, encoding A1:
+  //   VMOV<c> <Dd>, <Dm>
+  //
+  // 111100100D10mmmmdddd0001MQM1mmmm
+  constexpr IValueT VmovOpcode = B25 | B21 | B8 | B4;
+  constexpr bool UseQRegs = false;
+  constexpr bool IsFloatTy = false;
+
+  if (Dd != Dm)
+    emitSIMDBase(VmovOpcode, Dd, Dm, Dm, UseQRegs, IsFloatTy);
+}
+
 void AssemblerARM32::emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm) {
   // VMOV (register) - ARM section A8.8.340, encoding A2:
   //   vmov<c>.f32 <Sd>, <Sm>
@@ -1121,7 +1134,9 @@
   // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
   constexpr IValueT VmovssOpcode = B23 | B21 | B20 | B6;
   constexpr IValueT S0 = 0;
-  emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
+
+  if (Sd != Sm)
+    emitVFPsss(Cond, VmovssOpcode, Sd, S0, Sm);
 }
 
 void AssemblerARM32::emitMulOp(CondARM32::Cond Cond, IValueT Opcode, IValueT Rd,
@@ -3479,20 +3494,14 @@
   const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vzip));
   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vzip));
 
-  constexpr bool UseQRegs = false;
-  constexpr bool IsFloatTy = false;
-
-  // VMOV Dd, Dm
-  // 111100100D10mmmmdddd0001MQM1mmmm
-  constexpr IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
   // Copy lower half of second source to upper half of destination.
-  emitSIMDBase(VmovOpcode, Dd + 1, Dm, Dm, UseQRegs, IsFloatTy);
+  emitMoveDD(Dd + 1, Dm);
 
   // Copy lower half of first source to lower half of destination.
-  if (Dd != Dn)
-    emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloatTy);
+  emitMoveDD(Dd, Dn);
 
+  constexpr bool UseQRegs = false;
+  constexpr bool IsFloatTy = false;
   constexpr IValueT ElmtShift = 18;
   const IValueT ElmtSize = encodeElmtType(ElmtTy);
   assert(Utils::IsUint(2, ElmtSize));
@@ -3554,15 +3563,8 @@
   const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
 
-  constexpr bool UseQRegs = false;
-  constexpr bool IsFloat = false;
-
-  const IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
-  if (Dd != Dm)
-    emitSIMDBase(VmovOpcode, Dd, Dm, Dm, UseQRegs, IsFloat);
-  if (Dd + 1 != Dn + 1)
-    emitSIMDBase(VmovOpcode, Dd + 1, Dn + 1, Dn + 1, UseQRegs, IsFloat);
+  emitMoveDD(Dd, Dm);
+  emitMoveDD(Dd + 1, Dn + 1);
 }
 
 void AssemblerARM32::vmovhq(const Operand *OpQd, const Operand *OpQn,
@@ -3580,15 +3582,8 @@
   const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
 
-  constexpr bool UseQRegs = false;
-  constexpr bool IsFloat = false;
-
-  const IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
-  if (Dd != Dn)
-    emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloat);
-  if (Dd + 1 != Dm + 1)
-    emitSIMDBase(VmovOpcode, Dd + 1, Dm + 1, Dm + 1, UseQRegs, IsFloat);
+  emitMoveDD(Dd, Dn);
+  emitMoveDD(Dd + 1, Dm + 1);
 }
 
 void AssemblerARM32::vmovhlq(const Operand *OpQd, const Operand *OpQn,
@@ -3606,15 +3601,8 @@
   const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
 
-  constexpr bool UseQRegs = false;
-  constexpr bool IsFloat = false;
-
-  const IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
-  if (Dd != Dm + 1)
-    emitSIMDBase(VmovOpcode, Dd, Dm + 1, Dm + 1, UseQRegs, IsFloat);
-  if (Dd + 1 != Dn + 1)
-    emitSIMDBase(VmovOpcode, Dd + 1, Dn + 1, Dn + 1, UseQRegs, IsFloat);
+  emitMoveDD(Dd, Dm + 1);
+  emitMoveDD(Dd + 1, Dn + 1);
 }
 
 void AssemblerARM32::vmovlhq(const Operand *OpQd, const Operand *OpQn,
@@ -3632,15 +3620,8 @@
   const IValueT Dn = mapQRegToDReg(encodeQRegister(OpQn, "Qn", Vmov));
   const IValueT Dm = mapQRegToDReg(encodeQRegister(OpQm, "Qm", Vmov));
 
-  constexpr bool UseQRegs = false;
-  constexpr bool IsFloat = false;
-
-  const IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
-  if (Dd + 1 != Dm)
-    emitSIMDBase(VmovOpcode, Dd + 1, Dm, Dm, UseQRegs, IsFloat);
-  if (Dd != Dn)
-    emitSIMDBase(VmovOpcode, Dd, Dn, Dn, UseQRegs, IsFloat);
+  emitMoveDD(Dd + 1, Dm);
+  emitMoveDD(Dd, Dn);
 }
 
 void AssemblerARM32::vnegqs(Type ElmtTy, const Operand *OpQd,
@@ -3938,12 +3919,8 @@
   } else {
     // Narrow first source operand to lower half of destination.
     emitSIMDBase(VqmovnOpcode, Dd, 0, Dm, UseQRegs, IsFloatTy);
-
-    // VMOV Dd, Dm
-    // 111100100D10mmmmdddd0001MQM1mmmm
-    const IValueT VmovOpcode = B25 | B21 | B8 | B4;
-
-    emitSIMDBase(VmovOpcode, Dd + 1, Dd, Dd, UseQRegs, IsFloatTy);
+    // Duplicate to upper half.
+    emitMoveDD(Dd + 1, Dd);
   }
 }
 
diff --git a/src/IceAssemblerARM32.h b/src/IceAssemblerARM32.h
index 43c3f56..f6d2416 100644
--- a/src/IceAssemblerARM32.h
+++ b/src/IceAssemblerARM32.h
@@ -809,8 +809,12 @@
                             uint32_t Index, const Operand *OpRt, bool IsExtract,
                             const char *InstName);
 
+  // 111100100D10mmmmdddd0001MQM1mmmm where Ddddd=Dd, and Mmmmm=Dm.
+  // Assigns register Dd the value of register Dm.
+  void emitMoveDD(IValueT Dd, IValueT Dm);
+
   // cccc11101D110000dddd101001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
-  // Assigns Sd the value of Sm.
+  // Assigns register Sd the value of register Sm.
   void emitMoveSS(CondARM32::Cond Cond, IValueT Sd, IValueT Sm);
 
   // Pattern ccccxxxxxxxfnnnnddddssss1001mmmm where cccc=Cond, dddd=Rd, nnnn=Rn,