Skip to content
TwoAddressInstructionPass.cpp 57.3 KiB
Newer Older
//===-- TwoAddressInstructionPass.cpp - Two-Address instruction pass ------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
Alkis Evlogimenos's avatar
Alkis Evlogimenos committed
// This file implements the TwoAddress instruction pass which is used
// by most register allocators. Two-Address instructions are rewritten
// from:
//
//     A = B op C
//
// to:
//
//     A = B
// Note that if a register allocator chooses to use this pass, that it
// has to be capable of handling the non-SSA nature of these rewritten
// virtual registers.
//
// It is also worth noting that the duplicate operand of the two
// address instruction is removed.
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "twoaddrinstr"
Chris Lattner's avatar
Chris Lattner committed
#include "llvm/CodeGen/Passes.h"
Chris Lattner's avatar
Chris Lattner committed
#include "llvm/Function.h"
#include "llvm/CodeGen/LiveVariables.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallSet.h"
Reid Spencer's avatar
Reid Spencer committed
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/STLExtras.h"
STATISTIC(NumTwoAddressInstrs, "Number of two-address instructions");
STATISTIC(NumCommuted        , "Number of instructions commuted to coalesce");
STATISTIC(NumAggrCommuted    , "Number of instructions aggressively commuted");
STATISTIC(NumConvertedTo3Addr, "Number of instructions promoted to 3-address");
STATISTIC(Num3AddrSunk,        "Number of 3-address instructions sunk");
STATISTIC(NumReMats,           "Number of instructions re-materialized");
STATISTIC(NumDeletes,          "Number of dead instructions deleted");
namespace {
  class TwoAddressInstructionPass : public MachineFunctionPass {
    const TargetInstrInfo *TII;
    const TargetRegisterInfo *TRI;
    MachineRegisterInfo *MRI;
    LiveVariables *LV;
Evan Cheng's avatar
Evan Cheng committed
    // DistanceMap - Keep track the distance of a MI from the start of the
    // current basic block.
    DenseMap<MachineInstr*, unsigned> DistanceMap;

    // SrcRegMap - A map from virtual registers to physical registers which
    // are likely targets to be coalesced to due to copies from physical
    // registers to virtual registers. e.g. v1024 = move r0.
    DenseMap<unsigned, unsigned> SrcRegMap;

    // DstRegMap - A map from virtual registers to physical registers which
    // are likely targets to be coalesced to due to copies to physical
    // registers from virtual registers. e.g. r1 = move v1024.
    DenseMap<unsigned, unsigned> DstRegMap;

    /// RegSequences - Keep track the list of REG_SEQUENCE instructions seen
    /// during the initial walk of the machine function.
    SmallVector<MachineInstr*, 16> RegSequences;

Bill Wendling's avatar
Bill Wendling committed
    bool Sink3AddrInstruction(MachineBasicBlock *MBB, MachineInstr *MI,
                              unsigned Reg,
                              MachineBasicBlock::iterator OldPos);

    bool isProfitableToReMat(unsigned Reg, const TargetRegisterClass *RC,
                             MachineInstr *MI, MachineInstr *DefMI,
Evan Cheng's avatar
Evan Cheng committed
                             MachineBasicBlock *MBB, unsigned Loc);
    bool NoUseAfterLastDef(unsigned Reg, MachineBasicBlock *MBB, unsigned Dist,
                           unsigned &LastDef);

    MachineInstr *FindLastUseInMBB(unsigned Reg, MachineBasicBlock *MBB,
                                   unsigned Dist);

    bool isProfitableToCommute(unsigned regB, unsigned regC,
                               MachineInstr *MI, MachineBasicBlock *MBB,
Evan Cheng's avatar
Evan Cheng committed
                               unsigned Dist);
    bool CommuteInstruction(MachineBasicBlock::iterator &mi,
                            MachineFunction::iterator &mbbi,
Evan Cheng's avatar
Evan Cheng committed
                            unsigned RegB, unsigned RegC, unsigned Dist);

    bool isProfitableToConv3Addr(unsigned RegA, unsigned RegB);

