[PeepholeOptimizer] Take advantage of the isInsertSubreg property in the
authorQuentin Colombet <qcolombet@apple.com>
Thu, 21 Aug 2014 00:19:16 +0000 (00:19 +0000)
committerQuentin Colombet <qcolombet@apple.com>
Thu, 21 Aug 2014 00:19:16 +0000 (00:19 +0000)
advanced copy optimization.

This is the final step patch toward transforming:
udiv    r0, r0, r2
udiv    r1, r1, r3
vmov.32 d16[0], r0
vmov.32 d16[1], r1
vmov    r0, r1, d16
bx      lr

into:
udiv    r0, r0, r2
udiv    r1, r1, r3
bx      lr

Indeed, thanks to this patch, this optimization is able to look through
vmov.32 d16[0], r0
vmov.32 d16[1], r1

and is able to rewrite the following sequence:
vmov.32 d16[0], r0
vmov.32 d16[1], r1
vmov    r0, r1, d16

into simple generic GPR copies that the coalescer managed to remove.

<rdar://problem/12702965>

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@216144 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/PeepholeOptimizer.cpp
test/CodeGen/ARM/adv-copy-opt.ll

index 495ed67397d4d6f850e4e0aa78488343c6601537..ae14331d6630257a2b91cd64955307ce146bde79 100644 (file)
@@ -161,9 +161,10 @@ namespace {
     /// \brief Check whether \p MI is a copy like instruction that is
     /// not recognized by the register coalescer.
     bool isUncoalescableCopy(const MachineInstr &MI) {
-      return MI.isBitcast() || (!DisableAdvCopyOpt &&
-                                (MI.isRegSequenceLike() ||
-                                 MI.isExtractSubregLike()));
+      return MI.isBitcast() ||
+             (!DisableAdvCopyOpt &&
+              (MI.isRegSequenceLike() || MI.isInsertSubregLike() ||
+               MI.isExtractSubregLike()));
     }
   };
 
@@ -1271,44 +1272,26 @@ bool ValueTracker::getNextSourceFromRegSequence(unsigned &SrcReg,
   return false;
 }
 
-/// Extract the inputs from INSERT_SUBREG.
-/// INSERT_SUBREG vreg0:sub0, vreg1:sub1, sub3 would produce:
-/// - BaseReg: vreg0:sub0
-/// - InsertedReg: vreg1:sub1, sub3
-static void
-getInsertSubregInputs(const MachineInstr &MI,
-                      TargetInstrInfo::RegSubRegPair &BaseReg,
-                      TargetInstrInfo::RegSubRegPairAndIdx &InsertedReg) {
-  assert(MI.isInsertSubreg() && "Instruction do not have the proper type");
-
-  // We are looking at:
-  // Def = INSERT_SUBREG v0, v1, sub0.
-  const MachineOperand &MOBaseReg = MI.getOperand(1);
-  const MachineOperand &MOInsertedReg = MI.getOperand(2);
-  const MachineOperand &MOSubIdx = MI.getOperand(3);
-  assert(MOSubIdx.isImm() &&
-         "One of the subindex of the reg_sequence is not an immediate");
-  BaseReg.Reg = MOBaseReg.getReg();
-  BaseReg.SubReg = MOBaseReg.getSubReg();
-
-  InsertedReg.Reg = MOInsertedReg.getReg();
-  InsertedReg.SubReg = MOInsertedReg.getSubReg();
-  InsertedReg.SubIdx = (unsigned)MOSubIdx.getImm();
-}
-
 bool ValueTracker::getNextSourceFromInsertSubreg(unsigned &SrcReg,
                                                  unsigned &SrcSubReg) {
-  assert(Def->isInsertSubreg() && "Invalid definition");
+  assert((Def->isInsertSubreg() || Def->isInsertSubregLike()) &&
+         "Invalid definition");
+
   if (Def->getOperand(DefIdx).getSubReg())
     // If we are composing subreg, bails out.
     // Same remark as getNextSourceFromRegSequence.
     // I.e., this may be turned into an assert.
     return false;
 
+  if (!TII)
+    // We could handle the REG_SEQUENCE here, but we do not want to
+    // duplicate the code from the generic TII.
+    return false;
+
   TargetInstrInfo::RegSubRegPair BaseReg;
   TargetInstrInfo::RegSubRegPairAndIdx InsertedReg;
-  assert(DefIdx == 0 && "Invalid definition");
-  getInsertSubregInputs(*Def, BaseReg, InsertedReg);
+  if (!TII->getInsertSubregInputs(*Def, DefIdx, BaseReg, InsertedReg))
+    return false;
 
   // We are looking at:
   // Def = INSERT_SUBREG v0, v1, sub1
@@ -1416,7 +1399,7 @@ bool ValueTracker::getNextSourceImpl(unsigned &SrcReg, unsigned &SrcSubReg) {
     return false;
   if (Def->isRegSequence() || Def->isRegSequenceLike())
     return getNextSourceFromRegSequence(SrcReg, SrcSubReg);
-  if (Def->isInsertSubreg())
+  if (Def->isInsertSubreg() || Def->isInsertSubregLike())
     return getNextSourceFromInsertSubreg(SrcReg, SrcSubReg);
   if (Def->isExtractSubreg() || Def->isExtractSubregLike())
     return getNextSourceFromExtractSubreg(SrcReg, SrcSubReg);
index c9a9b831d0edfe3579d21abe6090d009cc554e21..c618d40efa859a90aba9ce0506a89382d7603837 100644 (file)
 ; NOOPT-NEXT: bx       lr
 ;
 ; OPT-NOT: vmov
-; OPT:         udiv    [[RES_LOW:r[0-9]+]], r0, r2
-; OPT-NEXT: udiv       [[RES_HIGH:r[0-9]+]], r1, r3
-; OPT-NEXT: vmov.32    [[RES:d[0-9]+]][0], [[RES_LOW]]
-; OPT-NEXT: vmov.32    [[RES]][1], [[RES_HIGH]]
-; OPT-NEXT: vmov       r0, r1, [[RES]]
+; OPT:         udiv    r0, r0, r2
+; OPT-NEXT: udiv       r1, r1, r3
 ; OPT-NEXT: bx lr
 define <2 x i32> @simpleVectorDiv(<2 x i32> %A, <2 x i32> %B) nounwind {
 entry: