1 //===----- HexagonLoopAlign.cpp - Generate loop alignment directives -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // Inspect a basic block and if its single basic block loop with a small 9 // number of instructions, set the prefLoopAlignment to 32 bytes (5). 10 //===----------------------------------------------------------------------===// 11 12 #define DEBUG_TYPE "hexagon-loop-align" 13 14 #include "HexagonTargetMachine.h" 15 #include "llvm/CodeGen/MachineBlockFrequencyInfo.h" 16 #include "llvm/CodeGen/MachineBranchProbabilityInfo.h" 17 #include "llvm/CodeGen/SchedulerRegistry.h" 18 #include "llvm/Support/Debug.h" 19 20 using namespace llvm; 21 22 static cl::opt<bool> 23 DisableLoopAlign("disable-hexagon-loop-align", cl::Hidden, 24 cl::desc("Disable Hexagon loop alignment pass")); 25 26 static cl::opt<uint32_t> HVXLoopAlignLimitUB( 27 "hexagon-hvx-loop-align-limit-ub", cl::Hidden, cl::init(16), 28 cl::desc("Set hexagon hvx loop upper bound align limit")); 29 30 static cl::opt<uint32_t> TinyLoopAlignLimitUB( 31 "hexagon-tiny-loop-align-limit-ub", cl::Hidden, cl::init(16), 32 cl::desc("Set hexagon tiny-core loop upper bound align limit")); 33 34 static cl::opt<uint32_t> 35 LoopAlignLimitUB("hexagon-loop-align-limit-ub", cl::Hidden, cl::init(8), 36 cl::desc("Set hexagon loop upper bound align limit")); 37 38 static cl::opt<uint32_t> 39 LoopAlignLimitLB("hexagon-loop-align-limit-lb", cl::Hidden, cl::init(4), 40 cl::desc("Set hexagon loop lower bound align limit")); 41 42 static cl::opt<uint32_t> 43 LoopBndlAlignLimit("hexagon-loop-bundle-align-limit", cl::Hidden, 44 cl::init(4), 45 cl::desc("Set hexagon loop align bundle limit")); 46 47 static cl::opt<uint32_t> TinyLoopBndlAlignLimit( 48 "hexagon-tiny-loop-bundle-align-limit", cl::Hidden, cl::init(8), 49 cl::desc("Set hexagon tiny-core loop align bundle limit")); 50 51 static cl::opt<uint32_t> 52 LoopEdgeThreshold("hexagon-loop-edge-threshold", cl::Hidden, cl::init(7500), 53 cl::desc("Set hexagon loop align edge theshold")); 54 55 namespace llvm { 56 FunctionPass *createHexagonLoopAlign(); 57 void initializeHexagonLoopAlignPass(PassRegistry &); 58 } // namespace llvm 59 60 namespace { 61 62 class HexagonLoopAlign : public MachineFunctionPass { 63 const HexagonSubtarget *HST = nullptr; 64 const TargetMachine *HTM = nullptr; 65 const HexagonInstrInfo *HII = nullptr; 66 67 public: 68 static char ID; 69 HexagonLoopAlign() : MachineFunctionPass(ID) { 70 initializeHexagonLoopAlignPass(*PassRegistry::getPassRegistry()); 71 } 72 bool shouldBalignLoop(MachineBasicBlock &BB, bool AboveThres); 73 bool isSingleLoop(MachineBasicBlock &MBB); 74 bool attemptToBalignSmallLoop(MachineFunction &MF, MachineBasicBlock &MBB); 75 76 void getAnalysisUsage(AnalysisUsage &AU) const override { 77 AU.addRequired<MachineBranchProbabilityInfoWrapperPass>(); 78 AU.addRequired<MachineBlockFrequencyInfoWrapperPass>(); 79 MachineFunctionPass::getAnalysisUsage(AU); 80 } 81 82 StringRef getPassName() const override { return "Hexagon LoopAlign pass"; } 83 bool runOnMachineFunction(MachineFunction &MF) override; 84 }; 85 86 char HexagonLoopAlign::ID = 0; 87 88 bool HexagonLoopAlign::shouldBalignLoop(MachineBasicBlock &BB, 89 bool AboveThres) { 90 bool isVec = false; 91 unsigned InstCnt = 0; 92 unsigned BndlCnt = 0; 93 94 for (MachineBasicBlock::instr_iterator II = BB.instr_begin(), 95 IE = BB.instr_end(); 96 II != IE; ++II) { 97 98 // End if the instruction is endloop. 99 if (HII->isEndLoopN(II->getOpcode())) 100 break; 101 // Count the number of bundles. 102 if (II->isBundle()) { 103 BndlCnt++; 104 continue; 105 } 106 // Skip over debug instructions. 107 if (II->isDebugInstr()) 108 continue; 109 // Check if there are any HVX instructions in loop. 110 isVec |= HII->isHVXVec(*II); 111 // Count the number of instructions. 112 InstCnt++; 113 } 114 115 LLVM_DEBUG({ 116 dbgs() << "Bundle Count : " << BndlCnt << "\n"; 117 dbgs() << "Instruction Count : " << InstCnt << "\n"; 118 }); 119 120 unsigned LimitUB = 0; 121 unsigned LimitBndl = LoopBndlAlignLimit; 122 // The conditions in the order of priority. 123 if (HST->isTinyCore()) { 124 LimitUB = TinyLoopAlignLimitUB; 125 LimitBndl = TinyLoopBndlAlignLimit; 126 } else if (isVec) 127 LimitUB = HVXLoopAlignLimitUB; 128 else if (AboveThres) 129 LimitUB = LoopAlignLimitUB; 130 131 // if the upper bound is not set to a value, implies we didn't meet 132 // the criteria. 133 if (LimitUB == 0) 134 return false; 135 136 return InstCnt >= LoopAlignLimitLB && InstCnt <= LimitUB && 137 BndlCnt <= LimitBndl; 138 } 139 140 bool HexagonLoopAlign::isSingleLoop(MachineBasicBlock &MBB) { 141 int Succs = MBB.succ_size(); 142 return (MBB.isSuccessor(&MBB) && (Succs == 2)); 143 } 144 145 bool HexagonLoopAlign::attemptToBalignSmallLoop(MachineFunction &MF, 146 MachineBasicBlock &MBB) { 147 if (!isSingleLoop(MBB)) 148 return false; 149 150 const MachineBranchProbabilityInfo *MBPI = 151 &getAnalysis<MachineBranchProbabilityInfoWrapperPass>().getMBPI(); 152 const MachineBlockFrequencyInfo *MBFI = 153 &getAnalysis<MachineBlockFrequencyInfoWrapperPass>().getMBFI(); 154 155 // Compute frequency of back edge, 156 BlockFrequency BlockFreq = MBFI->getBlockFreq(&MBB); 157 BranchProbability BrProb = MBPI->getEdgeProbability(&MBB, &MBB); 158 BlockFrequency EdgeFreq = BlockFreq * BrProb; 159 LLVM_DEBUG({ 160 dbgs() << "Loop Align Pass:\n"; 161 dbgs() << "\tedge with freq(" << EdgeFreq.getFrequency() << ")\n"; 162 }); 163 164 bool AboveThres = EdgeFreq.getFrequency() > LoopEdgeThreshold; 165 if (shouldBalignLoop(MBB, AboveThres)) { 166 // We found a loop, change its alignment to be 32 (5). 167 MBB.setAlignment(llvm::Align(1 << 5)); 168 return true; 169 } 170 return false; 171 } 172 173 // Inspect each basic block, and if its a single BB loop, see if it 174 // meets the criteria for increasing alignment to 32. 175 176 bool HexagonLoopAlign::runOnMachineFunction(MachineFunction &MF) { 177 178 HST = &MF.getSubtarget<HexagonSubtarget>(); 179 HII = HST->getInstrInfo(); 180 HTM = &MF.getTarget(); 181 182 if (skipFunction(MF.getFunction())) 183 return false; 184 if (DisableLoopAlign) 185 return false; 186 187 // This optimization is performed at 188 // i) -O2 and above, and when the loop has a HVX instruction. 189 // ii) -O3 190 if (HST->useHVXOps()) { 191 if (HTM->getOptLevel() < CodeGenOptLevel::Default) 192 return false; 193 } else { 194 if (HTM->getOptLevel() < CodeGenOptLevel::Aggressive) 195 return false; 196 } 197 198 bool Changed = false; 199 for (MachineFunction::iterator MBBi = MF.begin(), MBBe = MF.end(); 200 MBBi != MBBe; ++MBBi) { 201 MachineBasicBlock &MBB = *MBBi; 202 Changed |= attemptToBalignSmallLoop(MF, MBB); 203 } 204 return Changed; 205 } 206 207 } // namespace 208 209 INITIALIZE_PASS(HexagonLoopAlign, "hexagon-loop-align", 210 "Hexagon LoopAlign pass", false, false) 211 212 //===----------------------------------------------------------------------===// 213 // Public Constructor Functions 214 //===----------------------------------------------------------------------===// 215 216 FunctionPass *llvm::createHexagonLoopAlign() { return new HexagonLoopAlign(); } 217