    bool ConvertInstTo3Addr(MachineBasicBlock::iterator &mi,
                            MachineBasicBlock::iterator &nmi,
                            MachineFunction::iterator &mbbi,
                            unsigned RegA, unsigned RegB, unsigned Dist);
    typedef std::pair<std::pair<unsigned, bool>, MachineInstr*> NewKill;
    bool canUpdateDeletedKills(SmallVector<unsigned, 4> &Kills,
                               SmallVector<NewKill, 4> &NewKills,
                               MachineBasicBlock *MBB, unsigned Dist);
    bool DeleteUnusedInstr(MachineBasicBlock::iterator &mi,
                           MachineBasicBlock::iterator &nmi,
Jakob Stoklund Olesen's avatar
Jakob Stoklund Olesen committed
                           MachineFunction::iterator &mbbi, unsigned Dist);
    bool TryInstructionTransform(MachineBasicBlock::iterator &mi,
                                 MachineBasicBlock::iterator &nmi,
                                 MachineFunction::iterator &mbbi,
                                 unsigned SrcIdx, unsigned DstIdx,
                                 unsigned Dist,
                                 SmallPtrSet<MachineInstr*, 8> &Processed);

    void ScanUses(unsigned DstReg, MachineBasicBlock *MBB,
                  SmallPtrSet<MachineInstr*, 8> &Processed);
Evan Cheng's avatar
Evan Cheng committed
    void ProcessCopy(MachineInstr *MI, MachineBasicBlock *MBB,
                     SmallPtrSet<MachineInstr*, 8> &Processed);
Evan Cheng's avatar
Evan Cheng committed

    void CoalesceExtSubRegs(SmallVector<unsigned,4> &Srcs, unsigned DstReg);

    /// EliminateRegSequences - Eliminate REG_SEQUENCE instructions as part
    /// of the de-ssa process. This replaces sources of REG_SEQUENCE as
    /// sub-register references of the register defined by REG_SEQUENCE.
    bool EliminateRegSequences();
Nick Lewycky's avatar
Nick Lewycky committed
    static char ID; // Pass identification, replacement for typeid
    TwoAddressInstructionPass() : MachineFunctionPass(ID) {
      initializeTwoAddressInstructionPassPass(*PassRegistry::getPassRegistry());
    }
Bill Wendling's avatar
Bill Wendling committed
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
Bill Wendling's avatar
Bill Wendling committed
      AU.addPreserved<LiveVariables>();
      AU.addPreservedID(MachineLoopInfoID);
      AU.addPreservedID(MachineDominatorsID);
Bill Wendling's avatar
Bill Wendling committed
      MachineFunctionPass::getAnalysisUsage(AU);
    }
Bill Wendling's avatar
Bill Wendling committed
    /// runOnMachineFunction - Pass entry point.
    bool runOnMachineFunction(MachineFunction&);
  };
char TwoAddressInstructionPass::ID = 0;
INITIALIZE_PASS_BEGIN(TwoAddressInstructionPass, "twoaddressinstruction",
                "Two-Address instruction pass", false, false)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_PASS_END(TwoAddressInstructionPass, "twoaddressinstruction",
                "Two-Address instruction pass", false, false)
char &llvm::TwoAddressInstructionPassID = TwoAddressInstructionPass::ID;
/// Sink3AddrInstruction - A two-address instruction has been converted to a
/// three-address instruction to avoid clobbering a register. Try to sink it
Bill Wendling's avatar
Bill Wendling committed
/// past the instruction that would kill the above mentioned register to reduce
/// register pressure.
bool TwoAddressInstructionPass::Sink3AddrInstruction(MachineBasicBlock *MBB,
                                           MachineInstr *MI, unsigned SavedReg,
                                           MachineBasicBlock::iterator OldPos) {
  // Check if it's safe to move this instruction.
  bool SeenStore = true; // Be conservative.
  if (!MI->isSafeToMove(TII, AA, SeenStore))
    return false;

  unsigned DefReg = 0;
  SmallSet<unsigned, 4> UseRegs;
Bill Wendling's avatar
Bill Wendling committed

  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
      continue;
    unsigned MOReg = MO.getReg();
    if (!MOReg)
      continue;
    if (MO.isUse() && MOReg != SavedReg)
      UseRegs.insert(MO.getReg());
    if (!MO.isDef())
      continue;
    if (MO.isImplicit())
      // Don't try to move it if it implicitly defines a register.
Loading
Loading full blame...