Home | History | Annotate | Download | only in Hexagon
      1 //===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 // The loop start address in the LOOPn instruction is encoded as a distance
      9 // from the LOOPn instruction itself.  If the start address is too far from
     10 // the LOOPn instruction, the loop needs to be set up manually, i.e. via
     11 // direct transfers to SAn and LCn.
     12 // This pass will identify and convert such LOOPn instructions to a proper
     13 // form.
     14 //===----------------------------------------------------------------------===//
     15 
     16 
     17 #include "llvm/ADT/DenseMap.h"
     18 #include "llvm/CodeGen/MachineFunction.h"
     19 #include "llvm/CodeGen/MachineFunctionPass.h"
     20 #include "llvm/CodeGen/MachineInstrBuilder.h"
     21 #include "llvm/CodeGen/Passes.h"
     22 #include "llvm/CodeGen/RegisterScavenging.h"
     23 #include "llvm/PassSupport.h"
     24 #include "llvm/Target/TargetInstrInfo.h"
     25 #include "Hexagon.h"
     26 #include "HexagonTargetMachine.h"
     27 
     28 using namespace llvm;
     29 
     30 namespace llvm {
     31   void initializeHexagonFixupHwLoopsPass(PassRegistry&);
     32 }
     33 
     34 namespace {
     35   struct HexagonFixupHwLoops : public MachineFunctionPass {
     36   public:
     37     static char ID;
     38 
     39     HexagonFixupHwLoops() : MachineFunctionPass(ID) {
     40       initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
     41     }
     42 
     43     virtual bool runOnMachineFunction(MachineFunction &MF);
     44 
     45     const char *getPassName() const { return "Hexagon Hardware Loop Fixup"; }
     46 
     47     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
     48       AU.setPreservesCFG();
     49       MachineFunctionPass::getAnalysisUsage(AU);
     50     }
     51 
     52   private:
     53     /// \brief Maximum distance between the loop instr and the basic block.
     54     /// Just an estimate.
     55     static const unsigned MAX_LOOP_DISTANCE = 200;
     56 
     57     /// \brief Check the offset between each loop instruction and
     58     /// the loop basic block to determine if we can use the LOOP instruction
     59     /// or if we need to set the LC/SA registers explicitly.
     60     bool fixupLoopInstrs(MachineFunction &MF);
     61 
     62     /// \brief Add the instruction to set the LC and SA registers explicitly.
     63     void convertLoopInstr(MachineFunction &MF,
     64                           MachineBasicBlock::iterator &MII,
     65                           RegScavenger &RS);
     66 
     67   };
     68 
     69   char HexagonFixupHwLoops::ID = 0;
     70 }
     71 
     72 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
     73                 "Hexagon Hardware Loops Fixup", false, false)
     74 
     75 FunctionPass *llvm::createHexagonFixupHwLoops() {
     76   return new HexagonFixupHwLoops();
     77 }
     78 
     79 
     80 /// \brief Returns true if the instruction is a hardware loop instruction.
     81 static bool isHardwareLoop(const MachineInstr *MI) {
     82   return MI->getOpcode() == Hexagon::LOOP0_r ||
     83          MI->getOpcode() == Hexagon::LOOP0_i;
     84 }
     85 
     86 
     87 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
     88   bool Changed = fixupLoopInstrs(MF);
     89   return Changed;
     90 }
     91 
     92 
     93 /// \brief For Hexagon, if the loop label is to far from the
     94 /// loop instruction then we need to set the LC0 and SA0 registers
     95 /// explicitly instead of using LOOP(start,count).  This function
     96 /// checks the distance, and generates register assignments if needed.
     97 ///
     98 /// This function makes two passes over the basic blocks.  The first
     99 /// pass computes the offset of the basic block from the start.
    100 /// The second pass checks all the loop instructions.
    101 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
    102 
    103   // Offset of the current instruction from the start.
    104   unsigned InstOffset = 0;
    105   // Map for each basic block to it's first instruction.
    106   DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
    107 
    108   // First pass - compute the offset of each basic block.
    109   for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
    110        MBB != MBBe; ++MBB) {
    111     BlockToInstOffset[MBB] = InstOffset;
    112     InstOffset += (MBB->size() * 4);
    113   }
    114 
    115   // Second pass - check each loop instruction to see if it needs to
    116   // be converted.
    117   InstOffset = 0;
    118   bool Changed = false;
    119   RegScavenger RS;
    120 
    121   // Loop over all the basic blocks.
    122   for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
    123        MBB != MBBe; ++MBB) {
    124     InstOffset = BlockToInstOffset[MBB];
    125     RS.enterBasicBlock(MBB);
    126 
    127     // Loop over all the instructions.
    128     MachineBasicBlock::iterator MIE = MBB->end();
    129     MachineBasicBlock::iterator MII = MBB->begin();
    130     while (MII != MIE) {
    131       if (isHardwareLoop(MII)) {
    132         RS.forward(MII);
    133         assert(MII->getOperand(0).isMBB() &&
    134                "Expect a basic block as loop operand");
    135         int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
    136         unsigned Dist = Sub > 0 ? Sub : -Sub;
    137         if (Dist > MAX_LOOP_DISTANCE) {
    138           // Convert to explicity setting LC0 and SA0.
    139           convertLoopInstr(MF, MII, RS);
    140           MII = MBB->erase(MII);
    141           Changed = true;
    142         } else {
    143           ++MII;
    144         }
    145       } else {
    146         ++MII;
    147       }
    148       InstOffset += 4;
    149     }
    150   }
    151 
    152   return Changed;
    153 }
    154 
    155 
    156 /// \brief convert a loop instruction to a sequence of instructions that
    157 /// set the LC0 and SA0 register explicitly.
    158 void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
    159                                            MachineBasicBlock::iterator &MII,
    160                                            RegScavenger &RS) {
    161   const TargetInstrInfo *TII = MF.getTarget().getInstrInfo();
    162   MachineBasicBlock *MBB = MII->getParent();
    163   DebugLoc DL = MII->getDebugLoc();
    164   unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
    165 
    166   // First, set the LC0 with the trip count.
    167   if (MII->getOperand(1).isReg()) {
    168     // Trip count is a register
    169     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
    170       .addReg(MII->getOperand(1).getReg());
    171   } else {
    172     // Trip count is an immediate.
    173     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
    174       .addImm(MII->getOperand(1).getImm());
    175     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
    176       .addReg(Scratch);
    177   }
    178   // Then, set the SA0 with the loop start address.
    179   BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
    180     .addMBB(MII->getOperand(0).getMBB());
    181   BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0)
    182     .addReg(Scratch);
    183 }
    184