HexagonFixupHwLoops.cpp revision 249259
1139799Simp//===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
211394Sswallace//
311397Sswallace//                     The LLVM Compiler Infrastructure
411394Sswallace//
511394Sswallace// This file is distributed under the University of Illinois Open Source
611394Sswallace// License. See LICENSE.TXT for details.
711394Sswallace//
811394Sswallace// The loop start address in the LOOPn instruction is encoded as a distance
911394Sswallace// from the LOOPn instruction itself.  If the start address is too far from
1011394Sswallace// the LOOPn instruction, the loop needs to be set up manually, i.e. via
1111394Sswallace// direct transfers to SAn and LCn.
1211394Sswallace// This pass will identify and convert such LOOPn instructions to a proper
1311394Sswallace// form.
1411394Sswallace//===----------------------------------------------------------------------===//
1511394Sswallace
1611394Sswallace
1711394Sswallace#include "llvm/ADT/DenseMap.h"
1811394Sswallace#include "llvm/CodeGen/MachineFunction.h"
1911394Sswallace#include "llvm/CodeGen/MachineFunctionPass.h"
2011394Sswallace#include "llvm/CodeGen/MachineInstrBuilder.h"
2111394Sswallace#include "llvm/CodeGen/Passes.h"
2211394Sswallace#include "llvm/CodeGen/RegisterScavenging.h"
2311394Sswallace#include "llvm/PassSupport.h"
2411394Sswallace#include "llvm/Target/TargetInstrInfo.h"
2511394Sswallace#include "Hexagon.h"
2611394Sswallace#include "HexagonTargetMachine.h"
2711394Sswallace
2811394Sswallaceusing namespace llvm;
29115684Sobrien
30115684Sobriennamespace llvm {
31115684Sobrien  void initializeHexagonFixupHwLoopsPass(PassRegistry&);
3211394Sswallace}
3311394Sswallace
3411394Sswallacenamespace {
3511394Sswallace  struct HexagonFixupHwLoops : public MachineFunctionPass {
3611394Sswallace  public:
3711394Sswallace    static char ID;
3891388Srobert
3911394Sswallace    HexagonFixupHwLoops() : MachineFunctionPass(ID) {
4011394Sswallace      initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
4111394Sswallace    }
4211397Sswallace
4311397Sswallace    virtual bool runOnMachineFunction(MachineFunction &MF);
4411394Sswallace
4511397Sswallace    const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
4611397Sswallace
4711397Sswallace    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
4811397Sswallace      AU.setPreservesCFG();
4911397Sswallace      MachineFunctionPass::getAnalysisUsage(AU);
5011397Sswallace    }
5111394Sswallace
5254655Seivind  private:
5392761Salfred    /// \brief Maximum distance between the loop instr and the basic block.
5492761Salfred    /// Just an estimate.
5511394Sswallace    static const unsigned MAX_LOOP_DISTANCE = 200;
5611394Sswallace
5711394Sswallace    /// \brief Check the offset between each loop instruction and
5811397Sswallace    /// the loop basic block to determine if we can use the LOOP instruction
5911394Sswallace    /// or if we need to set the LC/SA registers explicitly.
6011394Sswallace    bool fixupLoopInstrs(MachineFunction &MF);
6111394Sswallace
6211397Sswallace    /// \brief Add the instruction to set the LC and SA registers explicitly.
6311397Sswallace    void convertLoopInstr(MachineFunction &MF,
6411394Sswallace                          MachineBasicBlock::iterator &MII,
6511397Sswallace                          RegScavenger &RS);
6611397Sswallace
6711397Sswallace  };
6811394Sswallace
6911397Sswallace  char HexagonFixupHwLoops::ID = 0;
7011397Sswallace}
7111397Sswallace
7211397SswallaceINITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
7311394Sswallace                "Hexagon Hardware Loops Fixup", false, false)
7411394Sswallace
7511394SswallaceFunctionPass *llvm::createHexagonFixupHwLoops() {
7611394Sswallace  return new HexagonFixupHwLoops();
7711394Sswallace}
7811394Sswallace
7911394Sswallace
8011394Sswallace/// \brief Returns true if the instruction is a hardware loop instruction.
8111394Sswallacestatic bool isHardwareLoop(const MachineInstr *MI) {
8211394Sswallace  return MI->getOpcode() == Hexagon::LOOP0_r ||
8311394Sswallace         MI->getOpcode() == Hexagon::LOOP0_i;
8411394Sswallace}
8511394Sswallace
86118754Snectar
87118754Snectarbool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
88118754Snectar  bool Changed = fixupLoopInstrs(MF);
89118754Snectar  return Changed;
9011394Sswallace}
9111394Sswallace
9211394Sswallace
9311394Sswallace/// \brief For Hexagon, if the loop label is to far from the
9411394Sswallace/// loop instruction then we need to set the LC0 and SA0 registers
9511394Sswallace/// explicitly instead of using LOOP(start,count).  This function
9611394Sswallace/// checks the distance, and generates register assignments if needed.
9711394Sswallace///
9811394Sswallace/// This function makes two passes over the basic blocks.  The first
9911394Sswallace/// pass computes the offset of the basic block from the start.
10011394Sswallace/// The second pass checks all the loop instructions.
10111394Sswallacebool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
10211394Sswallace
10311394Sswallace  // Offset of the current instruction from the start.
10483366Sjulian  unsigned InstOffset = 0;
10583366Sjulian  // Map for each basic block to it's first instruction.
10611394Sswallace  DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
10711394Sswallace
10811394Sswallace  // First pass - compute the offset of each basic block.
10911394Sswallace  for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
11011394Sswallace       MBB != MBBe; ++MBB) {
11111394Sswallace    BlockToInstOffset[MBB] = InstOffset;
11211394Sswallace    InstOffset += (MBB->size() * 4);
11311394Sswallace  }
114107849Salfred
115107849Salfred  // Second pass - check each loop instruction to see if it needs to
11643314Sdillon  // be converted.
11711394Sswallace  InstOffset = 0;
11854655Seivind  bool Changed = false;
11911394Sswallace  RegScavenger RS;
12011394Sswallace
12111394Sswallace  // Loop over all the basic blocks.
12283366Sjulian  for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
12311394Sswallace       MBB != MBBe; ++MBB) {
12411394Sswallace    InstOffset = BlockToInstOffset[MBB];
125107849Salfred    RS.enterBasicBlock(MBB);
12611394Sswallace
12711394Sswallace    // Loop over all the instructions.
12811394Sswallace    MachineBasicBlock::iterator MIE = MBB->end();
12983366Sjulian    MachineBasicBlock::iterator MII = MBB->begin();
13083366Sjulian    while (MII != MIE) {
13111394Sswallace      if (isHardwareLoop(MII)) {
13211394Sswallace        RS.forward(MII);
13311394Sswallace        assert(MII->getOperand(0).isMBB() &&
13411394Sswallace               "Expect a basic block as loop operand");
13511394Sswallace        int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
13611394Sswallace        unsigned Dist = Sub > 0 ? Sub : -Sub;
13711394Sswallace        if (Dist > MAX_LOOP_DISTANCE) {
138107849Salfred          // Convert to explicity setting LC0 and SA0.
13911394Sswallace          convertLoopInstr(MF, MII, RS);
140116678Sphk          MII = MBB->erase(MII);
14111394Sswallace          Changed = true;
14289306Salfred        } else {
14389306Salfred          ++MII;
14489306Salfred        }
14511394Sswallace      } else {
14611394Sswallace        ++MII;
147107849Salfred      }
14811394Sswallace      InstOffset += 4;
14911394Sswallace    }
15011394Sswallace  }
15183366Sjulian
15283366Sjulian  return Changed;
15311394Sswallace}
15411394Sswallace
15511397Sswallace
15611394Sswallace/// \brief convert a loop instruction to a sequence of instructions that
15711397Sswallace/// set the LC0 and SA0 register explicitly.
15811394Sswallacevoid HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
15911394Sswallace                                           MachineBasicBlock::iterator &MII,
16011394Sswallace                                           RegScavenger &RS) {
161107849Salfred  const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
162107849Salfred  MachineBasicBlock *MBB = MII->getParent();
163107849Salfred  DebugLoc DL = MII->getDebugLoc();
16411397Sswallace  unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
16583366Sjulian
16611394Sswallace  // First, set the LC0 with the trip count.
16711397Sswallace  if (MII->getOperand(1).isReg()) {
168107849Salfred    // Trip count is a register
16911394Sswallace    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
17011394Sswallace      .addReg(MII->getOperand(1).getReg());
171107849Salfred  } else {
17211394Sswallace    // Trip count is an immediate.
17311394Sswallace    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
17411394Sswallace      .addImm(MII->getOperand(1).getImm());
17511394Sswallace    BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
17683366Sjulian      .addReg(Scratch);
17783366Sjulian  }
17811394Sswallace  // Then, set the SA0 with the loop start address.
17911394Sswallace  BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
18011397Sswallace    .addMBB(MII->getOperand(0).getMBB());
18111394Sswallace  BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0)
18211397Sswallace    .addReg(Scratch);
18311394Sswallace}
18411394Sswallace