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