"llvm/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "7530049b16c0fc6ef8b715d380e8fe5b570601f8"
Newer
Older
//===-- MachineLICM.cpp - Machine Loop Invariant Code Motion Pass ---------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This pass performs loop invariant code motion on machine instructions. We
// attempt to remove as much code from the body of a loop as possible.
//
// This pass does not attempt to throttle itself to limit register pressure.
// The register allocation phases are expected to perform rematerialization
// to recover when register pressure is high.
//
// This pass is not intended to be a replacement or a complete alternative
// for the LLVM-IR-level LICM pass. It is only designed to hoist simple
// constructs that are not exposed before lowering and instruction selection.
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "machine-licm"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
Bill Wendling
committed
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
Evan Cheng
committed
#include "llvm/MC/MCInstrItineraries.h"
Evan Cheng
committed
#include "llvm/Target/TargetLowering.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"
Evan Cheng
committed
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
Daniel Dunbar
committed
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
Evan Cheng
committed
static cl::opt<bool>
AvoidSpeculation("avoid-speculation",
cl::desc("MachineLICM should avoid speculation"),
cl::init(true), cl::Hidden);
Evan Cheng
committed
STATISTIC(NumHoisted,
"Number of machine instructions hoisted out of loops");
STATISTIC(NumLowRP,
"Number of instructions hoisted in low reg pressure situation");
STATISTIC(NumHighLatency,
"Number of high latency instructions hoisted");
STATISTIC(NumCSEed,
"Number of hoisted machine instructions CSEed");
STATISTIC(NumPostRAHoisted,
"Number of machine instructions hoisted out of loops post regalloc");
namespace {
Nick Lewycky
committed
class MachineLICM : public MachineFunctionPass {
Bill Wendling
committed
const TargetMachine *TM;
const TargetInstrInfo *TII;
Evan Cheng
committed
const TargetLowering *TLI;
const TargetRegisterInfo *TRI;
Evan Cheng
committed
MachineRegisterInfo *MRI;
const InstrItineraryData *InstrItins;
// Various analyses that we use...
AliasAnalysis *AA; // Alias analysis info.
MachineLoopInfo *MLI; // Current MachineLoopInfo
Bill Wendling
committed
MachineDominatorTree *DT; // Machine dominator tree for the cur loop
// State that is updated as we process loops
Bill Wendling
committed
bool Changed; // True if a loop is changed.
Evan Cheng
committed
bool FirstInLoop; // True if it's the first LICM in the loop.
Bill Wendling
committed
MachineLoop *CurLoop; // The current loop we are working on.
MachineBasicBlock *CurPreheader; // The preheader for CurLoop.
Evan Cheng
committed
// Track 'estimated' register pressure.
SmallSet<unsigned, 32> RegSeen;
Evan Cheng
committed
SmallVector<unsigned, 8> RegPressure;
// Register pressure "limit" per register class. If the pressure
// is higher than the limit, then it's considered high.
Evan Cheng
committed
SmallVector<unsigned, 8> RegLimit;
// Register pressure on path leading from loop preheader to current BB.
SmallVector<SmallVector<unsigned, 8>, 16> BackTrace;
// For each opcode, keep a list of potential CSE instructions.
DenseMap<unsigned, std::vector<const MachineInstr*> > CSEMap;
enum {
SpeculateFalse = 0,
SpeculateTrue = 1,
SpeculateUnknown = 2
};
// If a MBB does not dominate loop exiting blocks then it may not safe
// to hoist loads from this block.
// Tri-state: 0 - false, 1 - true, 2 - unknown
unsigned SpeculationState;
public:
static char ID; // Pass identification, replacement for typeid
Owen Anderson
committed
MachineFunctionPass(ID), PreRegAlloc(true) {
initializeMachineLICMPass(*PassRegistry::getPassRegistry());
}
explicit MachineLICM(bool PreRA) :
Owen Anderson
committed
MachineFunctionPass(ID), PreRegAlloc(PreRA) {
initializeMachineLICMPass(*PassRegistry::getPassRegistry());
}
virtual bool runOnMachineFunction(MachineFunction &MF);
const char *getPassName() const { return "Machine Instruction LICM"; }
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<MachineLoopInfo>();
AU.addRequired<MachineDominatorTree>();
AU.addRequired<AliasAnalysis>();
AU.addPreserved<MachineLoopInfo>();
AU.addPreserved<MachineDominatorTree>();
MachineFunctionPass::getAnalysisUsage(AU);
}
virtual void releaseMemory() {
RegSeen.clear();
Evan Cheng
committed
RegPressure.clear();
RegLimit.clear();
BackTrace.clear();
for (DenseMap<unsigned,std::vector<const MachineInstr*> >::iterator
CI = CSEMap.begin(), CE = CSEMap.end(); CI != CE; ++CI)
CI->second.clear();
private:
/// CandidateInfo - Keep track of information about hoisting candidates.
struct CandidateInfo {
MachineInstr *MI;
unsigned Def;
Evan Cheng
committed
int FI;
CandidateInfo(MachineInstr *mi, unsigned def, int fi)
: MI(mi), Def(def), FI(fi) {}
};
/// HoistRegionPostRA - Walk the specified region of the CFG and hoist loop
/// invariants out to the preheader.
void HoistRegionPostRA();
/// HoistPostRA - 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 HoistPostRA(MachineInstr *MI, unsigned Def);
/// ProcessMI - Examine the instruction for potentai LICM candidate. Also
/// gather register def and frame object update information.
void ProcessMI(MachineInstr *MI, unsigned *PhysRegDefs,
SmallSet<int, 32> &StoredFIs,
SmallVector<CandidateInfo, 32> &Candidates);
/// AddToLiveIns - Add register 'Reg' to the livein sets of BBs in the
/// current loop.
void AddToLiveIns(unsigned Reg);
Evan Cheng
committed
/// IsLICMCandidate - Returns true if the instruction may be a suitable
/// candidate for LICM. e.g. If the instruction is a call, then it's
/// obviously not safe to hoist it.
Evan Cheng
committed
bool IsLICMCandidate(MachineInstr &I);
/// 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.
///
bool IsLoopInvariantInst(MachineInstr &I);
Evan Cheng
committed
/// HasAnyPHIUse - Return true if the specified register is used by any
/// phi node.
bool HasAnyPHIUse(unsigned Reg) const;
/// HasHighOperandLatency - Compute operand latency between a def of 'Reg'
/// and an use in the current loop, return true if the target considered
/// it 'high'.
bool HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx,
unsigned Reg) const;
bool IsCheapInstruction(MachineInstr &MI) const;
Evan Cheng
committed
/// CanCauseHighRegPressure - Visit BBs from header to current BB,
Loading
Loading full blame...