diff --git a/llvm/lib/CodeGen/StackSlotColoring.cpp b/llvm/lib/CodeGen/StackSlotColoring.cpp index dd36bdd6041e..bc8353a31825 100644 --- a/llvm/lib/CodeGen/StackSlotColoring.cpp +++ b/llvm/lib/CodeGen/StackSlotColoring.cpp @@ -45,8 +45,10 @@ ColorWithRegs("color-ss-with-regs", static cl::opt DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden); STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring"); -STATISTIC(NumDead, "Number of trivially dead stack accesses eliminated"); STATISTIC(NumRegRepl, "Number of stack slot refs replaced with reg refs"); +STATISTIC(NumLoadElim, "Number of load eliminated"); +STATISTIC(NumStoreElim, "Number of stores eliminated"); +STATISTIC(NumDead, "Number of trivially dead stack accesses eliminated"); namespace { class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass { @@ -115,8 +117,15 @@ namespace { BitVector &SlotIsReg); void RewriteInstruction(MachineInstr *MI, int OldFI, int NewFI, MachineFunction &MF); + bool PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); + bool PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg); void UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, - unsigned Reg, MachineFunction &MF); + unsigned Reg, const TargetRegisterClass *RC, + MachineFunction &MF); bool AllMemRefsCanBeUnfolded(int SS); bool RemoveDeadStores(MachineBasicBlock* MBB); }; @@ -384,11 +393,13 @@ bool StackSlotColoring::ColorSlots(MachineFunction &MF) { SmallVector &RefMIs = SSRefs[SS]; for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) - if (isReg) - // Rewrite to use a register instead. - UnfoldAndRewriteInstruction(RefMIs[i], SS, NewFI, MF); - else + if (!isReg) RewriteInstruction(RefMIs[i], SS, NewFI, MF); + else { + // Rewrite to use a register instead. + const TargetRegisterClass *RC = LS->getIntervalRegClass(SS); + UnfoldAndRewriteInstruction(RefMIs[i], SS, NewFI, RC, MF); + } } // Delete unused stack slots. @@ -407,6 +418,10 @@ bool StackSlotColoring::AllMemRefsCanBeUnfolded(int SS) { SmallVector &RefMIs = SSRefs[SS]; for (unsigned i = 0, e = RefMIs.size(); i != e; ++i) { MachineInstr *MI = RefMIs[i]; + if (TII->isLoadFromStackSlot(MI, SS) || + TII->isStoreToStackSlot(MI, SS)) + // Restore and spill will become copies. + return true; if (!TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), false, false)) return false; for (unsigned j = 0, ee = MI->getNumOperands(); j != ee; ++j) { @@ -451,19 +466,118 @@ void StackSlotColoring::RewriteInstruction(MachineInstr *MI, int OldFI, } } +/// PropagateBackward - Traverse backward and look for the definition of +/// OldReg. If it can successfully update all of the references with NewReg, +/// do so and return true. +bool StackSlotColoring::PropagateBackward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + SmallVector Refs; + while (--MII != MBB->begin()) { + bool FoundDef = false; // Not counting 2address def. + bool FoundUse = false; + bool FoundKill = false; + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isUse()) { + FoundUse = true; + if (MO.isKill()) + FoundKill = true; + Refs.push_back(&MO); + } else { + Refs.push_back(&MO); + if (!MII->isRegTiedToUseOperand(i)) + FoundDef = true; + } + } else if (TRI->regsOverlap(Reg, NewReg)) { + return false; + } else if (TRI->regsOverlap(Reg, OldReg)) { + if (!MO.isUse() || !MO.isKill()) + return false; + } + } + if (FoundDef) { + for (unsigned i = 0, e = Refs.size(); i != e; ++i) + Refs[i]->setReg(NewReg); + return true; + } + } + return false; +} + +/// PropagateForward - Traverse forward and look for the kill of OldReg. If +/// it can successfully update all of the uses with NewReg, do so and +/// return true. +bool StackSlotColoring::PropagateForward(MachineBasicBlock::iterator MII, + MachineBasicBlock *MBB, + unsigned OldReg, unsigned NewReg) { + SmallVector Uses; + while (++MII != MBB->end()) { + bool FoundUse = false; + bool FoundKill = false; + for (unsigned i = 0, e = MII->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MII->getOperand(i); + if (!MO.isReg()) + continue; + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (Reg == OldReg) { + if (MO.isDef()) + return false; + FoundUse = true; + if (MO.isKill()) + FoundKill = true; + Uses.push_back(&MO); + } else if (TRI->regsOverlap(Reg, NewReg) || + TRI->regsOverlap(Reg, OldReg)) + return false; + } + if (FoundKill) { + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + Uses[i]->setReg(NewReg); + return true; + } + } + return false; +} + /// UnfoldAndRewriteInstruction - Rewrite specified instruction by unfolding /// folded memory references and replacing those references with register /// references instead. void StackSlotColoring::UnfoldAndRewriteInstruction(MachineInstr *MI, int OldFI, - unsigned Reg, - MachineFunction &MF) { + unsigned Reg, + const TargetRegisterClass *RC, + MachineFunction &MF) { MachineBasicBlock *MBB = MI->getParent(); - SmallVector NewMIs; - bool Success = TII->unfoldMemoryOperand(MF, MI, Reg, false, false, NewMIs); - assert(Success && "Failed to unfold!"); - MBB->insert(MI, NewMIs[0]); + if (unsigned DstReg = TII->isLoadFromStackSlot(MI, OldFI)) { + if (PropagateForward(MI, MBB, DstReg, Reg)) { + ++NumLoadElim; + } else { + TII->copyRegToReg(*MBB, MI, DstReg, Reg, RC, RC); + ++NumRegRepl; + } + } else if (unsigned SrcReg = TII->isStoreToStackSlot(MI, OldFI)) { + if (MI->killsRegister(SrcReg) && PropagateBackward(MI, MBB, SrcReg, Reg)) { + ++NumStoreElim; + } else { + TII->copyRegToReg(*MBB, MI, Reg, SrcReg, RC, RC); + ++NumRegRepl; + } + } else { + SmallVector NewMIs; + bool Success = TII->unfoldMemoryOperand(MF, MI, Reg, false, false, NewMIs); + assert(Success && "Failed to unfold!"); + MBB->insert(MI, NewMIs[0]); + ++NumRegRepl; + } MBB->erase(MI); - ++NumRegRepl; } /// RemoveDeadStores - Scan through a basic block and look for loads followed