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