From f9f1da17f8bd6ffb2df62ce3cb933f0ee63f8da4 Mon Sep 17 00:00:00 2001 From: Evan Cheng Date: Thu, 18 Jun 2009 02:04:01 +0000 Subject: [PATCH] - Update register allocation hint after coalescing. This is done by the target since the hint is target dependent. This is important for ARM register pair hints. - Register allocator should resolve the second part of the hint (register number) before passing it to the target since it knows virtual register to physical register mapping. - More fixes to get ARM load / store double word working. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@73671 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetRegisterInfo.h | 17 ++- lib/CodeGen/RegAllocLinearScan.cpp | 10 +- lib/CodeGen/SimpleRegisterCoalescing.cpp | 3 + lib/Target/ARM/ARMLoadStoreOptimizer.cpp | 66 +++++++--- lib/Target/ARM/ARMRegisterInfo.cpp | 158 ++++++++++++++--------- lib/Target/ARM/ARMRegisterInfo.h | 5 +- 6 files changed, 172 insertions(+), 87 deletions(-) diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 9da1134352b..91e8f80fd10 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -523,7 +523,7 @@ public: /// register class in the form of a pair of TargetRegisterClass iterators. virtual std::pair getAllocationOrder(const TargetRegisterClass *RC, - std::pair Hint, + unsigned HintType, unsigned HintReg, const MachineFunction &MF) const { return std::make_pair(RC->allocation_order_begin(MF), RC->allocation_order_end(MF)); @@ -531,13 +531,24 @@ public: /// ResolveRegAllocHint - Resolves the specified register allocation hint /// to a physical register. Returns the physical register if it is successful. - unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, - const MachineFunction &MF) const { + virtual unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, + const MachineFunction &MF) const { if (Type == 0 && Reg && isPhysicalRegister(Reg)) return Reg; return 0; } + /// UpdateRegAllocHint - A callback to allow target a chance to update + /// register allocation hints when a register is "changed" (e.g. coalesced) + /// to another register. e.g. On ARM, some virtual registers should target + /// register pairs, if one of pair is coalesced to another register, the + /// allocation hint of the other half of the pair should be changed to point + /// to the new register. + virtual void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + // Do nothing. + } + /// targetHandlesStackFrameRounding - Returns true if the target is /// responsible for rounding up the stack frame (probably at emitPrologue /// time). diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index f7f5dc74b5d..41a42fd22d3 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -1356,9 +1356,15 @@ unsigned RALinScan::getFreePhysReg(LiveInterval* cur, unsigned FreeReg = 0; unsigned FreeRegInactiveCount = 0; + std::pair Hint = mri_->getRegAllocationHint(cur->reg); + // Resolve second part of the hint (if possible) given the current allocation. + unsigned physReg = Hint.second; + if (physReg && + TargetRegisterInfo::isVirtualRegister(physReg) && vrm_->hasPhys(physReg)) + physReg = vrm_->getPhys(physReg); + TargetRegisterClass::iterator I, E; - tie(I, E) = tri_->getAllocationOrder(RC, - mri_->getRegAllocationHint(cur->reg), *mf_); + tie(I, E) = tri_->getAllocationOrder(RC, Hint.first, physReg, *mf_); assert(I != E && "No allocatable register in this register class!"); // Scan for the first available register. diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index c363ba52b5e..20348055bd9 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -1766,6 +1766,9 @@ bool SimpleRegisterCoalescing::JoinCopy(CopyRec &TheCopy, bool &Again) { // being merged. li_->removeInterval(SrcReg); + // Update regalloc hint. + tri_->UpdateRegAllocHint(SrcReg, DstReg, *mf_); + // Manually deleted the live interval copy. if (SavedLI) { SavedLI->clear(); diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index 1b8223aa0ab..f8de0efc0d4 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -41,6 +41,12 @@ STATISTIC(NumSTMGened , "Number of stm instructions generated"); STATISTIC(NumFLDMGened, "Number of fldm instructions generated"); STATISTIC(NumFSTMGened, "Number of fstm instructions generated"); STATISTIC(NumLdStMoved, "Number of load / store instructions moved"); +STATISTIC(NumLDRDFormed,"Number of ldrd created before allocation"); +STATISTIC(NumSTRDFormed,"Number of strd created before allocation"); +STATISTIC(NumLDRD2LDM, "Number of ldrd instructions turned back into ldm"); +STATISTIC(NumSTRD2STM, "Number of strd instructions turned back into stm"); +STATISTIC(NumLDRD2LDR, "Number of ldrd instructions turned back into ldr's"); +STATISTIC(NumSTRD2STR, "Number of strd instructions turned back into str's"); /// ARMAllocLoadStoreOpt - Post- register allocation pass the combine /// load / store instructions to form ldm / stm instructions. @@ -651,9 +657,9 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, if ((EvenRegNum & 1) == 0 && (EvenRegNum + 1) == OddRegNum) return false; - bool isDef = Opcode == ARM::LDRD; - bool EvenKill = isDef ? false : MI->getOperand(0).isKill(); - bool OddKill = isDef ? false : MI->getOperand(1).isKill(); + bool isLd = Opcode == ARM::LDRD; + bool EvenKill = isLd ? false : MI->getOperand(0).isKill(); + bool OddKill = isLd ? false : MI->getOperand(1).isKill(); const MachineOperand &BaseOp = MI->getOperand(2); unsigned BaseReg = BaseOp.getReg(); bool BaseKill = BaseOp.isKill(); @@ -668,34 +674,49 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB, // Ascending register numbers and no offset. It's safe to change it to a // ldm or stm. unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDM : ARM::STM; - BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) - .addReg(BaseReg, getKillRegState(BaseKill)) - .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) - .addImm(Pred).addReg(PredReg) - .addReg(EvenReg, getDefRegState(isDef)) - .addReg(OddReg, getDefRegState(isDef)); + if (isLd) { + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) + .addReg(BaseReg, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) + .addImm(Pred).addReg(PredReg) + .addReg(EvenReg, getDefRegState(isLd)) + .addReg(OddReg, getDefRegState(isLd)); + ++NumLDRD2LDM; + } else { + BuildMI(MBB, MBBI, MBBI->getDebugLoc(), TII->get(NewOpc)) + .addReg(BaseReg, getKillRegState(BaseKill)) + .addImm(ARM_AM::getAM4ModeImm(ARM_AM::ia)) + .addImm(Pred).addReg(PredReg) + .addReg(EvenReg, getKillRegState(EvenKill)) + .addReg(OddReg, getKillRegState(OddKill)); + ++NumSTRD2STM; + } } else { // Split into two instructions. unsigned NewOpc = (Opcode == ARM::LDRD) ? ARM::LDR : ARM::STR; DebugLoc dl = MBBI->getDebugLoc(); // If this is a load and base register is killed, it may have been // re-defed by the load, make sure the first load does not clobber it. - if (isDef && + if (isLd && (BaseKill || OffKill) && (TRI->regsOverlap(EvenReg, BaseReg) || (OffReg && TRI->regsOverlap(EvenReg, OffReg)))) { assert(!TRI->regsOverlap(OddReg, BaseReg) && (!OffReg || !TRI->regsOverlap(OddReg, OffReg))); - InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill, + InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, OddReg, OddKill, BaseReg, false, OffReg, false, Pred, PredReg, TII); - InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill, + InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, EvenReg, EvenKill, BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII); } else { - InsertLDR_STR(MBB, MBBI, OffImm, isDef, dl, NewOpc, EvenReg, EvenKill, + InsertLDR_STR(MBB, MBBI, OffImm, isLd, dl, NewOpc, EvenReg, EvenKill, BaseReg, false, OffReg, false, Pred, PredReg, TII); - InsertLDR_STR(MBB, MBBI, OffImm+4, isDef, dl, NewOpc, OddReg, OddKill, + InsertLDR_STR(MBB, MBBI, OffImm+4, isLd, dl, NewOpc, OddReg, OddKill, BaseReg, BaseKill, OffReg, OffKill, Pred, PredReg, TII); } + if (isLd) + ++NumLDRD2LDR; + else + ++NumSTRD2STR; } MBBI = prior(MBBI); @@ -1069,6 +1090,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, MachineInstr *FirstOp = 0; MachineInstr *LastOp = 0; int LastOffset = 0; + unsigned LastOpcode = 0; unsigned LastBytes = 0; unsigned NumMove = 0; for (int i = Ops.size() - 1; i >= 0; --i) { @@ -1083,6 +1105,10 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, LastOp = Op; } + unsigned Opcode = Op->getOpcode(); + if (LastOpcode && Opcode != LastOpcode) + break; + int Offset = getMemoryOpOffset(Op); unsigned Bytes = getLSMultipleTransferSize(Op); if (LastBytes) { @@ -1091,6 +1117,7 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, } LastOffset = Offset; LastBytes = Bytes; + LastOpcode = Opcode; if (++NumMove == 4) break; } @@ -1131,22 +1158,25 @@ bool ARMPreAllocLoadStoreOpt::RescheduleOps(MachineBasicBlock *MBB, Offset, PredReg, Pred)) { Ops.pop_back(); Ops.pop_back(); - MBB->erase(Op0); - MBB->erase(Op1); // Form the pair instruction. - if (isLd) + if (isLd) { BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc)) .addReg(EvenReg, RegState::Define) .addReg(OddReg, RegState::Define) .addReg(BaseReg).addReg(0).addImm(Offset) .addImm(Pred).addReg(PredReg); - else + ++NumLDRDFormed; + } else { BuildMI(*MBB, InsertPos, dl, TII->get(NewOpc)) .addReg(EvenReg) .addReg(OddReg) .addReg(BaseReg).addReg(0).addImm(Offset) .addImm(Pred).addReg(PredReg); + ++NumSTRDFormed; + } + MBB->erase(Op0); + MBB->erase(Op1); // Add register allocation hints to form register pairs. MRI->setRegAllocationHint(EvenReg, ARMRI::RegPairEven, OddReg); diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 6298df9773f..71137dd75fe 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -308,7 +308,7 @@ const TargetRegisterClass *ARMRegisterInfo::getPointerRegClass() const { /// register class in the form of a pair of TargetRegisterClass iterators. std::pair ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, - std::pair Hint, + unsigned HintType, unsigned HintReg, const MachineFunction &MF) const { // Alternative register allocation orders when favoring even / odd registers // of register pairs. @@ -384,7 +384,13 @@ ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, }; - if (Hint.first == ARMRI::RegPairEven) { + if (HintType == ARMRI::RegPairEven) { + if (isPhysicalRegister(HintReg) && getRegisterPairEven(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + if (!STI.isTargetDarwin() && !hasFP(MF)) { if (!STI.isR9Reserved()) return std::make_pair(GPREven1, @@ -407,7 +413,13 @@ ARMRegisterInfo::getAllocationOrder(const TargetRegisterClass *RC, return std::make_pair(GPREven6, GPREven6 + (sizeof(GPREven6)/sizeof(unsigned))); } - } else if (Hint.first == ARMRI::RegPairOdd) { + } else if (HintType == ARMRI::RegPairOdd) { + if (isPhysicalRegister(HintReg) && getRegisterPairOdd(HintReg, MF) == 0) + // It's no longer possible to fulfill this hint. Return the default + // allocation order. + return std::make_pair(RC->allocation_order_begin(MF), + RC->allocation_order_end(MF)); + if (!STI.isTargetDarwin() && !hasFP(MF)) { if (!STI.isR9Reserved()) return std::make_pair(GPROdd1, @@ -453,6 +465,26 @@ ARMRegisterInfo::ResolveRegAllocHint(unsigned Type, unsigned Reg, return 0; } +void +ARMRegisterInfo::UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const { + MachineRegisterInfo *MRI = &MF.getRegInfo(); + std::pair Hint = MRI->getRegAllocationHint(Reg); + if ((Hint.first == (unsigned)ARMRI::RegPairOdd || + Hint.first == (unsigned)ARMRI::RegPairEven) && + Hint.second && TargetRegisterInfo::isVirtualRegister(Hint.second)) { + // If 'Reg' is one of the even / odd register pair and it's now changed + // (e.g. coalesced) into a different register. The other register of the + // pair allocation hint must be updated to reflect the relationship + // change. + unsigned OtherReg = Hint.second; + Hint = MRI->getRegAllocationHint(OtherReg); + if (Hint.second == Reg) + // Make sure the pair has not already divorced. + MRI->setRegAllocationHint(OtherReg, Hint.first, NewReg); + } +} + bool ARMRegisterInfo::requiresRegisterScavenging(const MachineFunction &MF) const { const ARMFunctionInfo *AFI = MF.getInfo(); @@ -1680,68 +1712,68 @@ unsigned ARMRegisterInfo::getRegisterPairEven(unsigned Reg, default: break; // Return 0 if either register of the pair is a special register. // So no R12, etc. - case ARM::R0: case ARM::R1: + case ARM::R1: return ARM::R0; - case ARM::R2: case ARM::R3: + case ARM::R3: // FIXME! return STI.isThumb() ? 0 : ARM::R2; - case ARM::R4: case ARM::R5: + case ARM::R5: return ARM::R4; - case ARM::R6: case ARM::R7: + case ARM::R7: return isReservedReg(MF, ARM::R7) ? 0 : ARM::R6; - case ARM::R8: case ARM::R9: + case ARM::R9: return isReservedReg(MF, ARM::R9) ? 0 :ARM::R8; - case ARM::R10: case ARM::R11: + case ARM::R11: return isReservedReg(MF, ARM::R11) ? 0 : ARM::R10; - case ARM::S0: case ARM::S1: + case ARM::S1: return ARM::S0; - case ARM::S2: case ARM::S3: + case ARM::S3: return ARM::S2; - case ARM::S4: case ARM::S5: + case ARM::S5: return ARM::S4; - case ARM::S6: case ARM::S7: + case ARM::S7: return ARM::S6; - case ARM::S8: case ARM::S9: + case ARM::S9: return ARM::S8; - case ARM::S10: case ARM::S11: + case ARM::S11: return ARM::S10; - case ARM::S12: case ARM::S13: + case ARM::S13: return ARM::S12; - case ARM::S14: case ARM::S15: + case ARM::S15: return ARM::S14; - case ARM::S16: case ARM::S17: + case ARM::S17: return ARM::S16; - case ARM::S18: case ARM::S19: + case ARM::S19: return ARM::S18; - case ARM::S20: case ARM::S21: + case ARM::S21: return ARM::S20; - case ARM::S22: case ARM::S23: + case ARM::S23: return ARM::S22; - case ARM::S24: case ARM::S25: + case ARM::S25: return ARM::S24; - case ARM::S26: case ARM::S27: + case ARM::S27: return ARM::S26; - case ARM::S28: case ARM::S29: + case ARM::S29: return ARM::S28; - case ARM::S30: case ARM::S31: + case ARM::S31: return ARM::S30; - case ARM::D0: case ARM::D1: + case ARM::D1: return ARM::D0; - case ARM::D2: case ARM::D3: + case ARM::D3: return ARM::D2; - case ARM::D4: case ARM::D5: + case ARM::D5: return ARM::D4; - case ARM::D6: case ARM::D7: + case ARM::D7: return ARM::D6; - case ARM::D8: case ARM::D9: + case ARM::D9: return ARM::D8; - case ARM::D10: case ARM::D11: + case ARM::D11: return ARM::D10; - case ARM::D12: case ARM::D13: + case ARM::D13: return ARM::D12; - case ARM::D14: case ARM::D15: + case ARM::D15: return ARM::D14; } @@ -1754,68 +1786,68 @@ unsigned ARMRegisterInfo::getRegisterPairOdd(unsigned Reg, default: break; // Return 0 if either register of the pair is a special register. // So no R12, etc. - case ARM::R0: case ARM::R1: + case ARM::R0: return ARM::R1; - case ARM::R2: case ARM::R3: + case ARM::R2: // FIXME! return STI.isThumb() ? 0 : ARM::R3; - case ARM::R4: case ARM::R5: + case ARM::R4: return ARM::R5; - case ARM::R6: case ARM::R7: + case ARM::R6: return isReservedReg(MF, ARM::R7) ? 0 : ARM::R7; - case ARM::R8: case ARM::R9: + case ARM::R8: return isReservedReg(MF, ARM::R9) ? 0 :ARM::R9; - case ARM::R10: case ARM::R11: + case ARM::R10: return isReservedReg(MF, ARM::R11) ? 0 : ARM::R11; - case ARM::S0: case ARM::S1: + case ARM::S0: return ARM::S1; - case ARM::S2: case ARM::S3: + case ARM::S2: return ARM::S3; - case ARM::S4: case ARM::S5: + case ARM::S4: return ARM::S5; - case ARM::S6: case ARM::S7: + case ARM::S6: return ARM::S7; - case ARM::S8: case ARM::S9: + case ARM::S8: return ARM::S9; - case ARM::S10: case ARM::S11: + case ARM::S10: return ARM::S11; - case ARM::S12: case ARM::S13: + case ARM::S12: return ARM::S13; - case ARM::S14: case ARM::S15: + case ARM::S14: return ARM::S15; - case ARM::S16: case ARM::S17: + case ARM::S16: return ARM::S17; - case ARM::S18: case ARM::S19: + case ARM::S18: return ARM::S19; - case ARM::S20: case ARM::S21: + case ARM::S20: return ARM::S21; - case ARM::S22: case ARM::S23: + case ARM::S22: return ARM::S23; - case ARM::S24: case ARM::S25: + case ARM::S24: return ARM::S25; - case ARM::S26: case ARM::S27: + case ARM::S26: return ARM::S27; - case ARM::S28: case ARM::S29: + case ARM::S28: return ARM::S29; - case ARM::S30: case ARM::S31: + case ARM::S30: return ARM::S31; - case ARM::D0: case ARM::D1: + case ARM::D0: return ARM::D1; - case ARM::D2: case ARM::D3: + case ARM::D2: return ARM::D3; - case ARM::D4: case ARM::D5: + case ARM::D4: return ARM::D5; - case ARM::D6: case ARM::D7: + case ARM::D6: return ARM::D7; - case ARM::D8: case ARM::D9: + case ARM::D8: return ARM::D9; - case ARM::D10: case ARM::D11: + case ARM::D10: return ARM::D11; - case ARM::D12: case ARM::D13: + case ARM::D12: return ARM::D13; - case ARM::D14: case ARM::D15: + case ARM::D14: return ARM::D15; } diff --git a/lib/Target/ARM/ARMRegisterInfo.h b/lib/Target/ARM/ARMRegisterInfo.h index b27e3b7c0ad..e8f4fd805d5 100644 --- a/lib/Target/ARM/ARMRegisterInfo.h +++ b/lib/Target/ARM/ARMRegisterInfo.h @@ -70,12 +70,15 @@ public: std::pair getAllocationOrder(const TargetRegisterClass *RC, - std::pair Hint, + unsigned HintType, unsigned HintReg, const MachineFunction &MF) const; unsigned ResolveRegAllocHint(unsigned Type, unsigned Reg, const MachineFunction &MF) const; + void UpdateRegAllocHint(unsigned Reg, unsigned NewReg, + MachineFunction &MF) const; + bool requiresRegisterScavenging(const MachineFunction &MF) const; bool hasFP(const MachineFunction &MF) const;