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 26using namespace llvm; 27 28static cl::opt<unsigned> MaxLoopRange( 29 "hexagon-loop-range", cl::Hidden, cl::init(200), 30 cl::desc("Restrict range of loopN instructions (testing only)")); 31 32namespace llvm { 33 FunctionPass *createHexagonFixupHwLoops(); 34 void initializeHexagonFixupHwLoopsPass(PassRegistry&); 35} 36 37namespace { 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 const char *getPassName() const override { 49 return "Hexagon Hardware Loop Fixup"; 50 } 51 52 void getAnalysisUsage(AnalysisUsage &AU) const override { 53 AU.setPreservesCFG(); 54 MachineFunctionPass::getAnalysisUsage(AU); 55 } 56 57 private: 58 /// \brief Check the offset between each loop instruction and 59 /// the loop basic block to determine if we can use the LOOP instruction 60 /// or if we need to set the LC/SA registers explicitly. 61 bool fixupLoopInstrs(MachineFunction &MF); 62 63 /// \brief Replace loop instruction with the constant extended 64 /// version if the loop label is too far from the loop instruction. 65 void useExtLoopInstr(MachineFunction &MF, 66 MachineBasicBlock::iterator &MII); 67 }; 68 69 char HexagonFixupHwLoops::ID = 0; 70} 71 72INITIALIZE_PASS(HexagonFixupHwLoops, "hwloopsfixup", 73 "Hexagon Hardware Loops Fixup", false, false) 74 75FunctionPass *llvm::createHexagonFixupHwLoops() { 76 return new HexagonFixupHwLoops(); 77} 78 79/// \brief Returns true if the instruction is a hardware loop instruction. 80static bool isHardwareLoop(const MachineInstr *MI) { 81 return MI->getOpcode() == Hexagon::J2_loop0r || 82 MI->getOpcode() == Hexagon::J2_loop0i || 83 MI->getOpcode() == Hexagon::J2_loop1r || 84 MI->getOpcode() == Hexagon::J2_loop1i; 85} 86 87bool HexagonFixupHwLoops::runOnMachineFunction(MachineFunction &MF) { 88 return fixupLoopInstrs(MF); 89} 90 91/// \brief For Hexagon, if the loop label is to far from the 92/// loop instruction then we need to set the LC0 and SA0 registers 93/// explicitly instead of using LOOP(start,count). This function 94/// checks the distance, and generates register assignments if needed. 95/// 96/// This function makes two passes over the basic blocks. The first 97/// pass computes the offset of the basic block from the start. 98/// The second pass checks all the loop instructions. 99bool HexagonFixupHwLoops::fixupLoopInstrs(MachineFunction &MF) { 100 101 // Offset of the current instruction from the start. 102 unsigned InstOffset = 0; 103 // Map for each basic block to it's first instruction. 104 DenseMap<const MachineBasicBlock *, unsigned> BlockToInstOffset; 105 106 const HexagonInstrInfo *HII = 107 static_cast<const HexagonInstrInfo *>(MF.getSubtarget().getInstrInfo()); 108 109 // First pass - compute the offset of each basic block. 110 for (const MachineBasicBlock &MBB : MF) { 111 if (MBB.getAlignment()) { 112 // Although we don't know the exact layout of the final code, we need 113 // to account for alignment padding somehow. This heuristic pads each 114 // aligned basic block according to the alignment value. 115 int ByteAlign = (1u << MBB.getAlignment()) - 1; 116 InstOffset = (InstOffset + ByteAlign) & ~(ByteAlign); 117 } 118 119 BlockToInstOffset[&MBB] = InstOffset; 120 for (const MachineInstr &MI : MBB) 121 InstOffset += HII->getSize(&MI); 122 } 123 124 // Second pass - check each loop instruction to see if it needs to be 125 // converted. 126 InstOffset = 0; 127 bool Changed = false; 128 for (MachineBasicBlock &MBB : MF) { 129 InstOffset = BlockToInstOffset[&MBB]; 130 131 // Loop over all the instructions. 132 MachineBasicBlock::iterator MII = MBB.begin(); 133 MachineBasicBlock::iterator MIE = MBB.end(); 134 while (MII != MIE) { 135 InstOffset += HII->getSize(&*MII); 136 if (MII->isDebugValue()) { 137 ++MII; 138 continue; 139 } 140 if (isHardwareLoop(MII)) { 141 assert(MII->getOperand(0).isMBB() && 142 "Expect a basic block as loop operand"); 143 int diff = InstOffset - BlockToInstOffset[MII->getOperand(0).getMBB()]; 144 if ((unsigned)abs(diff) > MaxLoopRange) { 145 useExtLoopInstr(MF, MII); 146 MII = MBB.erase(MII); 147 Changed = true; 148 } else { 149 ++MII; 150 } 151 } else { 152 ++MII; 153 } 154 } 155 } 156 157 return Changed; 158} 159 160/// \brief Replace loop instructions with the constant extended version. 161void HexagonFixupHwLoops::useExtLoopInstr(MachineFunction &MF, 162 MachineBasicBlock::iterator &MII) { 163 const TargetInstrInfo *TII = MF.getSubtarget().getInstrInfo(); 164 MachineBasicBlock *MBB = MII->getParent(); 165 DebugLoc DL = MII->getDebugLoc(); 166 MachineInstrBuilder MIB; 167 unsigned newOp; 168 switch (MII->getOpcode()) { 169 case Hexagon::J2_loop0r: 170 newOp = Hexagon::J2_loop0rext; 171 break; 172 case Hexagon::J2_loop0i: 173 newOp = Hexagon::J2_loop0iext; 174 break; 175 case Hexagon::J2_loop1r: 176 newOp = Hexagon::J2_loop1rext; 177 break; 178 case Hexagon::J2_loop1i: 179 newOp = Hexagon::J2_loop1iext; 180 break; 181 default: 182 llvm_unreachable("Invalid Hardware Loop Instruction."); 183 } 184 MIB = BuildMI(*MBB, MII, DL, TII->get(newOp)); 185 186 for (unsigned i = 0; i < MII->getNumOperands(); ++i) 187 MIB.addOperand(MII->getOperand(i)); 188} 189