mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	In particular, check if MachineBasicBlock::iterator is end() before using it to call getDebugLoc(); See also this thread on llvm-commits: http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20121112/155914.html git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@169634 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			655 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			655 lines
		
	
	
		
			23 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- HexagonHardwareLoops.cpp - Identify and generate hardware loops ---===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This pass identifies loops where we can generate the Hexagon hardware
 | 
						|
// loop instruction.  The hardware loop can perform loop branches with a
 | 
						|
// zero-cycle overhead.
 | 
						|
//
 | 
						|
// The pattern that defines the induction variable can changed depending on
 | 
						|
// prior optimizations.  For example, the IndVarSimplify phase run by 'opt'
 | 
						|
// normalizes induction variables, and the Loop Strength Reduction pass
 | 
						|
// run by 'llc' may also make changes to the induction variable.
 | 
						|
// The pattern detected by this phase is due to running Strength Reduction.
 | 
						|
//
 | 
						|
// Criteria for hardware loops:
 | 
						|
//  - Countable loops (w/ ind. var for a trip count)
 | 
						|
//  - Assumes loops are normalized by IndVarSimplify
 | 
						|
//  - Try inner-most loops first
 | 
						|
//  - No nested hardware loops.
 | 
						|
//  - No function calls in loops.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#define DEBUG_TYPE "hwloops"
 | 
						|
#include "Hexagon.h"
 | 
						|
#include "HexagonTargetMachine.h"
 | 
						|
#include "llvm/ADT/DenseMap.h"
 | 
						|
#include "llvm/ADT/Statistic.h"
 | 
						|
#include "llvm/CodeGen/MachineDominators.h"
 | 
						|
#include "llvm/CodeGen/MachineFunction.h"
 | 
						|
#include "llvm/CodeGen/MachineFunctionPass.h"
 | 
						|
#include "llvm/CodeGen/MachineInstrBuilder.h"
 | 
						|
#include "llvm/CodeGen/MachineLoopInfo.h"
 | 
						|
#include "llvm/CodeGen/MachineRegisterInfo.h"
 | 
						|
#include "llvm/CodeGen/Passes.h"
 | 
						|
#include "llvm/CodeGen/RegisterScavenging.h"
 | 
						|
#include "llvm/Constants.h"
 | 
						|
#include "llvm/PassSupport.h"
 | 
						|
#include "llvm/Support/Debug.h"
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
#include "llvm/Target/TargetInstrInfo.h"
 | 
						|
#include <algorithm>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
STATISTIC(NumHWLoops, "Number of loops converted to hardware loops");
 | 
						|
 | 
						|
