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