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