xref: /freebsd/contrib/llvm-project/llvm/lib/Target/Hexagon/HexagonLoopAlign.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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;
HexagonLoopAlign()64   HexagonLoopAlign() : MachineFunctionPass(ID) {}
65   bool shouldBalignLoop(MachineBasicBlock &BB, bool AboveThres);
66   bool isSingleLoop(MachineBasicBlock &MBB);
67   bool attemptToBalignSmallLoop(MachineFunction &MF, MachineBasicBlock &MBB);
68 
getAnalysisUsage(AnalysisUsage & AU) const69   void getAnalysisUsage(AnalysisUsage &AU) const override {
70     AU.addRequired<MachineBranchProbabilityInfoWrapperPass>();
71     AU.addRequired<MachineBlockFrequencyInfoWrapperPass>();
72     MachineFunctionPass::getAnalysisUsage(AU);
73   }
74 
getPassName() const75   StringRef getPassName() const override { return "Hexagon LoopAlign pass"; }
76   bool runOnMachineFunction(MachineFunction &MF) override;
77 };
78 
79 char HexagonLoopAlign::ID = 0;
80 
shouldBalignLoop(MachineBasicBlock & BB,bool AboveThres)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 
isSingleLoop(MachineBasicBlock & MBB)133 bool HexagonLoopAlign::isSingleLoop(MachineBasicBlock &MBB) {
134   int Succs = MBB.succ_size();
135   return (MBB.isSuccessor(&MBB) && (Succs == 2));
136 }
137 
attemptToBalignSmallLoop(MachineFunction & MF,MachineBasicBlock & MBB)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 
runOnMachineFunction(MachineFunction & MF)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 
createHexagonLoopAlign()209 FunctionPass *llvm::createHexagonLoopAlign() { return new HexagonLoopAlign(); }
210