diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2009-11-04 14:58:56 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2009-11-04 14:58:56 +0000 |
commit | 7ff99155c39edd73ebf1c6adfa023b1048fee9a4 (patch) | |
tree | b4dc751bcee540346911aa4115729eff2f991657 /lib/CodeGen/MachineLICM.cpp | |
parent | d1f06de484602e72707476a6152974847bac1570 (diff) | |
download | FreeBSD-src-7ff99155c39edd73ebf1c6adfa023b1048fee9a4.zip FreeBSD-src-7ff99155c39edd73ebf1c6adfa023b1048fee9a4.tar.gz |
Update LLVM to r86025.
Diffstat (limited to 'lib/CodeGen/MachineLICM.cpp')
-rw-r--r-- | lib/CodeGen/MachineLICM.cpp | 161 |
1 files changed, 128 insertions, 33 deletions
diff --git a/lib/CodeGen/MachineLICM.cpp b/lib/CodeGen/MachineLICM.cpp index f92ddb2..1306aa6 100644 --- a/lib/CodeGen/MachineLICM.cpp +++ b/lib/CodeGen/MachineLICM.cpp @@ -24,14 +24,15 @@ #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineLoopInfo.h" +#include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/PseudoSourceValue.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -41,7 +42,7 @@ STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops"); STATISTIC(NumCSEed, "Number of hoisted machine instructions CSEed"); namespace { - class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass { + class MachineLICM : public MachineFunctionPass { const TargetMachine *TM; const TargetInstrInfo *TII; const TargetRegisterInfo *TRI; @@ -55,12 +56,12 @@ namespace { // State that is updated as we process loops bool Changed; // True if a loop is changed. + bool FirstInLoop; // True if it's the first LICM in the loop. MachineLoop *CurLoop; // The current loop we are working on. MachineBasicBlock *CurPreheader; // The preheader for CurLoop. - // For each BB and opcode pair, keep a list of hoisted instructions. - DenseMap<std::pair<unsigned, unsigned>, - std::vector<const MachineInstr*> > CSEMap; + // For each opcode, keep a list of potentail CSE instructions. + DenseMap<unsigned, std::vector<const MachineInstr*> > CSEMap; public: static char ID; // Pass identification, replacement for typeid MachineLICM() : MachineFunctionPass(&ID) {} @@ -104,10 +105,21 @@ namespace { /// void HoistRegion(MachineDomTreeNode *N); + /// ExtractHoistableLoad - Unfold a load from the given machineinstr if + /// the load itself could be hoisted. Return the unfolded and hoistable + /// load, or null if the load couldn't be unfolded or if it wouldn't + /// be hoistable. + MachineInstr *ExtractHoistableLoad(MachineInstr *MI); + /// Hoist - When an instruction is found to only use loop invariant operands /// that is safe to hoist, this instruction is called to do the dirty work. /// - void Hoist(MachineInstr &MI); + void Hoist(MachineInstr *MI); + + /// InitCSEMap - Initialize the CSE map with instructions that are in the + /// current loop preheader that may become duplicates of instructions that + /// are hoisted out of the loop. + void InitCSEMap(MachineBasicBlock *BB); }; } // end anonymous namespace @@ -133,7 +145,7 @@ static bool LoopIsOuterMostWithPreheader(MachineLoop *CurLoop) { bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { DEBUG(errs() << "******** Machine LICM ********\n"); - Changed = false; + Changed = FirstInLoop = false; TM = &MF.getTarget(); TII = TM->getInstrInfo(); TRI = TM->getRegisterInfo(); @@ -145,8 +157,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { DT = &getAnalysis<MachineDominatorTree>(); AA = &getAnalysis<AliasAnalysis>(); - for (MachineLoopInfo::iterator - I = LI->begin(), E = LI->end(); I != E; ++I) { + for (MachineLoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I) { CurLoop = *I; // Only visit outer-most preheader-sporting loops. @@ -163,7 +174,11 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) { if (!CurPreheader) continue; + // CSEMap is initialized for loop header when the first instruction is + // being hoisted. + FirstInLoop = true; HoistRegion(DT->getNode(CurLoop->getHeader())); + CSEMap.clear(); } return Changed; @@ -184,10 +199,7 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N) { for (MachineBasicBlock::iterator MII = BB->begin(), E = BB->end(); MII != E; ) { MachineBasicBlock::iterator NextMII = MII; ++NextMII; - MachineInstr &MI = *MII; - - Hoist(MI); - + Hoist(&*MII); MII = NextMII; } @@ -368,42 +380,125 @@ static const MachineInstr *LookForDuplicate(const MachineInstr *MI, return 0; } +MachineInstr *MachineLICM::ExtractHoistableLoad(MachineInstr *MI) { + // If not, we may be able to unfold a load and hoist that. + // First test whether the instruction is loading from an amenable + // memory location. + if (!MI->getDesc().mayLoad()) return 0; + if (!MI->hasOneMemOperand()) return 0; + MachineMemOperand *MMO = *MI->memoperands_begin(); + if (MMO->isVolatile()) return 0; + MachineFunction &MF = *MI->getParent()->getParent(); + if (!MMO->getValue()) return 0; + if (const PseudoSourceValue *PSV = + dyn_cast<PseudoSourceValue>(MMO->getValue())) { + if (!PSV->isConstant(MF.getFrameInfo())) return 0; + } else { + if (!AA->pointsToConstantMemory(MMO->getValue())) return 0; + } + // Next determine the register class for a temporary register. + unsigned LoadRegIndex; + unsigned NewOpc = + TII->getOpcodeAfterMemoryUnfold(MI->getOpcode(), + /*UnfoldLoad=*/true, + /*UnfoldStore=*/false, + &LoadRegIndex); + if (NewOpc == 0) return 0; + const TargetInstrDesc &TID = TII->get(NewOpc); + if (TID.getNumDefs() != 1) return 0; + const TargetRegisterClass *RC = TID.OpInfo[LoadRegIndex].getRegClass(TRI); + // Ok, we're unfolding. Create a temporary register and do the unfold. + unsigned Reg = RegInfo->createVirtualRegister(RC); + SmallVector<MachineInstr *, 2> NewMIs; + bool Success = + TII->unfoldMemoryOperand(MF, MI, Reg, + /*UnfoldLoad=*/true, /*UnfoldStore=*/false, + NewMIs); + (void)Success; + assert(Success && + "unfoldMemoryOperand failed when getOpcodeAfterMemoryUnfold " + "succeeded!"); + assert(NewMIs.size() == 2 && + "Unfolded a load into multiple instructions!"); + MachineBasicBlock *MBB = MI->getParent(); + MBB->insert(MI, NewMIs[0]); + MBB->insert(MI, NewMIs[1]); + // If unfolding produced a load that wasn't loop-invariant or profitable to + // hoist, discard the new instructions and bail. + if (!IsLoopInvariantInst(*NewMIs[0]) || !IsProfitableToHoist(*NewMIs[0])) { + NewMIs[0]->eraseFromParent(); + NewMIs[1]->eraseFromParent(); + return 0; + } + // Otherwise we successfully unfolded a load that we can hoist. + MI->eraseFromParent(); + return NewMIs[0]; +} + +void MachineLICM::InitCSEMap(MachineBasicBlock *BB) { + for (MachineBasicBlock::iterator I = BB->begin(),E = BB->end(); I != E; ++I) { + const MachineInstr *MI = &*I; + // FIXME: For now, only hoist re-materilizable instructions. LICM will + // increase register pressure. We want to make sure it doesn't increase + // spilling. + if (TII->isTriviallyReMaterializable(MI, AA)) { + unsigned Opcode = MI->getOpcode(); + DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator + CI = CSEMap.find(Opcode); + if (CI != CSEMap.end()) + CI->second.push_back(MI); + else { + std::vector<const MachineInstr*> CSEMIs; + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); + } + } + } +} + /// Hoist - When an instruction is found to use only loop invariant operands /// that are safe to hoist, this instruction is called to do the dirty work. /// -void MachineLICM::Hoist(MachineInstr &MI) { - if (!IsLoopInvariantInst(MI)) return; - if (!IsProfitableToHoist(MI)) return; +void MachineLICM::Hoist(MachineInstr *MI) { + // First check whether we should hoist this instruction. + if (!IsLoopInvariantInst(*MI) || !IsProfitableToHoist(*MI)) { + // If not, try unfolding a hoistable load. + MI = ExtractHoistableLoad(MI); + if (!MI) return; + } // Now move the instructions to the predecessor, inserting it before any // terminator instructions. DEBUG({ - errs() << "Hoisting " << MI; + errs() << "Hoisting " << *MI; if (CurPreheader->getBasicBlock()) errs() << " to MachineBasicBlock " << CurPreheader->getBasicBlock()->getName(); - if (MI.getParent()->getBasicBlock()) + if (MI->getParent()->getBasicBlock()) errs() << " from MachineBasicBlock " - << MI.getParent()->getBasicBlock()->getName(); + << MI->getParent()->getBasicBlock()->getName(); errs() << "\n"; }); + // If this is the first instruction being hoisted to the preheader, + // initialize the CSE map with potential common expressions. + InitCSEMap(CurPreheader); + // Look for opportunity to CSE the hoisted instruction. - std::pair<unsigned, unsigned> BBOpcPair = - std::make_pair(CurPreheader->getNumber(), MI.getOpcode()); - DenseMap<std::pair<unsigned, unsigned>, - std::vector<const MachineInstr*> >::iterator CI = CSEMap.find(BBOpcPair); + unsigned Opcode = MI->getOpcode(); + DenseMap<unsigned, std::vector<const MachineInstr*> >::iterator + CI = CSEMap.find(Opcode); bool DoneCSE = false; if (CI != CSEMap.end()) { - const MachineInstr *Dup = LookForDuplicate(&MI, CI->second, RegInfo); + const MachineInstr *Dup = LookForDuplicate(MI, CI->second, RegInfo); if (Dup) { - DEBUG(errs() << "CSEing " << MI << " with " << *Dup); - for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { - const MachineOperand &MO = MI.getOperand(i); + DEBUG(errs() << "CSEing " << *MI << " with " << *Dup); + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + const MachineOperand &MO = MI->getOperand(i); if (MO.isReg() && MO.isDef()) RegInfo->replaceRegWith(MO.getReg(), Dup->getOperand(i).getReg()); } - MI.eraseFromParent(); + MI->eraseFromParent(); DoneCSE = true; ++NumCSEed; } @@ -411,15 +506,15 @@ void MachineLICM::Hoist(MachineInstr &MI) { // Otherwise, splice the instruction to the preheader. if (!DoneCSE) { - CurPreheader->splice(CurPreheader->getFirstTerminator(), - MI.getParent(), &MI); + CurPreheader->splice(CurPreheader->getFirstTerminator(),MI->getParent(),MI); + // Add to the CSE map. if (CI != CSEMap.end()) - CI->second.push_back(&MI); + CI->second.push_back(MI); else { std::vector<const MachineInstr*> CSEMIs; - CSEMIs.push_back(&MI); - CSEMap.insert(std::make_pair(BBOpcPair, CSEMIs)); + CSEMIs.push_back(MI); + CSEMap.insert(std::make_pair(Opcode, CSEMIs)); } } |