Model VLD*_UPD and VLD*odd_UPD pair with REG_SEQUENCE.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@103790 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Target/ARM/NEONPreAllocPass.cpp b/lib/Target/ARM/NEONPreAllocPass.cpp
index 6c43e69..017e6f7 100644
--- a/lib/Target/ARM/NEONPreAllocPass.cpp
+++ b/lib/Target/ARM/NEONPreAllocPass.cpp
@@ -33,7 +33,8 @@
 
   private:
     bool FormsRegSequence(MachineInstr *MI,
-                          unsigned FirstOpnd, unsigned NumRegs) const;
+                          unsigned FirstOpnd, unsigned NumRegs,
+                          unsigned Offset, unsigned Stride) const;
     bool PreAllocNEONRegisters(MachineBasicBlock &MBB);
   };
 
@@ -340,13 +341,16 @@
 
 bool
 NEONPreAllocPass::FormsRegSequence(MachineInstr *MI,
-                                   unsigned FirstOpnd, unsigned NumRegs) const {
+                                   unsigned FirstOpnd, unsigned NumRegs,
+                                   unsigned Offset, unsigned Stride) const {
   MachineOperand &FMO = MI->getOperand(FirstOpnd);
   assert(FMO.isReg() && FMO.getSubReg() == 0 && "unexpected operand");
   unsigned VirtReg = FMO.getReg();
   (void)VirtReg;
   assert(TargetRegisterInfo::isVirtualRegister(VirtReg) &&
          "expected a virtual register");
+
+  unsigned LastSubIdx = 0;
   if (FMO.isDef()) {
     MachineInstr *RegSeq = 0;
     for (unsigned R = 0; R < NumRegs; ++R) {
@@ -363,13 +367,28 @@
         return false;
       if (RegSeq && RegSeq != UseMI)
         return false;
+      unsigned OpIdx = 1 + (Offset + R * Stride) * 2;
+      if (UseMI->getOperand(OpIdx).getReg() != VirtReg)
+        llvm_unreachable("Malformed REG_SEQUENCE instruction!");
+      unsigned SubIdx = UseMI->getOperand(OpIdx + 1).getImm();
+      if (LastSubIdx) {
+        if (LastSubIdx != SubIdx-Stride)
+          return false;
+      } else {
+        // Must start from arm_dsubreg_0 or arm_qsubreg_0.
+        if (SubIdx != (ARM::DSUBREG_0+Offset) &&
+            SubIdx != (ARM::QSUBREG_0+Offset))
+          return false;
+      }
       RegSeq = UseMI;
+      LastSubIdx = SubIdx;
     }
 
-    // Make sure trailing operands of REG_SEQUENCE are undef.
-    unsigned NumExps = (RegSeq->getNumOperands() - 1) / 2;
-    for (unsigned i = NumRegs * 2 + 1; i < NumExps; i += 2) {
-      const MachineOperand &MO = RegSeq->getOperand(i);
+    // In the case of vld3, etc., make sure the trailing operand of
+    // REG_SEQUENCE is an undef.
+    if (NumRegs == 3) {
+      unsigned OpIdx = 1 + (Offset + 3 * Stride) * 2;
+      const MachineOperand &MO = RegSeq->getOperand(OpIdx);
       unsigned VirtReg = MO.getReg();
       MachineInstr *DefMI = MRI->getVRegDef(VirtReg);
       if (!DefMI || !DefMI->isImplicitDef())
@@ -379,7 +398,6 @@
   }
 
   unsigned LastSrcReg = 0;
-  unsigned LastSubIdx = 0;
   SmallVector<unsigned, 4> SubIds;
   for (unsigned R = 0; R < NumRegs; ++R) {
     const MachineOperand &MO = MI->getOperand(FirstOpnd + R);
@@ -400,11 +418,12 @@
       return false;
     unsigned SubIdx = DefMI->getOperand(2).getImm();
     if (LastSubIdx) {
-      if (LastSubIdx != SubIdx-1)
+      if (LastSubIdx != SubIdx-Stride)
         return false;
     } else {
       // Must start from arm_dsubreg_0 or arm_qsubreg_0.
-      if (SubIdx != ARM::DSUBREG_0 && SubIdx != ARM::QSUBREG_0)
+      if (SubIdx != (ARM::DSUBREG_0+Offset) &&
+          SubIdx != (ARM::QSUBREG_0+Offset))
         return false;
     }
     SubIds.push_back(SubIdx);
@@ -447,7 +466,7 @@
     if (!isNEONMultiRegOp(MI->getOpcode(), FirstOpnd, NumRegs, Offset, Stride))
       continue;
     if (llvm::ModelWithRegSequence() &&
-        FormsRegSequence(MI, FirstOpnd, NumRegs))
+        FormsRegSequence(MI, FirstOpnd, NumRegs, Offset, Stride))
       continue;
 
     MachineBasicBlock::iterator NextI = llvm::next(MBBI);