X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FStackSlotColoring.cpp;h=4fedc1a0421f5f63e2f70622c505dd7e7f4c52d9;hb=f45a82890e34984ad1e1e259f8fb902caddfb0b1;hp=c6ec9f5e6cf05f111082d582bf971e5483d6c3c8;hpb=d17e44769fcd2ca4052ea0cd8890c8290a94a881;p=oota-llvm.git diff --git a/lib/CodeGen/StackSlotColoring.cpp b/lib/CodeGen/StackSlotColoring.cpp index c6ec9f5e6cf..4fedc1a0421 100644 --- a/lib/CodeGen/StackSlotColoring.cpp +++ b/lib/CodeGen/StackSlotColoring.cpp @@ -15,9 +15,12 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" @@ -27,14 +30,19 @@ using namespace llvm; static cl::opt DisableSharing("no-stack-slot-sharing", cl::init(false), cl::Hidden, - cl::desc("Surpress slot sharing during stack coloring")); + cl::desc("Suppress slot sharing during stack coloring")); + +static cl::opt DCELimit("ssc-dce-limit", cl::init(-1), cl::Hidden); STATISTIC(NumEliminated, "Number of stack slots eliminated due to coloring"); +STATISTIC(NumDeadAccesses, + "Number of trivially dead stack accesses eliminated"); namespace { class VISIBILITY_HIDDEN StackSlotColoring : public MachineFunctionPass { LiveStacks* LS; MachineFrameInfo *MFI; + const TargetInstrInfo *TII; // SSIntervals - Spill slot intervals. std::vector SSIntervals; @@ -62,10 +70,13 @@ namespace { public: static char ID; // Pass identification - StackSlotColoring() : MachineFunctionPass((intptr_t)&ID), NextColor(-1) {} + StackSlotColoring() : MachineFunctionPass(&ID), NextColor(-1) {} virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); + + AU.addPreservedID(MachineLoopInfoID); + AU.addPreservedID(MachineDominatorsID); MachineFunctionPass::getAnalysisUsage(AU); } @@ -79,6 +90,7 @@ namespace { bool OverlapWithAssignments(LiveInterval *li, int Color) const; int ColorSlot(LiveInterval *li); bool ColorSlots(MachineFunction &MF); + bool removeDeadStores(MachineBasicBlock* MBB); }; } // end anonymous namespace @@ -177,7 +189,7 @@ int StackSlotColoring::ColorSlot(LiveInterval *li) { // Record the assignment. Assignments[Color].push_back(li); int FI = li->getStackSlotIndex(); - DOUT << "Assigning fi #" << FI << " to fi #" << Color << "\n"; + DOUT << "Assigning fi#" << FI << " to fi#" << Color << "\n"; // Change size and alignment of the allocated slot. If there are multiple // objects sharing the same slot, then make sure the size and alignment @@ -218,22 +230,38 @@ bool StackSlotColoring::ColorSlots(MachineFunction &MF) { MachineInstr &MI = *MII; for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { MachineOperand &MO = MI.getOperand(i); - if (!MO.isFrameIndex()) + if (!MO.isFI()) continue; int FI = MO.getIndex(); if (FI < 0) continue; - FI = SlotMapping[FI]; - if (FI == -1) + int NewFI = SlotMapping[FI]; + if (NewFI == -1) continue; - MO.setIndex(FI); + MO.setIndex(NewFI); + + // Update the MachineMemOperand for the new memory location. + // FIXME: We need a better method of managing these too. + SmallVector MMOs(MI.memoperands_begin(), + MI.memoperands_end()); + MI.clearMemOperands(MF); + const Value *OldSV = PseudoSourceValue::getFixedStack(FI); + for (unsigned i = 0, e = MMOs.size(); i != e; ++i) { + if (MMOs[i].getValue() == OldSV) { + MachineMemOperand MMO(PseudoSourceValue::getFixedStack(NewFI), + MMOs[i].getFlags(), MMOs[i].getOffset(), + MMOs[i].getSize(), MMOs[i].getAlignment()); + MI.addMemOperand(MF, MMO); + } else + MI.addMemOperand(MF, MMOs[i]); + } } } } // Delete unused stack slots. while (NextColor != -1) { - DOUT << "Removing unused stack object fi #" << NextColor << "\n"; + DOUT << "Removing unused stack object fi#" << NextColor << "\n"; MFI->RemoveStackObject(NextColor); NextColor = AllColors.find_next(NextColor); } @@ -241,10 +269,58 @@ bool StackSlotColoring::ColorSlots(MachineFunction &MF) { return true; } +/// removeDeadStores - Scan through a basic block and look for loads followed +/// by stores. If they're both using the same stack slot, then the store is +/// definitely dead. This could obviously be much more aggressive (consider +/// pairs with instructions between them), but such extensions might have a +/// considerable compile time impact. +bool StackSlotColoring::removeDeadStores(MachineBasicBlock* MBB) { + // FIXME: This could be much more aggressive, but we need to investigate + // the compile time impact of doing so. + bool changed = false; + + SmallVector toErase; + + for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); + I != E; ++I) { + if (DCELimit != -1 && (int)NumDeadAccesses >= DCELimit) + break; + + MachineBasicBlock::iterator NextMI = next(I); + if (NextMI == MBB->end()) continue; + + int FirstSS, SecondSS; + unsigned LoadReg = 0; + unsigned StoreReg = 0; + if (!(LoadReg = TII->isLoadFromStackSlot(I, FirstSS))) continue; + if (!(StoreReg = TII->isStoreToStackSlot(NextMI, SecondSS))) continue; + if (FirstSS != SecondSS || LoadReg != StoreReg || FirstSS == -1) continue; + + ++NumDeadAccesses; + changed = true; + + if (NextMI->findRegisterUseOperandIdx(LoadReg, true, 0) != -1) { + ++NumDeadAccesses; + toErase.push_back(I); + } + + toErase.push_back(NextMI); + ++I; + } + + for (SmallVector::iterator I = toErase.begin(), + E = toErase.end(); I != E; ++I) + (*I)->eraseFromParent(); + + return changed; +} + + bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { - DOUT << "******** Stack Slot Coloring ********\n"; + DOUT << "********** Stack Slot Coloring **********\n"; MFI = MF.getFrameInfo(); + TII = MF.getTarget().getInstrInfo(); LS = &getAnalysis(); bool Changed = false; @@ -261,5 +337,10 @@ bool StackSlotColoring::runOnMachineFunction(MachineFunction &MF) { Assignments[i].clear(); Assignments.clear(); + if (Changed) { + for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) + Changed |= removeDeadStores(I); + } + return Changed; }