LLVM API Documentation

HexagonFixupHwLoops.cpp
Go to the documentation of this file.
00001 //===---- HexagonFixupHwLoops.cpp - Fixup HW loops too far from LOOPn. ----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 // The loop start address in the LOOPn instruction is encoded as a distance
00009 // from the LOOPn instruction itself.  If the start address is too far from
00010 // the LOOPn instruction, the loop needs to be set up manually, i.e. via
00011 // direct transfers to SAn and LCn.
00012 // This pass will identify and convert such LOOPn instructions to a proper
00013 // form.
00014 //===----------------------------------------------------------------------===//
00015 
00016 
00017 #include "llvm/ADT/DenseMap.h"
00018 #include "Hexagon.h"
00019 #include "HexagonTargetMachine.h"
00020 #include "llvm/CodeGen/MachineFunction.h"
00021 #include "llvm/CodeGen/MachineFunctionPass.h"
00022 #include "llvm/CodeGen/MachineInstrBuilder.h"
00023 #include "llvm/CodeGen/Passes.h"
00024 #include "llvm/CodeGen/RegisterScavenging.h"
00025 #include "llvm/PassSupport.h"
00026 #include "llvm/Target/TargetInstrInfo.h"
00027 
00028 using namespace llvm;
00029 
00030 namespace llvm {
00031   void initializeHexagonFixupHwLoopsPass(PassRegistry&);
00032 }
00033 
00034 namespace {
00035   struct HexagonFixupHwLoops : public MachineFunctionPass {
00036   public:
00037     static char ID;
00038 
00039     HexagonFixupHwLoops() : MachineFunctionPass(ID) {
00040       initializeHexagonFixupHwLoopsPass(*PassRegistry::getPassRegistry());
00041     }
00042 
00043     bool runOnMachineFunction(MachineFunction &MF) override;
00044 
00045     const char *getPassName() const override {
00046       return "Hexagon Hardware Loop Fixup";
00047     }
00048 
00049     void getAnalysisUsage(AnalysisUsage &AU) const override {
00050       AU.setPreservesCFG();
00051       MachineFunctionPass::getAnalysisUsage(AU);
00052     }
00053 
00054   private:
00055     /// \brief Maximum distance between the loop instr and the basic block.
00056     /// Just an estimate.
00057     static const unsigned MAX_LOOP_DISTANCE = 200;
00058 
00059     /// \brief Check the offset between each loop instruction and
00060     /// the loop basic block to determine if we can use the LOOP instruction
00061     /// or if we need to set the LC/SA registers explicitly.
00062     bool fixupLoopInstrs(MachineFunction &MF);
00063 
00064     /// \brief Add the instruction to set the LC and SA registers explicitly.
00065     void convertLoopInstr(MachineFunction &MF,
00066                           MachineBasicBlock::iterator &MII,
00067                           RegScavenger &RS);
00068 
00069   };
00070 
00071   char HexagonFixupHwLoops::ID = 0;
00072 }
00073 
00074 INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup",
00075                 "Hexagon Hardware Loops Fixup", false, false)
00076 
00077 FunctionPass *llvm::createHexagonFixupHwLoops() {
00078   return new HexagonFixupHwLoops();
00079 }
00080 
00081 
00082 /// \brief Returns true if the instruction is a hardware loop instruction.
00083 static bool isHardwareLoop(const MachineInstr *MI) {
00084   return MI->getOpcode() == Hexagon::LOOP0_r ||
00085          MI->getOpcode() == Hexagon::LOOP0_i;
00086 }
00087 
00088 
00089 bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) {
00090   bool Changed = fixupLoopInstrs(MF);
00091   return Changed;
00092 }
00093 
00094 
00095 /// \brief For Hexagon, if the loop label is to far from the
00096 /// loop instruction then we need to set the LC0 and SA0 registers
00097 /// explicitly instead of using LOOP(start,count).  This function
00098 /// checks the distance, and generates register assignments if needed.
00099 ///
00100 /// This function makes two passes over the basic blocks.  The first
00101 /// pass computes the offset of the basic block from the start.
00102 /// The second pass checks all the loop instructions.
00103 bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) {
00104 
00105   // Offset of the current instruction from the start.
00106   unsigned InstOffset = 0;
00107   // Map for each basic block to it's first instruction.
00108   DenseMap<MachineBasicBlock*, unsigned> BlockToInstOffset;
00109 
00110   // First pass - compute the offset of each basic block.
00111   for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
00112        MBB != MBBe; ++MBB) {
00113     BlockToInstOffset[MBB] = InstOffset;
00114     InstOffset += (MBB->size() * 4);
00115   }
00116 
00117   // Second pass - check each loop instruction to see if it needs to
00118   // be converted.
00119   InstOffset = 0;
00120   bool Changed = false;
00121   RegScavenger RS;
00122 
00123   // Loop over all the basic blocks.
00124   for (MachineFunction::iterator MBB = MF.begin(), MBBe = MF.end();
00125        MBB != MBBe; ++MBB) {
00126     InstOffset = BlockToInstOffset[MBB];
00127     RS.enterBasicBlock(MBB);
00128 
00129     // Loop over all the instructions.
00130     MachineBasicBlock::iterator MIE = MBB->end();
00131     MachineBasicBlock::iterator MII = MBB->begin();
00132     while (MII != MIE) {
00133       if (isHardwareLoop(MII)) {
00134         RS.forward(MII);
00135         assert(MII->getOperand(0).isMBB() &&
00136                "Expect a basic block as loop operand");
00137         int Sub = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()];
00138         unsigned Dist = Sub > 0 ? Sub : -Sub;
00139         if (Dist > MAX_LOOP_DISTANCE) {
00140           // Convert to explicity setting LC0 and SA0.
00141           convertLoopInstr(MF, MII, RS);
00142           MII = MBB->erase(MII);
00143           Changed = true;
00144         } else {
00145           ++MII;
00146         }
00147       } else {
00148         ++MII;
00149       }
00150       InstOffset += 4;
00151     }
00152   }
00153 
00154   return Changed;
00155 }
00156 
00157 
00158 /// \brief convert a loop instruction to a sequence of instructions that
00159 /// set the LC0 and SA0 register explicitly.
00160 void HexagonFixupHwLoops::convertLoopInstr(MachineFunction &MF,
00161                                            MachineBasicBlock::iterator &MII,
00162                                            RegScavenger &RS) {
00163   const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo();
00164   MachineBasicBlock *MBB = MII->getParent();
00165   DebugLoc DL = MII->getDebugLoc();
00166   unsigned Scratch = RS.scavengeRegister(&Hexagon::IntRegsRegClass, MII, 0);
00167 
00168   // First, set the LC0 with the trip count.
00169   if (MII->getOperand(1).isReg()) {
00170     // Trip count is a register
00171     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
00172       .addReg(MII->getOperand(1).getReg());
00173   } else {
00174     // Trip count is an immediate.
00175     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFRI), Scratch)
00176       .addImm(MII->getOperand(1).getImm());
00177     BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::LC0)
00178       .addReg(Scratch);
00179   }
00180   // Then, set the SA0 with the loop start address.
00181   BuildMI(*MBB, MII, DL, TII->get(Hexagon::CONST32_Label), Scratch)
00182     .addMBB(MII->getOperand(0).getMBB());
00183   BuildMI(*MBB, MII, DL, TII->get(Hexagon::TFCR), Hexagon::SA0)
00184     .addReg(Scratch);
00185 }