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