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