summaryrefslogtreecommitdiff
path: root/lib/CodeGen/RegisterCoalescer.cpp
diff options
context:
space:
mode:
authorTim Northover <tnorthover@apple.com>2013-05-29 19:32:06 +0000
committerTim Northover <tnorthover@apple.com>2013-05-29 19:32:06 +0000
commitaae0fa998af0f65221d7b98630162be6d88f05dc (patch)
tree32f70d885b5b98aac7a135eb1d8dd0b00d32f5e0 /lib/CodeGen/RegisterCoalescer.cpp
parent88c744083d6cf5f4810c1e9fe457a212bb24d432 (diff)
downloadllvm-aae0fa998af0f65221d7b98630162be6d88f05dc.tar.gz
llvm-aae0fa998af0f65221d7b98630162be6d88f05dc.tar.bz2
llvm-aae0fa998af0f65221d7b98630162be6d88f05dc.tar.xz
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 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182872 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/RegisterCoalescer.cpp')
-rw-r--r--lib/CodeGen/RegisterCoalescer.cpp83
1 files changed, 65 insertions, 18 deletions
diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp
index d85646dd3c..f0e62412ba 100644
--- a/lib/CodeGen/RegisterCoalescer.cpp
+++ b/lib/CodeGen/RegisterCoalescer.cpp
@@ -733,7 +733,9 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
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::reMaterializeTrivialDef(CoalescerPair &CP,
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::reMaterializeTrivialDef(CoalescerPair &CP,
}
}
+ 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::reMaterializeTrivialDef(CoalescerPair &CP,
}
}
- 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::reMaterializeTrivialDef(CoalescerPair &CP,
LI->createDeadDef(NewMIIdx.getRegSlot(), LIS->getVNInfoAllocator());
}
- CopyMI->eraseFromParent();
- ErasedInstrs.insert(CopyMI);
DEBUG(dbgs() << "Remat: " << *NewMI);
++NumReMats;