Skip to content
MachineLICM.cpp 51.3 KiB
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"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#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/SmallSet.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
static cl::opt<bool>
AvoidSpeculation("avoid-speculation",
                 cl::desc("MachineLICM should avoid speculation"),
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");
  class MachineLICM : public MachineFunctionPass {
    bool PreRegAlloc;

    const TargetInstrInfo *TII;
    const MachineFrameInfo *MFI;
    MachineRegisterInfo *MRI;
    const InstrItineraryData *InstrItins;
    AliasAnalysis        *AA;      // Alias analysis info.
    MachineLoopInfo      *MLI;     // Current MachineLoopInfo
    MachineDominatorTree *DT;      // Machine dominator tree for the cur loop

    // State that is updated as we process loops
    bool         Changed;          // True if a loop is changed.
    bool         FirstInLoop;      // True if it's the first LICM in the loop.
    MachineLoop *CurLoop;          // The current loop we are working on.
    MachineBasicBlock *CurPreheader; // The preheader for CurLoop.
    BitVector AllocatableSet;

    // Track 'estimated' register pressure.
    SmallVector<unsigned, 8> RegPressure;

    // Register pressure "limit" per register class. If the pressure
    // is higher than the limit, then it's considered high.
    // Register pressure on path leading from loop preheader to current BB.
    SmallVector<SmallVector<unsigned, 8>, 16> BackTrace;

Dale Johannesen's avatar
Dale Johannesen committed
    // 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
    MachineLICM() :
      MachineFunctionPass(ID), PreRegAlloc(true) {
        initializeMachineLICMPass(*PassRegistry::getPassRegistry());
      }

    explicit MachineLICM(bool PreRA) :
      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() {
      for (DenseMap<unsigned,std::vector<const MachineInstr*> >::iterator
             CI = CSEMap.begin(), CE = CSEMap.end(); CI != CE; ++CI)
        CI->second.clear();
    /// CandidateInfo - Keep track of information about hoisting candidates.
    struct CandidateInfo {
      MachineInstr *MI;
      unsigned      Def;
      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.

    /// 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);
    /// 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.
    /// 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);
    /// 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;
    /// CanCauseHighRegPressure - Visit BBs from header to current BB,
Loading
Loading full blame...