namespace {
 | 
						|
  class CountValue;
 | 
						|
  struct HexagonHardwareLoops : public MachineFunctionPass {
 | 
						|
    MachineLoopInfo       *MLI;
 | 
						|
    MachineRegisterInfo   *MRI;
 | 
						|
    const TargetInstrInfo *TII;
 | 
						|
 | 
						|
  public:
 | 
						|
    static char ID;   // Pass identification, replacement for typeid
 | 
						|
 | 
						|
    HexagonHardwareLoops() : MachineFunctionPass(ID) {}
 | 
						|
 | 
						|
    virtual bool runOnMachineFunction(MachineFunction &MF);
 | 
						|
 | 
						|
    const char *getPassName() const { return "Hexagon Hardware Loops"; }
 | 
						|
 | 
						|
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
 | 
						|
      AU.setPreservesCFG();
 | 
						|
      AU.addRequired<MachineDominatorTree>();
 | 
						|
      AU.addPreserved<MachineDominatorTree>();
 | 
						|
      AU.addRequired<MachineLoopInfo>();
 | 
						|
      AU.addPreserved<MachineLoopInfo>();
 | 
						|
      MachineFunctionPass::getAnalysisUsage(AU);
 | 
						|
    }
 | 
						|
 | 
						|
  private:
 | 
						|
    /// getCanonicalInductionVariable - Check to see if the loop has a canonical
 | 
						|
    /// induction variable.
 | 
						|
    /// Should be defined in MachineLoop. Based upon version in class Loop.
 | 
						|
    const MachineInstr *getCanonicalInductionVariable(MachineLoop *L) const;
 | 
						|
 | 
						|
    /// getTripCount - Return a loop-invariant LLVM register indicating the
 | 
						|
    /// number of times the loop will be executed.  If the trip-count cannot
 | 
						|
    /// be determined, this return null.
 | 
						|
    CountValue *getTripCount(MachineLoop *L) const;
 | 
						|
 | 
						|
    /// isInductionOperation - Return true if the instruction matches the
 | 
						|
    /// pattern for an opertion that defines an induction variable.
 | 
						|
    bool isInductionOperation(const MachineInstr *MI, unsigned IVReg) const;
 | 
						|
 | 
						|
    /// isInvalidOperation - Return true if the instruction is not valid within
 | 
						|
    /// a hardware loop.
 | 
						|
    bool isInvalidLoopOperation(const MachineInstr *MI) const;
 | 
						|
 | 
						|
    /// containsInavlidInstruction - Return true if the loop contains an
 | 
						|
    /// instruction that inhibits using the hardware loop.
 | 
						|
    bool containsInvalidInstruction(MachineLoop *L) const;
 | 
						|
 | 
						|
    /// converToHardwareLoop - Given a loop, check if we can convert it to a
 | 
						|
    /// hardware loop.  If so, then perform the conversion and return true.
 | 
						|
    bool convertToHardwareLoop(MachineLoop *L);
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  char HexagonHardwareLoops::ID = 0;
 | 
						|
 | 
						|
 | 
						|
  // CountValue class - Abstraction for a trip count of a loop. A
 | 
						|
  // smaller vesrsion of the MachineOperand class without the concerns
 | 
						|
  // of changing the operand representation.
 | 
						|
  class CountValue {
 | 
						|
  public:
 | 
						|
    enum CountValueType {
 | 
						|
      CV_Register,
 | 
						|
      CV_Immediate
 | 
						|
    };
 | 
						|
  private:
 | 
						|
    CountValueType Kind;
 | 
						|
    union Values {
 | 
						|
      unsigned RegNum;
 | 
						|
      int64_t ImmVal;
 | 
						|
      Values(unsigned r) : RegNum(r) {}
 | 
						|
      Values(int64_t i) : ImmVal(i) {}
 | 
						|
    } Contents;
 | 
						|
    bool isNegative;
 | 
						|
 | 
						|
  public:
 | 
						|
    CountValue(unsigned r, bool neg) : Kind(CV_Register), Contents(r),
 | 
						|
                                       isNegative(neg) {}
 | 
						|
    explicit CountValue(int64_t i) : Kind(CV_Immediate), Contents(i),
 | 
						|
                                     isNegative(i < 0) {}
 | 
						|
    CountValueType getType() const { return Kind; }
 | 
						|
    bool isReg() const { return Kind == CV_Register; }
 | 
						|
    bool isImm() const { return Kind == CV_Immediate; }
 | 
						|
    bool isNeg() const { return isNegative; }
 | 
						|
 | 
						|
    unsigned getReg() const {
 | 
						|
      assert(isReg() && "Wrong CountValue accessor");
 | 
						|
      return Contents.RegNum;
 | 
						|
    }
 | 
						|
    void setReg(unsigned Val) {
 | 
						|
      Contents.RegNum = Val;
 | 
						|
    }
 | 
						|
    int64_t getImm() const {
 | 
						|
      assert(isImm() && "Wrong CountValue accessor");
 | 
						|
      if (isNegative) {
 | 
						|
        return -Contents.ImmVal;
 | 
						|
      }
 | 
						|
      return Contents.ImmVal;
 | 
						|
    }
 | 
						|
    void setImm(int64_t Val) {
 | 
						|
      Contents.ImmVal = Val;
 | 
						|
    }
 | 
						|
 | 
						|
    void print(raw_ostream &OS, const TargetMachine *TM = 0) const {
 | 
						|
      if (isReg()) { OS << PrintReg(getReg()); }
 | 
						|
      if (isImm()) { OS << getImm(); }
 | 
						|
    }
 | 
						|
  };
 | 
						|
 | 
						|
  struct HexagonFixupHwLoops : public MachineFunctionPass {
 | 
						|
  public:
 | 
						|
    static char ID;     // Pass identification, replacement for typeid.
 | 
						|
 | 
						|
    HexagonFixupHwLoops() : MachineFunctionPass(ID) {}
 | 
						|
 | 
						|
    virtual bool runOnMachineFunction(MachineFunction &MF);
 | 
						|
 | 
						|
    const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
 | 
						|
 | 
						|
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
 | 
						|
      AU.setPreservesCFG();
 | 
						|
      MachineFunctionPass::getAnalysisUsage(AU);
 | 
						|
    }
 | 
						|
 | 
						|
  private:
 | 
						|
    /// Maximum distance between the loop instr and the basic block.
 | 
						|
    /// Just an estimate.
 | 
						|
    static const unsigned MAX_LOOP_DISTANCE = 200;
 | 
						|
 | 
						|
    /// fixupLoopInstrs - Check the offset between each loop instruction and
 | 
						|
    /// the loop basic block to determine if we can use the LOOP instruction
 | 
						|
    /// or if we need to set the LC/SA registers explicitly.
 | 
						|
    bool fixupLoopInstrs(MachineFunction &MF);
 | 
						|
 | 
						|
    /// convertLoopInstr - Add the instruction to set the LC and SA registers
 | 
						|
    /// explicitly.
 | 
						|
    void convertLoopInstr(MachineFunction &MF,
 | 
						|
                          MachineBasicBlock::iterator &MII,
 | 
						|
                          RegScavenger &RS);
 | 
						|
 | 
						|
  };
 | 
						|
 | 
						|
  char HexagonFixupHwLoops::ID = 0;
 | 
						|
 | 
						|
} // end anonymous namespace
 | 
						|
 | 
						|
 | 
						|
