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 instruction needs to use a constant extender.
     11 // This pass will identify and convert such LOOPn instructions to a proper
     12 // form.
     13 //===----------------------------------------------------------------------===//
     14 
     15 
     16 #include "llvm/ADT/DenseMap.h"
     17 #include "Hexagon.h"
     18 #include "HexagonTargetMachine.h"
     19 #include "llvm/CodeGen/MachineFunction.h"
     20 #include "llvm/CodeGen/MachineFunctionPass.h"
     21 #include "llvm/CodeGen/MachineInstrBuilder.h"
     22 #include "llvm/CodeGen/Passes.h"
     23 #include "llvm/PassSupport.h"
     24 #include "llvm/Target/TargetInstrInfo.h"
     25 
     26 using namespace llvm;
     27 
     28 static cl::opt<unsigned> MaxLoopRange(
     29     "hexagon-loop-range", cl::Hidden, cl::init(200),
     30     cl::desc("Restrict range of loopN instructions (testing only)"));
     31 
     32 namespace llvm {
     33   FunctionPass *createHexagonFixupHwLoops();
     34   void initializeHexagonFixupHwLoopsPass(PassRegistry&);
     35 }
     36 
     37 namespace {
     38   struct HexagonFixupHwLoops : public MachineFunctionPass {
     39   public:
     40     static char ID;
     41 
     42     HexagonFixupHwLoops() : MachineFunctionPass(ID) {
     43       initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
     44     }
     45 
     46     bool runOnMachineFunction(MachineFunction &MF) override;
     47 
     48     MachineFunctionProperties getRequiredProperties() const override {
     49       return MachineFunctionProperties().set(
     50           MachineFunctionProperties::Property::AllVRegsAllocated);
     51     }
     52 
     53     const char *getPassName() const override {
     54       return "Hexagon Hardware Loop Fixup";
     55     }
     56 
     57     void getAnalysisUsage(AnalysisUsage &AU) const override {
     58       AU.setPreservesCFG();
     59       MachineFunctionPass::getAnalysisUsage(AU);
     60     }
     61 
     62   private:
     63     /// \brief Check the offset between each loop instruction and
     64     /// the loop basic block to determine if we can use the LOOP instruction
     65     /// or if we need to set the LC/SA registers explicitly.
     66     bool fixupLoopInstrs(MachineFunction &MF);
     67 
     68     /// \brief Replace loop instruction with the constant extended
     69     /// version if the loop label is too far from the loop instruction.
     70     void useExtLoopInstr(MachineFunction &MF,
     71                          MachineBasicBlock::iterator &MII);
     72   };
     73 
     74   char HexagonFixupHwLoops::ID = 0;
     75 }
     76 
     77 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
     78                 "Hexagon Hardware Loops Fixup", false, false)
     79 
     80 FunctionPass *llvm::createHexagonFixupHwLoops() {
     81   return new HexagonFixupHwLoops();
     82 }
     83 
     84 /// \brief Returns true if the instruction is a hardware loop instruction.
     85 static bool isHardwareLoop(const MachineInstr &MI) {
     86   return MI.getOpcode() == Hexagon::J2_loop0r ||
     87          MI.getOpcode() == Hexagon::J2_loop0i ||
     88          MI.getOpcode() == Hexagon::J2_loop1r ||
     89          MI.getOpcode() == Hexagon::J2_loop1i;
     90 }
     91 
     92 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
     93   if (skipFunction(*MF.getFunction()))
     94     return false;
     95   return fixupLoopInstrs(MF);
     96 }
     97 
     98 /// \brief For Hexagon, if the loop label is to far from the
     99 /// loop instruction then we need to set the LC0 and SA0 registers
    100 /// explicitly instead of using LOOP(start,count).  This function
    101 /// checks the distance, and generates register assignments if needed.
    102 ///
    103 /// This function makes two passes over the basic blocks.  The first
    104 /// pass computes the offset of the basic block from the start.
    105 /// The second pass checks all the loop instructions.
    106 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
    107 
    108   // Offset of the current instruction from the start.
    109   unsigned InstOffset = 0;
    110   // Map for each basic block to it's first instruction.
    111   DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset;
    112 
    113   const HexagonInstrInfo *HII =
    114       static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo());
    115 
    116   // First pass - compute the offset of each basic block.
    117   for (const MachineBasicBlock &MBB : MF) {
    118     if (MBB.getAlignment()) {
    119       // Although we don't know the exact layout of the final code, we need
    120       // to account for alignment padding somehow. This heuristic pads each
    121       // aligned basic block according to the alignment value.
    122       int ByteAlign = (1u << MBB.getAlignment()) - 1;
    123       InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign);
    124     }
    125 
    126     BlockToInstOffset[&MBB] = InstOffset;
    127     for (const MachineInstr &MI : MBB)
    128       InstOffset += HII->getSize(&MI);
    129   }
    130 
    131   // Second pass - check each loop instruction to see if it needs to be
    132   // converted.
    133   bool Changed = false;
    134   for (MachineBasicBlock &MBB : MF) {
    135     InstOffset = BlockToInstOffset[&MBB];
    136 
    137     // Loop over all the instructions.
    138     MachineBasicBlock::iterator MII = MBB.begin();
    139     MachineBasicBlock::iterator MIE = MBB.end();
    140     while (MII != MIE) {
    141       InstOffset += HII->getSize(&*MII);
    142       if (MII->isDebugValue()) {
    143         ++MII;
    144         continue;
    145       }
    146       if (isHardwareLoop(*MII)) {
    147         assert(MII->getOperand(0).isMBB() &&
    148                "Expect a basic block as loop operand");
    149         int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
    150         if ((unsigned)abs(diff) > MaxLoopRange) {
    151           useExtLoopInstr(MF, MII);
    152           MII = MBB.erase(MII);
    153           Changed = true;
    154         } else {
    155           ++MII;
    156         }
    157       } else {
    158         ++MII;
    159       }
    160     }
    161   }
    162 
    163   return Changed;
    164 }
    165 
    166 /// \brief Replace loop instructions with the constant extended version.
    167 void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF,
    168                                           MachineBasicBlock::iterator &MII) {
    169   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
    170   MachineBasicBlock *MBB = MII->getParent();
    171   DebugLoc DL = MII->getDebugLoc();
    172   MachineInstrBuilder MIB;
    173   unsigned newOp;
    174   switch (MII->getOpcode()) {
    175   case Hexagon::J2_loop0r:
    176     newOp = Hexagon::J2_loop0rext;
    177     break;
    178   case Hexagon::J2_loop0i:
    179     newOp = Hexagon::J2_loop0iext;
    180     break;
    181   case Hexagon::J2_loop1r:
    182     newOp = Hexagon::J2_loop1rext;
    183     break;
    184   case Hexagon::J2_loop1i:
    185     newOp = Hexagon::J2_loop1iext;
    186     break;
    187   default:
    188     llvm_unreachable("Invalid Hardware Loop Instruction.");
    189   }
    190   MIB = BuildMI(*MBB, MII, DL, TII->get(newOp));
    191 
    192   for (unsigned i = 0; i < MII->getNumOperands(); ++i)
    193     MIB.addOperand(MII->getOperand(i));
    194 }
    195