//
// The LLVM Compiler Infrastructure
//
-// This file was developed by Bill Wendling and is distributed under the
-// University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "machine-licm"
-#include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/Statistic.h"
-#include "llvm/CodeGen/MachineBasicBlock.h"
+#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineDominators.h"
-#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
-#include "llvm/CodeGen/Passes.h"
-#include "llvm/Support/CFG.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Target/MRegisterInfo.h"
-#include "llvm/Target/TargetInstrInfo.h"
-#include "llvm/Target/TargetMachine.h"
using namespace llvm;
-namespace {
- // Hidden options to help debugging
- cl::opt<bool>
- PerformLICM("machine-licm",
- cl::init(false), cl::Hidden,
- cl::desc("Perform loop-invariant code motion on machine code"));
-}
-
STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loops");
namespace {
class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass {
+ const TargetMachine *TM;
const TargetInstrInfo *TII;
MachineFunction *CurMF; // Current MachineFunction
// Various analyses that we use...
MachineLoopInfo *LI; // Current MachineLoopInfo
MachineDominatorTree *DT; // Machine dominator tree for the current Loop
+ MachineRegisterInfo *RegInfo; // Machine register information
// State that is updated as we process loops
bool Changed; // True if a loop is changed.
MachineLoop *CurLoop; // The current loop we are working on.
-
- // Map the def of a virtual register to the machine instruction.
- IndexedMap<const MachineInstr*, VirtReg2IndexFunctor> VRegDefs;
public:
static char ID; // Pass identification, replacement for typeid
MachineLICM() : MachineFunctionPass((intptr_t)&ID) {}
AU.setPreservesCFG();
AU.addRequired<MachineLoopInfo>();
AU.addRequired<MachineDominatorTree>();
+ AU.addPreserved<MachineLoopInfo>();
+ AU.addPreserved<MachineDominatorTree>();
+ MachineFunctionPass::getAnalysisUsage(AU);
}
private:
/// VisitAllLoops - Visit all of the loops in depth first order and try to
HoistRegion(DT->getNode(L->getHeader()));
}
- /// MapVirtualRegisterDefs - Create a map of which machine instruction
- /// defines a virtual register.
- ///
- void MapVirtualRegisterDefs();
-
/// IsInSubLoop - A little predicate that returns true if the specified
/// basic block is in a subloop of the current one, not the current one
/// itself.
/// MoveInstToEndOfBlock - Moves the machine instruction to the bottom of
/// the predecessor basic block (but before the terminator instructions).
///
- void MoveInstToEndOfBlock(MachineBasicBlock *MBB, MachineInstr *MI) {
+ void MoveInstToEndOfBlock(MachineBasicBlock *ToMBB,
+ MachineBasicBlock *FromMBB,
+ MachineInstr *MI) {
DEBUG({
DOUT << "Hoisting " << *MI;
- if (MBB->getBasicBlock())
+ if (ToMBB->getBasicBlock())
DOUT << " to MachineBasicBlock "
- << MBB->getBasicBlock()->getName();
+ << ToMBB->getBasicBlock()->getName();
DOUT << "\n";
});
- MachineBasicBlock::iterator Iter = MBB->getFirstTerminator();
- MBB->insert(Iter, MI);
+
+ MachineBasicBlock::iterator WhereIter = ToMBB->getFirstTerminator();
+ MachineBasicBlock::iterator To, From = FromMBB->begin();
+
+ while (&*From != MI)
+ ++From;
+
+ assert(From != FromMBB->end() && "Didn't find instr in BB!");
+
+ To = From;
+ ToMBB->splice(WhereIter, FromMBB, From, ++To);
++NumHoisted;
}
/// loop.
///
bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
- if (!PerformLICM) return false; // For debugging.
-
DOUT << "******** Machine LICM ********\n";
Changed = false;
CurMF = &MF;
- TII = CurMF->getTarget().getInstrInfo();
+ TM = &CurMF->getTarget();
+ TII = TM->getInstrInfo();
+ RegInfo = &CurMF->getRegInfo();
// Get our Loop information...
LI = &getAnalysis<MachineLoopInfo>();
DT = &getAnalysis<MachineDominatorTree>();
- MapVirtualRegisterDefs();
-
for (MachineLoopInfo::iterator
I = LI->begin(), E = LI->end(); I != E; ++I) {
CurLoop = *I;
return Changed;
}
-/// MapVirtualRegisterDefs - Create a map of which machine instruction defines a
-/// virtual register.
-///
-void MachineLICM::MapVirtualRegisterDefs() {
- for (MachineFunction::const_iterator
- I = CurMF->begin(), E = CurMF->end(); I != E; ++I) {
- const MachineBasicBlock &MBB = *I;
-
- for (MachineBasicBlock::const_iterator
- II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
- const MachineInstr &MI = *II;
-
- for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = MI.getOperand(i);
-
- if (MO.isRegister() && MO.isDef() &&
- MRegisterInfo::isVirtualRegister(MO.getReg())) {
- VRegDefs.grow(MO.getReg());
- VRegDefs[MO.getReg()] = &MI;
- }
- }
- }
- }
-}
-
/// HoistRegion - Walk the specified region of the CFG (defined by all blocks
/// dominated by the specified block, and that are in the current loop) in depth
/// first order w.r.t the DominatorTree. This allows us to visit definitions
/// IsLoopInvariantInst - Returns true if the instruction is loop
/// invariant. I.e., all virtual register operands are defined outside of the
-/// loop, physical registers aren't accessed (explicitly or implicitly), and the
-/// instruction is hoistable.
+/// loop, physical registers aren't accessed explicitly, and there are no side
+/// effects that aren't captured by the operands or other flags.
///
bool MachineLICM::IsLoopInvariantInst(MachineInstr &I) {
+ const TargetInstrDesc &TID = I.getDesc();
+
+ // Ignore stuff that we obviously can't hoist.
+ if (TID.mayStore() || TID.isCall() || TID.isReturn() || TID.isBranch() ||
+ TID.hasUnmodeledSideEffects())
+ return false;
+
+ if (TID.mayLoad()) {
+ // Okay, this instruction does a load. As a refinement, allow the target
+ // to decide whether the loaded value is actually a constant. If so, we
+ // can actually use it as a load.
+ if (!TII->isInvariantLoad(&I)) {
+ // FIXME: we should be able to sink loads with no other side effects if
+ // there is nothing that can change memory from here until the end of
+ // block. This is a trivial form of alias analysis.
+ return false;
+ }
+ }
+
+
DEBUG({
DOUT << "--- Checking if we can hoist " << I;
- if (I.getInstrDescriptor()->ImplicitUses) {
+ if (I.getDesc().getImplicitUses()) {
DOUT << " * Instruction has implicit uses:\n";
- const TargetMachine &TM = CurMF->getTarget();
- const MRegisterInfo *MRI = TM.getRegisterInfo();
- const unsigned *ImpUses = I.getInstrDescriptor()->ImplicitUses;
-
- for (; *ImpUses; ++ImpUses)
- DOUT << " -> " << MRI->getName(*ImpUses) << "\n";
+ const TargetRegisterInfo *TRI = TM->getRegisterInfo();
+ for (const unsigned *ImpUses = I.getDesc().getImplicitUses();
+ *ImpUses; ++ImpUses)
+ DOUT << " -> " << TRI->getName(*ImpUses) << "\n";
}
- if (I.getInstrDescriptor()->ImplicitDefs) {
+ if (I.getDesc().getImplicitDefs()) {
DOUT << " * Instruction has implicit defines:\n";
- const TargetMachine &TM = CurMF->getTarget();
- const MRegisterInfo *MRI = TM.getRegisterInfo();
- const unsigned *ImpDefs = I.getInstrDescriptor()->ImplicitDefs;
-
- for (; *ImpDefs; ++ImpDefs)
- DOUT << " -> " << MRI->getName(*ImpDefs) << "\n";
+ const TargetRegisterInfo *TRI = TM->getRegisterInfo();
+ for (const unsigned *ImpDefs = I.getDesc().getImplicitDefs();
+ *ImpDefs; ++ImpDefs)
+ DOUT << " -> " << TRI->getName(*ImpDefs) << "\n";
}
- if (TII->hasUnmodelledSideEffects(&I))
- DOUT << " * Instruction has side effects.\n";
+ //if (TII->hasUnmodelledSideEffects(&I))
+ //DOUT << " * Instruction has side effects.\n";
});
-#if 0
- // FIXME: Don't hoist if this instruction implicitly reads physical registers.
- if (I.getInstrDescriptor()->ImplicitUses ||
- I.getInstrDescriptor()->ImplicitDefs)
- return false;
-#endif
-
// The instruction is loop invariant if all of its operands are loop-invariant
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = I.getOperand(i);
unsigned Reg = MO.getReg();
// Don't hoist instructions that access physical registers.
- if (!MRegisterInfo::isVirtualRegister(Reg))
+ if (!TargetRegisterInfo::isVirtualRegister(Reg))
return false;
- assert(VRegDefs[Reg] && "Machine instr not mapped for this vreg?");
+ assert(RegInfo->getVRegDef(Reg)&&"Machine instr not mapped for this vreg?");
// If the loop contains the definition of an operand, then the instruction
// isn't loop invariant.
- if (CurLoop->contains(VRegDefs[Reg]->getParent()))
+ if (CurLoop->contains(RegInfo->getVRegDef(Reg)->getParent()))
return false;
}
- // Don't hoist something that has side effects.
- if (TII->hasUnmodelledSideEffects(&I)) return false;
-
// If we got this far, the instruction is loop invariant!
return true;
}
"The predecessor doesn't feed directly into the loop header!");
// Now move the instructions to the predecessor.
- MachineInstr *NewMI = MI.clone();
- MoveInstToEndOfBlock(MBB, NewMI);
-
- // Update VRegDefs.
- for (unsigned i = 0, e = NewMI->getNumOperands(); i != e; ++i) {
- const MachineOperand &MO = NewMI->getOperand(i);
-
- if (MO.isRegister() && MO.isDef() &&
- MRegisterInfo::isVirtualRegister(MO.getReg())) {
- VRegDefs.grow(MO.getReg());
- VRegDefs[MO.getReg()] = NewMI;
- }
- }
-
- // Hoisting was successful! Remove bothersome instruction now.
- MI.getParent()->remove(&MI);
+ MoveInstToEndOfBlock(MBB, MI.getParent(), &MI);
Changed = true;
}