[llvm] r182872 - Teach ReMaterialization to be more cunning about subregisters

Tim Northover tnorthover at apple.com
Wed May 29 12:32:06 PDT 2013


Author: tnorthover
Date: Wed May 29 14:32:06 2013
New Revision: 182872

URL: http://llvm.org/viewvc/llvm-project?rev=182872&view=rev
Log:
Teach ReMaterialization to be more cunning about subregisters

This allows rematerialization during register coalescing to handle
more cases involving operations like SUBREG_TO_REG which might need to
be rematerialized using sub-register indices.

For example, code like:
    v1(GPR64):sub_32 = MOVZ something
    v2(GPR64) = COPY v1(GPR64)
should be convertable to:
    v2(GPR64):sub_32 = MOVZ something

but previously we just gave up in places like this

Modified:
    llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp
    llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
    llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll

Modified: llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp?rev=182872&r1=182871&r2=182872&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp (original)
+++ llvm/trunk/lib/CodeGen/RegisterCoalescer.cpp Wed May 29 14:32:06 2013
@@ -733,7 +733,9 @@ bool RegisterCoalescer::removeCopyByComm
 bool RegisterCoalescer::reMaterializeTrivialDef(CoalescerPair &CP,
                                                 MachineInstr *CopyMI) {
   unsigned SrcReg = CP.isFlipped() ? CP.getDstReg() : CP.getSrcReg();
+  unsigned SrcIdx = CP.isFlipped() ? CP.getDstIdx() : CP.getSrcIdx();
   unsigned DstReg = CP.isFlipped() ? CP.getSrcReg() : CP.getDstReg();
+  unsigned DstIdx = CP.isFlipped() ? CP.getSrcIdx() : CP.getDstIdx();
   if (TargetRegisterInfo::isPhysicalRegister(SrcReg))
     return false;
 
@@ -762,29 +764,38 @@ bool RegisterCoalescer::reMaterializeTri
   MachineOperand &DstOperand = CopyMI->getOperand(0);
   if (DstOperand.getSubReg() && !DstOperand.isUndef())
     return false;
+
+  const TargetRegisterClass *DefRC = TII->getRegClass(MCID, 0, TRI, *MF);
   if (!DefMI->isImplicitDef()) {
-    // Make sure the copy destination register class fits the instruction
-    // definition register class. The mismatch can happen as a result of earlier
-    // extract_subreg, insert_subreg, subreg_to_reg coalescing.
-    const TargetRegisterClass *RC = TII->getRegClass(MCID, 0, TRI, *MF);
-    if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
-      if (!MRI->constrainRegClass(DstReg, RC))
+    if (TargetRegisterInfo::isPhysicalRegister(DstReg)) {
+      unsigned NewDstReg = DstReg;
+
+      unsigned NewDstIdx = TRI->composeSubRegIndices(CP.getSrcIdx(),
+                                              DefMI->getOperand(0).getSubReg());
+      if (NewDstIdx)
+        NewDstReg = TRI->getSubReg(DstReg, NewDstIdx);
+
+      // Finally, make sure that the physical subregister that will be
+      // constructed later is permitted for the instruction.
+      if (!DefRC->contains(NewDstReg))
         return false;
-    } else if (!RC->contains(DstReg))
-      return false;
+    } else {
+      // Theoretically, some stack frame reference could exist. Just make sure
+      // it hasn't actually happened.
+      assert(TargetRegisterInfo::isVirtualRegister(DstReg) &&
+             "Only expect to deal with virtual or physical registers");
+    }
   }
 
   MachineBasicBlock *MBB = CopyMI->getParent();
   MachineBasicBlock::iterator MII =
     llvm::next(MachineBasicBlock::iterator(CopyMI));
-  TII->reMaterialize(*MBB, MII, DstReg, 0, DefMI, *TRI);
+  TII->reMaterialize(*MBB, MII, DstReg, SrcIdx, DefMI, *TRI);
   MachineInstr *NewMI = prior(MII);
 
-  // The original DefMI may have been a subregister def, but the full register
-  // class of its destination matches the destination of CopyMI, and CopyMI is
-  // either a full register def or is read-undef. Therefore we can clear the
-  // subregister index on the rematerialized instruction.
-  NewMI->getOperand(0).setSubReg(0);
+  LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI);
+  CopyMI->eraseFromParent();
+  ErasedInstrs.insert(CopyMI);
 
   // NewMI may have dead implicit defs (E.g. EFLAGS for MOV<bits>r0 on X86).
   // We need to remember these so we can add intervals once we insert
@@ -800,6 +811,46 @@ bool RegisterCoalescer::reMaterializeTri
     }
   }
 
