Bill Wendling 2007-12-08 01:47:01 +00:00
parent 086b2c4537
commit 4375173ba0
1 changed files with 52 additions and 56 deletions

View File

@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#define DEBUG_TYPE "machine-licm" #define DEBUG_TYPE "machine-licm"
#include "llvm/ADT/IndexedMap.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineBasicBlock.h"
@ -27,7 +28,6 @@
#include "llvm/Support/Debug.h" #include "llvm/Support/Debug.h"
#include "llvm/Target/MRegisterInfo.h" #include "llvm/Target/MRegisterInfo.h"
#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachine.h"
#include <map>
using namespace llvm; using namespace llvm;
@ -35,9 +35,12 @@ namespace {
// Hidden options to help debugging // Hidden options to help debugging
cl::opt<bool> cl::opt<bool>
PerformLICM("machine-licm", PerformLICM("machine-licm",
cl::init(false), cl::Hidden); cl::init(false), cl::Hidden,
cl::desc("Perform loop-invariant code motion on machine code"));
} }
STATISTIC(NumHoisted, "Number of machine instructions hoisted out of loop");
namespace { namespace {
class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass { class VISIBILITY_HIDDEN MachineLICM : public MachineFunctionPass {
// Various analyses that we use... // Various analyses that we use...
@ -51,7 +54,7 @@ namespace {
MachineLoop *CurLoop; // The current loop we are working on. MachineLoop *CurLoop; // The current loop we are working on.
// Map the def of a virtual register to the machine instruction. // Map the def of a virtual register to the machine instruction.
std::map<unsigned, const MachineInstr*> VRegDefs; IndexedMap<const MachineInstr*, VirtReg2IndexFunctor> VRegDefs;
public: public:
static char ID; // Pass identification, replacement for typeid static char ID; // Pass identification, replacement for typeid
MachineLICM() : MachineFunctionPass((intptr_t)&ID) {} MachineLICM() : MachineFunctionPass((intptr_t)&ID) {}
@ -66,16 +69,23 @@ namespace {
AU.addRequired<MachineDominatorTree>(); AU.addRequired<MachineDominatorTree>();
} }
private: private:
/// GatherAllLoops - Get all loops in depth first order. /// VisitAllLoops - Visit all of the loops in depth first order and try to
/// hoist invariant instructions from them.
/// ///
void GatherAllLoops(MachineLoop *L, SmallVectorImpl<MachineLoop*> &Loops) { void VisitAllLoops(MachineLoop *L) {
const std::vector<MachineLoop*> &SubLoops = L->getSubLoops(); const std::vector<MachineLoop*> &SubLoops = L->getSubLoops();
for (MachineLoop::iterator for (MachineLoop::iterator
I = SubLoops.begin(), E = SubLoops.end(); I != E; ++I) I = SubLoops.begin(), E = SubLoops.end(); I != E; ++I) {
GatherAllLoops(*I, Loops); MachineLoop *ML = *I;
Loops.push_back(L); // Traverse the body of the loop in depth first order on the dominator
// tree so that we are guaranteed to see definitions before we see uses.
VisitAllLoops(ML);
HoistRegion(DT->getNode(ML->getHeader()));
}
HoistRegion(DT->getNode(L->getHeader()));
} }
/// MapVirtualRegisterDefs - Create a map of which machine instruction /// MapVirtualRegisterDefs - Create a map of which machine instruction
@ -104,8 +114,12 @@ namespace {
/// ///
bool CanHoistInst(MachineInstr &I) const { bool CanHoistInst(MachineInstr &I) const {
const TargetInstrDescriptor *TID = I.getInstrDescriptor(); const TargetInstrDescriptor *TID = I.getInstrDescriptor();
MachineOpCode Opcode = TID->Opcode;
// Don't hoist if this instruction implicitly reads physical registers or
// doesn't take any operands.
if (TID->ImplicitUses || !I.getNumOperands()) return false;
MachineOpCode Opcode = TID->Opcode;
return TII->isTriviallyReMaterializable(&I) && return TII->isTriviallyReMaterializable(&I) &&
// FIXME: Below necessary? // FIXME: Below necessary?
!(TII->isReturn(Opcode) || !(TII->isReturn(Opcode) ||
@ -137,12 +151,13 @@ namespace {
Preds.push_back(*I); Preds.push_back(*I);
} }
/// MoveInstToBlock - Moves the machine instruction to the bottom of the /// MoveInstToEndOfBlock - Moves the machine instruction to the bottom of
/// predecessor basic block (but before the terminator instructions). /// the predecessor basic block (but before the terminator instructions).
/// ///
void MoveInstToBlock(MachineBasicBlock *MBB, MachineInstr *MI) { void MoveInstToEndOfBlock(MachineBasicBlock *MBB, MachineInstr *MI) {
MachineBasicBlock::iterator Iter = MBB->getFirstTerminator(); MachineBasicBlock::iterator Iter = MBB->getFirstTerminator();
MBB->insert(Iter, MI); MBB->insert(Iter, MI);
++NumHoisted;
} }
/// HoistRegion - Walk the specified region of the CFG (defined by all /// HoistRegion - Walk the specified region of the CFG (defined by all
@ -156,7 +171,7 @@ namespace {
/// Hoist - When an instruction is found to only use loop invariant operands /// 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. /// that is safe to hoist, this instruction is called to do the dirty work.
/// ///
bool Hoist(MachineInstr &MI); void Hoist(MachineInstr &MI);
}; };
char MachineLICM::ID = 0; char MachineLICM::ID = 0;
@ -188,17 +203,7 @@ bool MachineLICM::runOnMachineFunction(MachineFunction &MF) {
// Visit all of the instructions of the loop. We want to visit the subloops // Visit all of the instructions of the loop. We want to visit the subloops
// first, though, so that we can hoist their invariants first into their // first, though, so that we can hoist their invariants first into their
// containing loop before we process that loop. // containing loop before we process that loop.
SmallVector<MachineLoop*, 16> Loops; VisitAllLoops(L);
GatherAllLoops(L, Loops);
for (SmallVector<MachineLoop*, 8>::iterator
II = Loops.begin(), IE = Loops.end(); II != IE; ++II) {
L = *II;
// Traverse the body of the loop in depth first order on the dominator
// tree so that we are guaranteed to see definitions before we see uses.
HoistRegion(DT->getNode(L->getHeader()));
}
} }
return Changed; return Changed;
@ -216,7 +221,7 @@ void MachineLICM::MapVirtualRegisterDefs(const MachineFunction &MF) {
II = MBB.begin(), IE = MBB.end(); II != IE; ++II) { II = MBB.begin(), IE = MBB.end(); II != IE; ++II) {
const MachineInstr &MI = *II; const MachineInstr &MI = *II;
if (MI.getNumOperands() > 0) { for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) {
const MachineOperand &MO = MI.getOperand(0); const MachineOperand &MO = MI.getOperand(0);
if (MO.isRegister() && MO.isDef() && if (MO.isRegister() && MO.isDef() &&
@ -249,9 +254,7 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N) {
// Try hoisting the instruction out of the loop. We can only do this if // Try hoisting the instruction out of the loop. We can only do this if
// all of the operands of the instruction are loop invariant and if it is // all of the operands of the instruction are loop invariant and if it is
// safe to hoist the instruction. // safe to hoist the instruction.
if (Hoist(MI)) Hoist(MI);
// Hoisting was successful! Remove bothersome instruction now.
MI.getParent()->remove(&MI);
} }
const std::vector<MachineDomTreeNode*> &Children = N->getChildren(); const std::vector<MachineDomTreeNode*> &Children = N->getChildren();
@ -266,12 +269,6 @@ void MachineLICM::HoistRegion(MachineDomTreeNode *N) {
/// instruction is hoistable. /// instruction is hoistable.
/// ///
bool MachineLICM::isLoopInvariantInst(MachineInstr &I) { bool MachineLICM::isLoopInvariantInst(MachineInstr &I) {
const TargetInstrDescriptor *TID = I.getInstrDescriptor();
// Don't hoist if this instruction implicitly reads physical registers or
// doesn't take any operands.
if (TID->ImplicitUses || !I.getNumOperands()) return false;
if (!CanHoistInst(I)) return false; if (!CanHoistInst(I)) return false;
// The instruction is loop invariant if all of its operands are loop-invariant // The instruction is loop invariant if all of its operands are loop-invariant
@ -287,7 +284,7 @@ bool MachineLICM::isLoopInvariantInst(MachineInstr &I) {
if (!MRegisterInfo::isVirtualRegister(Reg)) if (!MRegisterInfo::isVirtualRegister(Reg))
return false; return false;
assert(VRegDefs[Reg] && "Machine instr not mapped for this vreg?!"); assert(VRegDefs[Reg] && "Machine instr not mapped for this vreg?");
// If the loop contains the definition of an operand, then the instruction // If the loop contains the definition of an operand, then the instruction
// isn't loop invariant. // isn't loop invariant.
@ -302,35 +299,34 @@ bool MachineLICM::isLoopInvariantInst(MachineInstr &I) {
/// Hoist - When an instruction is found to only use loop invariant operands /// 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. /// that is safe to hoist, this instruction is called to do the dirty work.
/// ///
bool MachineLICM::Hoist(MachineInstr &MI) { void MachineLICM::Hoist(MachineInstr &MI) {
if (!isLoopInvariantInst(MI)) return false; if (!isLoopInvariantInst(MI)) return;
std::vector<MachineBasicBlock*> Preds; std::vector<MachineBasicBlock*> Preds;
// Non-back-edge predecessors. // Non-back-edge predecessors.
FindPredecessors(Preds); FindPredecessors(Preds);
if (Preds.empty()) return false;
// Check that the predecessors are qualified to take the hoisted // Either we don't have any predecessors(?!) or we have more than one, which
// instruction. I.e., there is only one edge from each predecessor, and it's // is forbidden.
// to the loop header. if (Preds.empty() || Preds.size() != 1) return;
for (std::vector<MachineBasicBlock*>::iterator
I = Preds.begin(), E = Preds.end(); I != E; ++I) {
MachineBasicBlock *MBB = *I;
// FIXME: We are assuming at first that the basic blocks coming into this // Check that the predecessor is qualified to take the hoisted
// loop have only one successor each. This isn't the case in general because // instruction. I.e., there is only one edge from the predecessor, and it's to
// we haven't broken critical edges or added preheaders. // the loop header.
if (MBB->succ_size() != 1) return false; MachineBasicBlock *MBB = Preds.front();
// FIXME: We are assuming at first that the basic blocks coming into this loop
// have only one successor each. This isn't the case in general because we
// haven't broken critical edges or added preheaders.
if (MBB->succ_size() != 1) return;
assert(*MBB->succ_begin() == CurLoop->getHeader() && assert(*MBB->succ_begin() == CurLoop->getHeader() &&
"The predecessor doesn't feed directly into the loop header!"); "The predecessor doesn't feed directly into the loop header!");
}
// Now move the instructions to the predecessors. // Now move the instructions to the predecessor.
for (std::vector<MachineBasicBlock*>::iterator MoveInstToEndOfBlock(MBB, MI.clone());
I = Preds.begin(), E = Preds.end(); I != E; ++I)
MoveInstToBlock(*I, MI.clone());
// Hoisting was successful! Remove bothersome instruction now.
MI.getParent()->remove(&MI);
Changed = true; Changed = true;
return true;
} }