#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineBlockFrequencyInfo.h"
#include "llvm/CodeGen/MachineDominators.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineLoopInfo.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TargetLowering.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/CodeGen/TargetSchedule.h"
#include "llvm/CodeGen/TargetSubtargetInfo.h"
#include "llvm/IR/DebugLoc.h"
#include "llvm/InitializePasses.h"
#include "llvm/MC/MCInstrDesc.h"
#include "llvm/MC/MCRegister.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/Pass.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cassert>
#include <limits>
#include <vector>
usingnamespacellvm;
#define DEBUG_TYPE …
static cl::opt<bool>
AvoidSpeculation("avoid-speculation",
cl::desc("MachineLICM should avoid speculation"),
cl::init(true), cl::Hidden);
static cl::opt<bool>
HoistCheapInsts("hoist-cheap-insts",
cl::desc("MachineLICM should hoist even cheap instructions"),
cl::init(false), cl::Hidden);
static cl::opt<bool>
HoistConstStores("hoist-const-stores",
cl::desc("Hoist invariant stores"),
cl::init(true), cl::Hidden);
static cl::opt<bool> HoistConstLoads("hoist-const-loads",
cl::desc("Hoist invariant loads"),
cl::init(true), cl::Hidden);
static cl::opt<unsigned>
BlockFrequencyRatioThreshold("block-freq-ratio-threshold",
cl::desc("Do not hoist instructions if target"
"block is N times hotter than the source."),
cl::init(100), cl::Hidden);
enum class UseBFI { … };
static cl::opt<UseBFI>
DisableHoistingToHotterBlocks("disable-hoisting-to-hotter-blocks",
cl::desc("Disable hoisting instructions to"
" hotter blocks"),
cl::init(UseBFI::PGO), cl::Hidden,
cl::values(clEnumValN(UseBFI::None, "none",
"disable the feature"),
clEnumValN(UseBFI::PGO, "pgo",
"enable the feature when using profile data"),
clEnumValN(UseBFI::All, "all",
"enable the feature with/wo profile data")));
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");
STATISTIC(NumStoreConst,
"Number of stores of const phys reg hoisted out of loops");
STATISTIC(NumNotHoistedDueToHotness,
"Number of instructions not hoisted due to block frequency");
namespace {
enum HoistResult { … };
class MachineLICMBase : public MachineFunctionPass { … };
class MachineLICM : public MachineLICMBase { … };
class EarlyMachineLICM : public MachineLICMBase { … };
}
char MachineLICM::ID;
char EarlyMachineLICM::ID;
char &llvm::MachineLICMID = …;
char &llvm::EarlyMachineLICMID = …;
INITIALIZE_PASS_BEGIN(MachineLICM, DEBUG_TYPE,
"Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(MachineLICM, DEBUG_TYPE,
"Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_BEGIN(EarlyMachineLICM, "early-machinelicm",
"Early Machine Loop Invariant Code Motion", false, false)
INITIALIZE_PASS_DEPENDENCY(MachineLoopInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineBlockFrequencyInfoWrapperPass)
INITIALIZE_PASS_DEPENDENCY(MachineDominatorTreeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass)
INITIALIZE_PASS_END(EarlyMachineLICM, "early-machinelicm",
"Early Machine Loop Invariant Code Motion", false, false)
bool MachineLICMBase::runOnMachineFunction(MachineFunction &MF) { … }
static bool InstructionStoresToFI(const MachineInstr *MI, int FI) { … }
static void applyBitsNotInRegMaskToRegUnitsMask(const TargetRegisterInfo &TRI,
BitVector &RUs,
const uint32_t *Mask) { … }
void MachineLICMBase::ProcessMI(MachineInstr *MI, BitVector &RUDefs,
BitVector &RUClobbers,
SmallDenseSet<int> &StoredFIs,
SmallVectorImpl<CandidateInfo> &Candidates,
MachineLoop *CurLoop) { … }
void MachineLICMBase::HoistRegionPostRA(MachineLoop *CurLoop,
MachineBasicBlock *CurPreheader) { … }
void MachineLICMBase::AddToLiveIns(MCRegister Reg, MachineLoop *CurLoop) { … }
void MachineLICMBase::HoistPostRA(MachineInstr *MI, unsigned Def,
MachineLoop *CurLoop,
MachineBasicBlock *CurPreheader) { … }
bool MachineLICMBase::IsGuaranteedToExecute(MachineBasicBlock *BB,
MachineLoop *CurLoop) { … }
bool MachineLICMBase::isTriviallyReMaterializable(
const MachineInstr &MI) const { … }
void MachineLICMBase::EnterScope(MachineBasicBlock *MBB) { … }
void MachineLICMBase::ExitScope(MachineBasicBlock *MBB) { … }
void MachineLICMBase::ExitScopeIfDone(MachineDomTreeNode *Node,
DenseMap<MachineDomTreeNode*, unsigned> &OpenChildren,
const DenseMap<MachineDomTreeNode*, MachineDomTreeNode*> &ParentMap) { … }
void MachineLICMBase::HoistOutOfLoop(MachineDomTreeNode *HeaderN,
MachineLoop *CurLoop,
MachineBasicBlock *CurPreheader) { … }
static bool isOperandKill(const MachineOperand &MO, MachineRegisterInfo *MRI) { … }
void MachineLICMBase::InitRegPressure(MachineBasicBlock *BB) { … }
void MachineLICMBase::UpdateRegPressure(const MachineInstr *MI,
bool ConsiderUnseenAsDef) { … }
DenseMap<unsigned, int>
MachineLICMBase::calcRegisterCost(const MachineInstr *MI, bool ConsiderSeen,
bool ConsiderUnseenAsDef) { … }
static bool mayLoadFromGOTOrConstantPool(MachineInstr &MI) { … }
static bool isInvariantStore(const MachineInstr &MI,
const TargetRegisterInfo *TRI,
const MachineRegisterInfo *MRI) { … }
static bool isCopyFeedingInvariantStore(const MachineInstr &MI,
const MachineRegisterInfo *MRI,
const TargetRegisterInfo *TRI) { … }
bool MachineLICMBase::IsLICMCandidate(MachineInstr &I, MachineLoop *CurLoop) { … }
bool MachineLICMBase::IsLoopInvariantInst(MachineInstr &I,
MachineLoop *CurLoop) { … }
bool MachineLICMBase::HasLoopPHIUse(const MachineInstr *MI,
MachineLoop *CurLoop) { … }
bool MachineLICMBase::HasHighOperandLatency(MachineInstr &MI, unsigned DefIdx,
Register Reg,
MachineLoop *CurLoop) const { … }
bool MachineLICMBase::IsCheapInstruction(MachineInstr &MI) const { … }
bool
MachineLICMBase::CanCauseHighRegPressure(const DenseMap<unsigned, int>& Cost,
bool CheapInstr) { … }
void MachineLICMBase::UpdateBackTraceRegPressure(const MachineInstr *MI) { … }
bool MachineLICMBase::IsProfitableToHoist(MachineInstr &MI,
MachineLoop *CurLoop) { … }
MachineInstr *MachineLICMBase::ExtractHoistableLoad(MachineInstr *MI,
MachineLoop *CurLoop) { … }
void MachineLICMBase::InitCSEMap(MachineBasicBlock *BB) { … }
void MachineLICMBase::InitializeLoadsHoistableLoops() { … }
MachineInstr *
MachineLICMBase::LookForDuplicate(const MachineInstr *MI,
std::vector<MachineInstr *> &PrevMIs) { … }
bool MachineLICMBase::EliminateCSE(
MachineInstr *MI,
DenseMap<unsigned, std::vector<MachineInstr *>>::iterator &CI) { … }
bool MachineLICMBase::MayCSE(MachineInstr *MI) { … }
unsigned MachineLICMBase::Hoist(MachineInstr *MI, MachineBasicBlock *Preheader,
MachineLoop *CurLoop) { … }
MachineBasicBlock *
MachineLICMBase::getCurPreheader(MachineLoop *CurLoop,
MachineBasicBlock *CurPreheader) { … }
bool MachineLICMBase::isTgtHotterThanSrc(MachineBasicBlock *SrcBlock,
MachineBasicBlock *TgtBlock) { … }