/// \brief For Hexagon, if the loop label is to far from the /// loop instruction then we need to set the LC0 and SA0 registers /// explicitly instead of using LOOP(start,count). This function /// checks the distance, and generates register assignments if needed. /// /// This function makes two passes over the basic blocks. The first /// pass computes the offset of the basic block from the start. /// The second pass checks all the loop instructions. bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { // Offset of the current instruction from the start. unsigned InstOffset = 0; // Map for each basic block to it's first instruction. DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset; const HexagonInstrInfo *HII = static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); // First pass - compute the offset of each basic block. for (const MachineBasicBlock &MBB : MF) { if (MBB.getAlignment()) { // Although we don't know the exact layout of the final code, we need // to account for alignment padding somehow. This heuristic pads each // aligned basic block according to the alignment value. int ByteAlign = (1u << MBB.getAlignment()) - 1; InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign); } BlockToInstOffset[&MBB] = InstOffset; for (const MachineInstr &MI : MBB) InstOffset += HII->getSize(MI); } // Second pass - check each loop instruction to see if it needs to be // converted. bool Changed = false; for (MachineBasicBlock &MBB : MF) { InstOffset = BlockToInstOffset[&MBB]; // Loop over all the instructions. MachineBasicBlock::iterator MII = MBB.begin(); MachineBasicBlock::iterator MIE = MBB.end(); while (MII != MIE) { InstOffset += HII->getSize(*MII); if (MII->isMetaInstruction()) { ++MII; continue; } if (isHardwareLoop(*MII)) { assert(MII->getOperand(0).isMBB() && "Expect a basic block as loop operand"); int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; if ((unsigned)abs(diff) > MaxLoopRange) { useExtLoopInstr(MF, MII); MII = MBB.erase(MII); Changed = true; } else { ++MII; } } else { ++MII; } } } return Changed; }