/// isHardwareLoop - Returns true if the instruction is a hardware loop
 | 
						|
/// instruction.
 | 
						|
static bool isHardwareLoop(const MachineInstr *MI) {
 | 
						|
  return MI->getOpcode() == Hexagon::LOOP0_r ||
 | 
						|
    MI->getOpcode() == Hexagon::LOOP0_i;
 | 
						|
}
 | 
						|
 | 
						|
/// isCompareEquals - Returns true if the instruction is a compare equals
 | 
						|
/// instruction with an immediate operand.
 | 
						|
static bool isCompareEqualsImm(const MachineInstr *MI) {
 | 
						|
  return MI->getOpcode() == Hexagon::CMPEQri;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/// createHexagonHardwareLoops - Factory for creating
 | 
						|
/// the hardware loop phase.
 | 
						|
FunctionPass *llvm::createHexagonHardwareLoops() {
 | 
						|
  return new HexagonHardwareLoops();
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
 | 
						|
  DEBUG(dbgs() << "********* Hexagon Hardware Loops *********\n");
 | 
						|
 | 
						|
  bool Changed = false;
 | 
						|
 | 
						|
  // get the loop information
 | 
						|
  MLI = &getAnalysis<MachineLoopInfo>();
 | 
						|
  // get the register information
 | 
						|
  MRI = &MF.getRegInfo();
 | 
						|
  // the target specific instructio info.
 | 
						|
  TII = MF.getTarget().getInstrInfo();
 | 
						|
 | 
						|
  for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
 | 
						|
       I != E; ++I) {
 | 
						|
    MachineLoop *L = *I;
 | 
						|
    if (!L->getParentLoop()) {
 | 
						|
      Changed |= convertToHardwareLoop(L);
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Changed;
 | 
						|
}
 | 
						|
 | 
						|
/// getCanonicalInductionVariable - Check to see if the loop has a canonical
 | 
						|
/// induction variable. We check for a simple recurrence pattern - an
 | 
						|
/// integer recurrence that decrements by one each time through the loop and
 | 
						|
/// ends at zero.  If so, return the phi node that corresponds to it.
 | 
						|
///
 | 
						|
/// Based upon the similar code in LoopInfo except this code is specific to
 | 
						|
/// the machine.
 | 
						|
/// This method assumes that the IndVarSimplify pass has been run by 'opt'.
 | 
						|
///
 | 
						|
const MachineInstr
 | 
						|
*HexagonHardwareLoops::getCanonicalInductionVariable(MachineLoop *L) const {
 | 
						|
  MachineBasicBlock *TopMBB = L->getTopBlock();
 | 
						|
  MachineBasicBlock::pred_iterator PI = TopMBB->pred_begin();
 | 
						|
  assert(PI != TopMBB->pred_end() &&
 | 
						|
         "Loop must have more than one incoming edge!");
 | 
						|
  MachineBasicBlock *Backedge = *PI++;
 | 
						|
  if (PI == TopMBB->pred_end()) return 0;  // dead loop
 | 
						|
  MachineBasicBlock *Incoming = *PI++;
 | 
						|
  if (PI != TopMBB->pred_end()) return 0;  // multiple backedges?
 | 
						|
 | 
						|
  // make sure there is one incoming and one backedge and determine which
 | 
						|
  // is which.
 | 
						|
  if (L->contains(Incoming)) {
 | 
						|
    if (L->contains(Backedge))
 | 
						|
      return 0;
 | 
						|
    std::swap(Incoming, Backedge);
 | 
						|
  } else if (!L->contains(Backedge))
 | 
						|
    return 0;
 | 
						|
 | 
						|
  // Loop over all of the PHI nodes, looking for a canonical induction variable:
 | 
						|
  //   - The PHI node is "reg1 = PHI reg2, BB1, reg3, BB2".
 | 
						|
  //   - The recurrence comes from the backedge.
 | 
						|
  //   - the definition is an induction operatio.n
 | 
						|
  for (MachineBasicBlock::iterator I = TopMBB->begin(), E = TopMBB->end();
 | 
						|
       I != E && I->isPHI(); ++I) {
 | 
						|
    const MachineInstr *MPhi = &*I;
 | 
						|
    unsigned DefReg = MPhi->getOperand(0).getReg();
 | 
						|
    for (unsigned i = 1; i != MPhi->getNumOperands(); i += 2) {
 | 
						|
      // Check each operand for the value from the backedge.
 | 
						|
      MachineBasicBlock *MBB = MPhi->getOperand(i+1).getMBB();
 | 
						|
      if (L->contains(MBB)) { // operands comes from the backedge
 | 
						|
        // Check if the definition is an induction operation.
 | 
						|
        const MachineInstr *DI = MRI->getVRegDef(MPhi->getOperand(i).getReg());
 | 
						|
        if (isInductionOperation(DI, DefReg)) {
 | 
						|
          return MPhi;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/// getTripCount - Return a loop-invariant LLVM value indicating the
 | 
						|
/// number of times the loop will be executed.  The trip count can
 | 
						|
/// be either a register or a constant value.  If the trip-count
 | 
						|
/// cannot be determined, this returns null.
 | 
						|
///
 | 
						|
/// We find the trip count from the phi instruction that defines the
 | 
						|
/// induction variable.  We follow the links to the CMP instruction
 | 
						|
/// to get the trip count.
 | 
						|
///
 | 
						|
/// Based upon getTripCount in LoopInfo.
 | 
						|
///
 | 
						|
CountValue *HexagonHardwareLoops::getTripCount(MachineLoop *L) const {
 | 
						|
  // Check that the loop has a induction variable.
 | 
						|
  const MachineInstr *IV_Inst = getCanonicalInductionVariable(L);
 | 
						|
  if (IV_Inst == 0) return 0;
 | 
						|
 | 
						|
  // Canonical loops will end with a 'cmpeq_ri IV, Imm',
 | 
						|
  //  if Imm is 0, get the count from the PHI opnd
 | 
						|
  //  if Imm is -M, than M is the count
 | 
						|
  //  Otherwise, Imm is the count
 | 
						|
  const MachineOperand *IV_Opnd;
 | 
						|
  const MachineOperand *InitialValue;
 | 
						|
  if (!L->contains(IV_Inst->getOperand(2).getMBB())) {
 | 
						|
    InitialValue = &IV_Inst->getOperand(1);
 | 
						|
    IV_Opnd = &IV_Inst->getOperand(3);
 | 
						|
  } else {
 | 
						|
    InitialValue = &IV_Inst->getOperand(3);
 | 
						|
    IV_Opnd = &IV_Inst->getOperand(1);
 | 
						|
  }
 | 
						|
 | 
						|
  // Look for the cmp instruction to determine if we
 | 
						|
  // can get a useful trip count.  The trip count can
 | 
						|
  // be either a register or an immediate.  The location
 | 
						|
  // of the value depends upon the type (reg or imm).
 | 
						|
  for (MachineRegisterInfo::reg_iterator
 | 
						|
       RI = MRI->reg_begin(IV_Opnd->getReg()), RE = MRI->reg_end();
 | 
						|
       RI != RE; ++RI) {
 | 
						|
    IV_Opnd = &RI.getOperand();
 | 
						|
    const MachineInstr *MI = IV_Opnd->getParent();
 | 
						|
    if (L->contains(MI) && isCompareEqualsImm(MI)) {
 | 
						|
      const MachineOperand &MO = MI->getOperand(2);
 | 
						|
      assert(MO.isImm() && "IV Cmp Operand should be 0");
 | 
						|
      int64_t ImmVal = MO.getImm();
 | 
						|
 | 
						|
      const MachineInstr *IV_DefInstr = MRI->getVRegDef(IV_Opnd->getReg());
 | 
						|
      assert(L->contains(IV_DefInstr->getParent()) &&
 | 
						|
             "IV definition should occurs in loop");
 | 
						|
      int64_t iv_value = IV_DefInstr->getOperand(2).getImm();
 | 
						|
 | 
						|
      if (ImmVal == 0) {
 | 
						|
        // Make sure the induction variable changes by one on each iteration.
 | 
						|
        if (iv_value != 1 && iv_value != -1) {
 | 
						|
          return 0;
 | 
						|
        }
 | 
						|
        return new CountValue(InitialValue->getReg(), iv_value > 0);
 | 
						|
      } else {
 | 
						|
        assert(InitialValue->isReg() && "Expecting register for init value");
 | 
						|
        const MachineInstr *DefInstr = MRI->getVRegDef(InitialValue->getReg());
 | 
						|
        if (DefInstr && DefInstr->getOpcode() == Hexagon::TFRI) {
 | 
						|
          int64_t count = ImmVal - DefInstr->getOperand(1).getImm();
 | 
						|
          if ((count % iv_value) != 0) {
 | 
						|
            return 0;
 | 
						|
          }
 | 
						|
          return new CountValue(count/iv_value);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
/// isInductionOperation - return true if the operation is matches the
 | 
						|
/// pattern that defines an induction variable:
 | 
						|
///    add iv, c
 | 
						|
///
 | 
						|
bool
 | 
						|
HexagonHardwareLoops::isInductionOperation(const MachineInstr *MI,
 | 
						|
                                           unsigned IVReg) const {
 | 
						|
  return (MI->getOpcode() ==
 | 
						|
          Hexagon::ADD_ri && MI->getOperand(1).getReg() == IVReg);
 | 
						|
}
 | 
						|
 | 
						|
/// isInvalidOperation - Return true if the operation is invalid within
 | 
						|
/// hardware loop.
 | 
						|
bool
 | 
						|
HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI) const {
 | 
						|
 | 
						|
  // call is not allowed because the callee may use a hardware loop
 | 
						|
  if (MI->getDesc().isCall()) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  // do not allow nested hardware loops
 | 
						|
  if (isHardwareLoop(MI)) {
 | 
						|
    return true;
 | 
						|
  }
 | 
						|
  // check if the instruction defines a hardware loop register
 | 
						|
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
 | 
						|
    const MachineOperand &MO = MI->getOperand(i);
 | 
						|
    if (MO.isReg() && MO.isDef() &&
 | 
						|
        (MO.getReg() == Hexagon::LC0 || MO.getReg() == Hexagon::LC1 ||
 | 
						|
         MO.getReg() == Hexagon::SA0 || MO.getReg() == Hexagon::SA0)) {
 | 
						|
      return true;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// containsInvalidInstruction - Return true if the loop contains
 | 
						|
/// an instruction that inhibits the use of the hardware loop function.
 | 
						|
///
 | 
						|
bool HexagonHardwareLoops::containsInvalidInstruction(MachineLoop *L) const {
 | 
						|
  const std::vector<MachineBasicBlock*> Blocks = L->getBlocks();
 | 
						|
  for (unsigned i = 0, e = Blocks.size(); i != e; ++i) {
 | 
						|
    MachineBasicBlock *MBB = Blocks[i];
 | 
						|
    for (MachineBasicBlock::iterator
 | 
						|
           MII = MBB->begin(), E = MBB->end(); MII != E; ++MII) {
 | 
						|
      const MachineInstr *MI = &*MII;
 | 
						|
      if (isInvalidLoopOperation(MI)) {
 | 
						|
        return true;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
/// converToHardwareLoop - check if the loop is a candidate for
 | 
						|
/// converting to a hardware loop.  If so, then perform the
 | 
						|
/// transformation.
 | 
						|
///
 | 
						|
/// This function works on innermost loops first.  A loop can
 | 
						|
/// be converted if it is a counting loop; either a register
 | 
						|
/// value or an immediate.
 | 
						|
///
 | 
						|
/// The code makes several assumptions about the representation
 | 
						|
/// of the loop in llvm.
 | 
						|
bool HexagonHardwareLoops::convertToHardwareLoop(MachineLoop *L) {
 | 
						|
  bool Changed = false;
 | 
						|
  // Process nested loops first.
 | 
						|
  for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I) {
 | 
						|
    Changed |= convertToHardwareLoop(*I);
 | 
						|
  }
 | 
						|
  // If a nested loop has been converted, then we can't convert this loop.
 | 
						|
  if (Changed) {
 | 
						|
    return Changed;
 | 
						|
  }
 | 
						|
  // Are we able to determine the trip count for the loop?
 | 
						|
  CountValue *TripCount = getTripCount(L);
 | 
						|
  if (TripCount == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  // Does the loop contain any invalid instructions?
 | 
						|
  if (containsInvalidInstruction(L)) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  MachineBasicBlock *Preheader = L->getLoopPreheader();
 | 
						|
  // No preheader means there's not place for the loop instr.
 | 
						|
  if (Preheader == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  MachineBasicBlock::iterator InsertPos = Preheader->getFirstTerminator();
 | 
						|
 | 
						|
  MachineBasicBlock *LastMBB = L->getExitingBlock();
 | 
						|
  // Don't generate hw loop if the loop has more than one exit.
 | 
						|
  if (LastMBB == 0) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  MachineBasicBlock::iterator LastI = LastMBB->getFirstTerminator();
 | 
						|
  if (LastI == LastMBB->end()) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
 | 
						|
  // Determine the loop start.
 | 
						|
  MachineBasicBlock *LoopStart = L->getTopBlock();
 | 
						|
  if (L->getLoopLatch() != LastMBB) {
 | 
						|
    // When the exit and latch are not the same, use the latch block as the
 | 
						|
    // start.
 | 
						|
    // The loop start address is used only after the 1st iteration, and the loop
 | 
						|
    // latch may contains instrs. that need to be executed after the 1st iter.
 | 
						|
    LoopStart = L->getLoopLatch();
 | 
						|
    // Make sure the latch is a successor of the exit, otherwise it won't work.
 | 
						|
    if (!LastMBB->isSuccessor(LoopStart)) {
 | 
						|
      return false;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Convert the loop to a hardware loop
 | 
						|
  DEBUG(dbgs() << "Change to hardware loop at "; L->dump());
 | 
						|
  DebugLoc InsertPosDL;
 | 
						|
  if (InsertPos != Preheader->end())
 | 
						|
    InsertPosDL = InsertPos->getDebugLoc();
 | 
						|
 | 
						|
  if (TripCount->isReg()) {
 | 
						|
    // Create a copy of the loop count register.
 | 
						|
    MachineFunction *MF = LastMBB->getParent();
 | 
						|
    const TargetRegisterClass *RC =
 | 
						|
      MF->getRegInfo().getRegClass(TripCount->getReg());
 | 
						|
    unsigned CountReg = MF->getRegInfo().createVirtualRegister(RC);
 | 
						|
    BuildMI(*Preheader, InsertPos, InsertPosDL,
 | 
						|
            TII->get(TargetOpcode::COPY), CountReg).addReg(TripCount->getReg());
 | 
						|
    if (TripCount->isNeg()) {
 | 
						|
      unsigned CountReg1 = CountReg;
 | 
						|
      CountReg = MF->getRegInfo().createVirtualRegister(RC);
 | 
						|
      BuildMI(*Preheader, InsertPos, InsertPosDL,
 | 
						|
              TII->get(Hexagon::NEG), CountReg).addReg(CountReg1);
 | 
						|
    }
 | 
						|
 | 
						|
    // Add the Loop instruction to the beginning of the loop.
 | 
						|
    BuildMI(*Preheader, InsertPos, InsertPosDL,
 | 
						|
            TII->get(Hexagon::LOOP0_r)).addMBB(LoopStart).addReg(CountReg);
 | 
						|
  } else {
 | 
						|
    assert(TripCount->isImm() && "Expecting immedate vaule for trip count");
 | 
						|
    // Add the Loop immediate instruction to the beginning of the loop.
 | 
						|
    int64_t CountImm = TripCount->getImm();
 | 
						|
    BuildMI(*Preheader, InsertPos, InsertPosDL,
 | 
						|
            TII->get(Hexagon::LOOP0_i)).addMBB(LoopStart).addImm(CountImm);
 | 
						|
  }
 | 
						|
 | 
						|
  // Make sure the loop start always has a reference in the CFG.  We need to
 | 
						|
  // create a BlockAddress operand to get this mechanism to work both the
 | 
						|
  // MachineBasicBlock and BasicBlock objects need the flag set.
 | 
						|
  LoopStart->setHasAddressTaken();
 | 
						|
  // This line is needed to set the hasAddressTaken flag on the BasicBlock
 | 
						|
  // object
 | 
						|
  BlockAddress::get(const_cast<BasicBlock *>(LoopStart->getBasicBlock()));
 | 
						|
 | 
						|
  // Replace the loop branch with an endloop instruction.
 | 
						|
  DebugLoc LastIDL = LastI->getDebugLoc();
 | 
						|
  BuildMI(*LastMBB, LastI, LastIDL,
 | 
						|
          TII->get(Hexagon::ENDLOOP0)).addMBB(LoopStart);
 | 
						|
 | 
						|
  // The loop ends with either:
 | 
						|
  //  - a conditional branch followed by an unconditional branch, or
 | 
						|
  //  - a conditional branch to the loop start.
 | 
						|
  if (LastI->getOpcode() == Hexagon::JMP_c ||
 | 
						|
      LastI->getOpcode() == Hexagon::JMP_cNot) {
 | 
						|
    // delete one and change/add an uncond. branch to out of the loop
 | 
						|
    MachineBasicBlock *BranchTarget = LastI->getOperand(1).getMBB();
 | 
						|
    LastI = LastMBB->erase(LastI);
 | 
						|
    if (!L->contains(BranchTarget)) {
 | 
						|
      if (LastI != LastMBB->end()) {
 | 
						|
        TII->RemoveBranch(*LastMBB);
 | 
						|
      }
 | 
						|
      SmallVector<MachineOperand, 0> Cond;
 | 
						|
      TII->InsertBranch(*LastMBB, BranchTarget, 0, Cond, LastIDL);
 | 
						|
    }
 | 
						|
  } else {
 | 
						|
    // Conditional branch to loop start; just delete it.
 | 
						|
    LastMBB->erase(LastI);
 | 
						|
  }
 | 
						|
  delete TripCount;
 | 
						|
 | 
						|
  ++NumHWLoops;
 | 
						|
  return true;
 | 
						|
}
 | 
						|
 | 
						|
/// createHexagonFixupHwLoops - Factory for creating the hardware loop
 | 
						|
/// phase.
 | 
						|
FunctionPass *llvm::createHexagonFixupHwLoops() {
 | 
						|
  return new HexagonFixupHwLoops();
 | 
						|
}
 | 
						|
 | 
						|
bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
 | 
						|
  DEBUG(dbgs() << "****** Hexagon Hardware Loop Fixup ******\n");
 | 
						|
 | 
						|
  bool Changed = fixupLoopInstrs(MF);
 | 
						|
  return Changed;
 | 
						|
}
 | 
						|
 | 
						|
/// fixupLoopInsts - For Hexagon, if the loop label is to far from the
 | 
						|
/// loop instruction then we need to set the LC0 and SA0 registers
 | 
						|
/// explicitly instead of using LOOP(start,count).  This function
 | 
						|
/// checks the distance, and generates register assignments if needed.
 | 
						|
///
 | 
						|
/// This function makes two passes over the basic blocks.  The first
 | 
						|
/// pass computes the offset of the basic block from the start.
 | 
						|
/// The second pass checks all the loop instructions.
 | 
						|
bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
 | 
						|
 | 
						|
  // Offset of the current instruction from the start.
 | 
						|
  unsigned InstOffset = 0;
 | 
						|
  // Map for each basic block to it's first instruction.
 | 
						|
  DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
 | 
						|
 | 
						|
  // First pass - compute the offset of each basic block.
 | 
						|
  for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
 | 
						|
       MBB != MBBe; ++MBB) {
 | 
						|
    BlockToInstOffset[MBB] = InstOffset;
 | 
						|
    InstOffset += (MBB->size() * 4);
 | 
						|
  }
 | 
						|
 | 
						|
  // Second pass - check each loop instruction to see if it needs to
 | 
						|
  // be converted.
 | 
						|
  InstOffset = 0;
 | 
						|
  bool Changed = false;
 | 
						|
  RegScavenger RS;
 | 
						|
 | 
						|
  // Loop over all the basic blocks.
 | 
						|
  for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
 | 
						|
       MBB != MBBe; ++MBB) {
 | 
						|
    InstOffset = BlockToInstOffset[MBB];
 | 
						|
    RS.enterBasicBlock(MBB);
 | 
						|
 | 
						|
    // Loop over all the instructions.
 | 
						|
    MachineBasicBlock::iterator MIE = MBB->end();
 | 
						|
    MachineBasicBlock::iterator MII = MBB->begin();
 | 
						|
    while (MII != MIE) {
 | 
						|
      if (isHardwareLoop(MII)) {
 | 
						|
        RS.forward(MII);
 | 
						|
        assert(MII->getOperand(0).isMBB() &&
 | 
						|
               "Expect a basic block as loop operand");
 | 
						|
        int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
 | 
						|
        diff = (diff > 0 ? diff : -diff);
 | 
						|
        if ((unsigned)diff > MAX_LOOP_DISTANCE) {
 | 
						|
          // Convert to explicity setting LC0 and SA0.
 | 
						|
          convertLoopInstr(MF, MII, RS);
 | 
						|
          MII = MBB->erase(MII);
 | 
						|
          Changed = true;
 | 
						|
        } else {
 | 
						|
          ++MII;
 | 
						|
        }
 | 
						|
      } else {
 | 
						|
        ++MII;
 | 
						|
      }
 | 
						|
      InstOffset += 4;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Changed;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/// convertLoopInstr - convert a loop instruction to a sequence of instructions
 | 
						|
/// that set the lc and sa register explicitly.
 | 
						|
void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
 | 
						|
                                           MachineBasicBlock::iterator &MII,
 | 
						|
                                           RegScavenger &RS) {
 | 
						|
  const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
 | 
						|
  MachineBasicBlock *MBB = MII->getParent();
 | 
						|
  DebugLoc DL = MII->getDebugLoc();
 | 
						|
  unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
 | 
						|
 | 
						|
  // First, set the LC0 with the trip count.
 | 
						|
  if (MII->getOperand(1).isReg()) {
 | 
						|
    // Trip count is a register
 | 
						|
    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
 | 
						|
      .addReg(MII->getOperand(1).getReg());
 | 
						|
  } else {
 | 
						|
    // Trip count is an immediate.
 | 
						|
    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
 | 
						|
      .addImm(MII->getOperand(1).getImm());
 | 
						|
    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
 | 
						|
      .addReg(Scratch);
 | 
						|
  }
 | 
						|
  // Then, set the SA0 with the loop start address.
 | 
						|
  BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
 | 
						|
    .addMBB(MII->getOperand(0).getMBB());
 | 
						|
  BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0).addReg(Scratch);
 | 
						|
}
 |