+  if (TargetRegisterInfo::isVirtualRegister(DstReg)) {
+    unsigned NewIdx = NewMI->getOperand(0).getSubReg();
+    const TargetRegisterClass *RCForInst;
+    if (NewIdx)
+      RCForInst = TRI->getMatchingSuperRegClass(MRI->getRegClass(DstReg), DefRC,
+                                                NewIdx);
+
+    if (MRI->constrainRegClass(DstReg, DefRC)) {
+      // The materialized instruction is quite capable of setting DstReg
+      // directly, but it may still have a now-trivial subregister index which
+      // we should clear.
+      NewMI->getOperand(0).setSubReg(0);
+    } else if (NewIdx && RCForInst) {
+      // The subreg index on NewMI is essential; we still have to make sure
+      // DstReg:idx is in a class that NewMI can use.
+      MRI->constrainRegClass(DstReg, RCForInst);
+    } else {
+      // DstReg is actually incompatible with NewMI, we have to move to a
+      // super-reg's class. This could come from a sequence like:
+      //     GR32 = MOV32r0
+      //     GR8 = COPY GR32:sub_8
+      MRI->setRegClass(DstReg, CP.getNewRC());
+      updateRegDefsUses(DstReg, DstReg, DstIdx);
+      NewMI->getOperand(0).setSubReg(
+          TRI->composeSubRegIndices(SrcIdx, DefMI->getOperand(0).getSubReg()));
+    }
+  } else if (NewMI->getOperand(0).getReg() != DstReg) {
+    // The New instruction may be defining a sub-register of what's actually
+    // been asked for. If so it must implicitly define the whole thing.
+    assert(TargetRegisterInfo::isPhysicalRegister(DstReg) &&
+           "Only expect virtual or physical registers in remat");
+    NewMI->addOperand(MachineOperand::CreateReg(DstReg,
+                                                true  /*IsDef*/,
+                                                true  /*IsImp*/,
+                                                false /*IsKill*/));
+  }
+
+  if (NewMI->getOperand(0).getSubReg())
+    NewMI->getOperand(0).setIsUndef();
+
   // CopyMI may have implicit operands, transfer them over to the newly
   // rematerialized instruction. And update implicit def interval valnos.
   for (unsigned i = CopyMI->getDesc().getNumOperands(),
@@ -814,8 +865,6 @@ bool RegisterCoalescer::reMaterializeTri
     }
   }
 
-  LIS->ReplaceMachineInstrInMaps(CopyMI, NewMI);
-
   SlotIndex NewMIIdx = LIS->getInstructionIndex(NewMI);
   for (unsigned i = 0, e = NewMIImplDefs.size(); i != e; ++i) {
     unsigned Reg = NewMIImplDefs[i];
@@ -824,8 +873,6 @@ bool RegisterCoalescer::reMaterializeTri
         LI->createDeadDef(NewMIIdx.getRegSlot(), LIS->getVNInfoAllocator());
   }
 
-  CopyMI->eraseFromParent();
-  ErasedInstrs.insert(CopyMI);
   DEBUG(dbgs() << "Remat: " << *NewMI);
   ++NumReMats;
 

Modified: llvm/trunk/test/CodeGen/AArch64/sibling-call.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/sibling-call.ll?rev=182872&r1=182871&r2=182872&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/sibling-call.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/sibling-call.ll Wed May 29 14:32:06 2013
@@ -91,7 +91,7 @@ define void @indirect_tail() {
   %fptr = load void(i32)** @func
   tail call void %fptr(i32 42)
   ret void
-; CHECK: movz w0, #42
 ; CHECK: ldr [[FPTR:x[1-9]+]], [{{x[0-9]+}}, #:lo12:func]
+; CHECK: movz w0, #42
 ; CHECK: br [[FPTR]]
-}
\ No newline at end of file
+}

Modified: llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll?rev=182872&r1=182871&r2=182872&view=diff
==============================================================================
--- llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll (original)
+++ llvm/trunk/test/DebugInfo/AArch64/variable-loc.ll Wed May 29 14:32:06 2013
@@ -16,21 +16,21 @@
 ;     return 0;
 ; }
 
-  ; First make sure main_arr is where we expect it: sp + 12 == x29 - 420:
+  ; First make sure main_arr is where we expect it: sp + 4 == x29 - 412:
 ; CHECK: main:
-; CHECK: sub sp, sp, #448
-; CHECK: stp x29, x30, [sp, #432]
-; CHECK: add x29, sp, #432
-; CHECK: add {{x[0-9]+}}, sp, #12
+; CHECK: sub sp, sp, #432
+; CHECK: stp x29, x30, [sp, #416]
+; CHECK: add x29, sp, #416
+; CHECK: add {{x[0-9]+}}, sp, #4
 
   ; Now check the debugging information reflects this:
 ; CHECK: DW_TAG_variable
 ; CHECK-NEXT: .word .Linfo_string7
 
-  ; Rather hard-coded, but 145 => DW_OP_fbreg and the .ascii is LEB128 encoded -420.
+  ; Rather hard-coded, but 145 => DW_OP_fbreg and the .ascii is LEB128 encoded -412.
 ; CHECK: DW_AT_location
 ; CHECK-NEXT: .byte 145
-; CHECK-NEXT: .ascii "\334|"
+; CHECK-NEXT: .ascii "\344|"
 
 ; CHECK: .Linfo_string7:
 ; CHECK-NEXT: main_arr





More information about the llvm-commits mailing list