forked from OSchip/llvm-project
Incorporated comments from Evan and Chris:
http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20071203/056043.html http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20071203/056048.html llvm-svn: 44696
This commit is contained in:
parent
086b2c4537
commit
4375173ba0
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue