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
20using namespace llvm;
21
22static cl::opt<bool>
23 DisableLoopAlign("disable-hexagon-loop-align", cl::Hidden,
24 cl::desc("Disable Hexagon loop alignment pass"));
25
26static cl::opt<uint32_t> HVXLoopAlignLimitUB(
27 "hexagon-hvx-loop-align-limit-ub", cl::Hidden, cl::init(Val: 16),
28 cl::desc("Set hexagon hvx loop upper bound align limit"));
29
30static cl::opt<uint32_t> TinyLoopAlignLimitUB(
31 "hexagon-tiny-loop-align-limit-ub", cl::Hidden, cl::init(Val: 16),
32 cl::desc("Set hexagon tiny-core loop upper bound align limit"));
33
34static cl::opt<uint32_t>
35 LoopAlignLimitUB("hexagon-loop-align-limit-ub", cl::Hidden, cl::init(Val: 8),
36 cl::desc("Set hexagon loop upper bound align limit"));
37
38static cl::opt<uint32_t>
39 LoopAlignLimitLB("hexagon-loop-align-limit-lb", cl::Hidden, cl::init(Val: 4),
40 cl::desc("Set hexagon loop lower bound align limit"));
41
42static cl::opt<uint32_t>
43 LoopBndlAlignLimit("hexagon-loop-bundle-align-limit", cl::Hidden,
44 cl::init(Val: 4),
45 cl::desc("Set hexagon loop align bundle limit"));
46
47static cl::opt<uint32_t> TinyLoopBndlAlignLimit(
48 "hexagon-tiny-loop-bundle-align-limit", cl::Hidden, cl::init(Val: 8),
49 cl::desc("Set hexagon tiny-core loop align bundle limit"));
50
51static cl::opt<uint32_t>
52 LoopEdgeThreshold("hexagon-loop-edge-threshold", cl::Hidden, cl::init(Val: 7500),
53 cl::desc("Set hexagon loop align edge threshold"));
54
55namespace {
56
57class HexagonLoopAlign : public MachineFunctionPass {
58 const HexagonSubtarget *HST = nullptr;
59 const TargetMachine *HTM = nullptr;
60 const HexagonInstrInfo *HII = nullptr;
61
62public:
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
79char HexagonLoopAlign::ID = 0;
80
81bool 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(Opcode: 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(MI: *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
133bool HexagonLoopAlign::isSingleLoop(MachineBasicBlock &MBB) {
134 int Succs = MBB.succ_size();
135 return (MBB.isSuccessor(MBB: &MBB) && (Succs == 2));
136}
137
138bool 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: &MBB);
150 BranchProbability BrProb = MBPI->getEdgeProbability(Src: &MBB, Dst: &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(BB&: 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
169bool HexagonLoopAlign::runOnMachineFunction(MachineFunction &MF) {
170
171 HST = &MF.getSubtarget<HexagonSubtarget>();
172 HII = HST->getInstrInfo();
173 HTM = &MF.getTarget();
174
175 if (skipFunction(F: 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
202INITIALIZE_PASS(HexagonLoopAlign, "hexagon-loop-align",
203 "Hexagon LoopAlign pass", false, false)
204
205//===----------------------------------------------------------------------===//
206// Public Constructor Functions
207//===----------------------------------------------------------------------===//
208
209FunctionPass *llvm::createHexagonLoopAlign() { return new HexagonLoopAlign(); }
210