LLVM 22.0.0git
HexagonLoopAlign.cpp
Go to the documentation of this file.
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"
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
27 "hexagon-hvx-loop-align-limit-ub", cl::Hidden, cl::init(16),
28 cl::desc("Set hexagon hvx loop upper bound align limit"));
29
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
35 LoopAlignLimitUB("hexagon-loop-align-limit-ub", cl::Hidden, cl::init(8),
36 cl::desc("Set hexagon loop upper bound align limit"));
37
39 LoopAlignLimitLB("hexagon-loop-align-limit-lb", cl::Hidden, cl::init(4),
40 cl::desc("Set hexagon loop lower bound align limit"));
41
43 LoopBndlAlignLimit("hexagon-loop-bundle-align-limit", cl::Hidden,
44 cl::init(4),
45 cl::desc("Set hexagon loop align bundle limit"));
46
48 "hexagon-tiny-loop-bundle-align-limit", cl::Hidden, cl::init(8),
49 cl::desc("Set hexagon tiny-core loop align bundle limit"));
50
52 LoopEdgeThreshold("hexagon-loop-edge-threshold", cl::Hidden, cl::init(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 {
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
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
133bool HexagonLoopAlign::isSingleLoop(MachineBasicBlock &MBB) {
134 int Succs = MBB.succ_size();
135 return (MBB.isSuccessor(&MBB) && (Succs == 2));
136}
137
138bool HexagonLoopAlign::attemptToBalignSmallLoop(MachineFunction &MF,
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);
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).
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(MF.getFunction()))
176 return false;
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(); }
MachineBasicBlock & MBB
static cl::opt< uint32_t > LoopBndlAlignLimit("hexagon-loop-bundle-align-limit", cl::Hidden, cl::init(4), cl::desc("Set hexagon loop align bundle limit"))
static cl::opt< uint32_t > LoopAlignLimitUB("hexagon-loop-align-limit-ub", cl::Hidden, cl::init(8), cl::desc("Set hexagon loop upper bound align limit"))
static cl::opt< uint32_t > LoopAlignLimitLB("hexagon-loop-align-limit-lb", cl::Hidden, cl::init(4), cl::desc("Set hexagon loop lower bound align limit"))
static cl::opt< uint32_t > LoopEdgeThreshold("hexagon-loop-edge-threshold", cl::Hidden, cl::init(7500), cl::desc("Set hexagon loop align edge threshold"))
static cl::opt< uint32_t > HVXLoopAlignLimitUB("hexagon-hvx-loop-align-limit-ub", cl::Hidden, cl::init(16), cl::desc("Set hexagon hvx loop upper bound align limit"))
static cl::opt< bool > DisableLoopAlign("disable-hexagon-loop-align", cl::Hidden, cl::desc("Disable Hexagon loop alignment pass"))
static cl::opt< uint32_t > TinyLoopAlignLimitUB("hexagon-tiny-loop-align-limit-ub", cl::Hidden, cl::init(16), cl::desc("Set hexagon tiny-core loop upper bound align limit"))
static cl::opt< uint32_t > TinyLoopBndlAlignLimit("hexagon-tiny-loop-bundle-align-limit", cl::Hidden, cl::init(8), cl::desc("Set hexagon tiny-core loop align bundle limit"))
uint64_t IntrinsicInst * II
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
#define LLVM_DEBUG(...)
Definition: Debug.h:119
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
uint64_t getFrequency() const
Returns the frequency as a fixpoint number scaled by the entry frequency.
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:314
const HexagonInstrInfo * getInstrInfo() const override
instr_iterator instr_begin()
unsigned succ_size() const
void setAlignment(Align A)
Set alignment of the basic block.
Instructions::iterator instr_iterator
instr_iterator instr_end()
LLVM_ABI bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
MachineBlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate machine basic b...
LLVM_ABI BlockFrequency getBlockFreq(const MachineBasicBlock *MBB) const
getblockFreq - Return block frequency.
BranchProbability getEdgeProbability(const MachineBasicBlock *Src, const MachineBasicBlock *Dst) const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Function & getFunction()
Return the LLVM function that this machine code represents.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:83
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:444
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createHexagonLoopAlign()
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:207
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39