1 //===--- HexagonBranchRelaxation.cpp - Identify and relax long jumps ------===//
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
7 //===----------------------------------------------------------------------===//
9 #define DEBUG_TYPE "hexagon-brelax"
12 #include "HexagonInstrInfo.h"
13 #include "HexagonSubtarget.h"
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/CodeGen/MachineFunction.h"
19 #include "llvm/CodeGen/MachineFunctionPass.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/CodeGen/MachineOperand.h"
22 #include "llvm/CodeGen/Passes.h"
23 #include "llvm/Pass.h"
24 #include "llvm/Support/CommandLine.h"
25 #include "llvm/Support/Debug.h"
26 #include "llvm/Support/raw_ostream.h"
34 // Since we have no exact knowledge of code layout, allow some safety buffer
35 // for jump target. This is measured in bytes.
36 static cl::opt
<uint32_t> BranchRelaxSafetyBuffer("branch-relax-safety-buffer",
37 cl::init(200), cl::Hidden
, cl::ZeroOrMore
, cl::desc("safety buffer size"));
41 FunctionPass
*createHexagonBranchRelaxation();
42 void initializeHexagonBranchRelaxationPass(PassRegistry
&);
44 } // end namespace llvm
48 struct HexagonBranchRelaxation
: public MachineFunctionPass
{
52 HexagonBranchRelaxation() : MachineFunctionPass(ID
) {
53 initializeHexagonBranchRelaxationPass(*PassRegistry::getPassRegistry());
56 bool runOnMachineFunction(MachineFunction
&MF
) override
;
58 StringRef
getPassName() const override
{
59 return "Hexagon Branch Relaxation";
62 void getAnalysisUsage(AnalysisUsage
&AU
) const override
{
64 MachineFunctionPass::getAnalysisUsage(AU
);
68 const HexagonInstrInfo
*HII
;
69 const HexagonRegisterInfo
*HRI
;
71 bool relaxBranches(MachineFunction
&MF
);
72 void computeOffset(MachineFunction
&MF
,
73 DenseMap
<MachineBasicBlock
*, unsigned> &BlockToInstOffset
);
74 bool reGenerateBranch(MachineFunction
&MF
,
75 DenseMap
<MachineBasicBlock
*, unsigned> &BlockToInstOffset
);
76 bool isJumpOutOfRange(MachineInstr
&MI
,
77 DenseMap
<MachineBasicBlock
*, unsigned> &BlockToInstOffset
);
80 char HexagonBranchRelaxation::ID
= 0;
82 } // end anonymous namespace
84 INITIALIZE_PASS(HexagonBranchRelaxation
, "hexagon-brelax",
85 "Hexagon Branch Relaxation", false, false)
87 FunctionPass
*llvm::createHexagonBranchRelaxation() {
88 return new HexagonBranchRelaxation();
91 bool HexagonBranchRelaxation::runOnMachineFunction(MachineFunction
&MF
) {
92 LLVM_DEBUG(dbgs() << "****** Hexagon Branch Relaxation ******\n");
94 auto &HST
= MF
.getSubtarget
<HexagonSubtarget
>();
95 HII
= HST
.getInstrInfo();
96 HRI
= HST
.getRegisterInfo();
99 Changed
= relaxBranches(MF
);
103 void HexagonBranchRelaxation::computeOffset(MachineFunction
&MF
,
104 DenseMap
<MachineBasicBlock
*, unsigned> &OffsetMap
) {
105 // offset of the current instruction from the start.
106 unsigned InstOffset
= 0;
108 if (B
.getAlignment()) {
109 // Although we don't know the exact layout of the final code, we need
110 // to account for alignment padding somehow. This heuristic pads each
111 // aligned basic block according to the alignment value.
112 int ByteAlign
= (1u << B
.getAlignment()) - 1;
113 InstOffset
= (InstOffset
+ ByteAlign
) & ~(ByteAlign
);
115 OffsetMap
[&B
] = InstOffset
;
116 for (auto &MI
: B
.instrs()) {
117 InstOffset
+= HII
->getSize(MI
);
118 // Assume that all extendable branches will be extended.
119 if (MI
.isBranch() && HII
->isExtendable(MI
))
120 InstOffset
+= HEXAGON_INSTR_SIZE
;
125 /// relaxBranches - For Hexagon, if the jump target/loop label is too far from
126 /// the jump/loop instruction then, we need to make sure that we have constant
127 /// extenders set for jumps and loops.
129 /// There are six iterations in this phase. It's self explanatory below.
130 bool HexagonBranchRelaxation::relaxBranches(MachineFunction
&MF
) {
131 // Compute the offset of each basic block
132 // offset of the current instruction from the start.
133 // map for each instruction to the beginning of the function
134 DenseMap
<MachineBasicBlock
*, unsigned> BlockToInstOffset
;
135 computeOffset(MF
, BlockToInstOffset
);
137 return reGenerateBranch(MF
, BlockToInstOffset
);
140 /// Check if a given instruction is:
141 /// - a jump to a distant target
142 /// - that exceeds its immediate range
143 /// If both conditions are true, it requires constant extension.
144 bool HexagonBranchRelaxation::isJumpOutOfRange(MachineInstr
&MI
,
145 DenseMap
<MachineBasicBlock
*, unsigned> &BlockToInstOffset
) {
146 MachineBasicBlock
&B
= *MI
.getParent();
147 auto FirstTerm
= B
.getFirstInstrTerminator();
148 if (FirstTerm
== B
.instr_end())
151 if (HII
->isExtended(MI
))
154 unsigned InstOffset
= BlockToInstOffset
[&B
];
155 unsigned Distance
= 0;
157 // To save time, estimate exact position of a branch instruction
158 // as one at the end of the MBB.
159 // Number of instructions times typical instruction size.
160 InstOffset
+= HII
->nonDbgBBSize(&B
) * HEXAGON_INSTR_SIZE
;
162 MachineBasicBlock
*TBB
= nullptr, *FBB
= nullptr;
163 SmallVector
<MachineOperand
, 4> Cond
;
165 // Try to analyze this branch.
166 if (HII
->analyzeBranch(B
, TBB
, FBB
, Cond
, false)) {
167 // Could not analyze it. See if this is something we can recognize.
168 // If it is a NVJ, it should always have its target in
170 if (HII
->isNewValueJump(*FirstTerm
))
171 TBB
= FirstTerm
->getOperand(HII
->getCExtOpNum(*FirstTerm
)).getMBB();
173 if (TBB
&& &MI
== &*FirstTerm
) {
174 Distance
= std::abs((long long)InstOffset
- BlockToInstOffset
[TBB
])
175 + BranchRelaxSafetyBuffer
;
176 return !HII
->isJumpWithinBranchRange(*FirstTerm
, Distance
);
179 // Look for second terminator.
180 auto SecondTerm
= std::next(FirstTerm
);
181 assert(SecondTerm
!= B
.instr_end() &&
182 (SecondTerm
->isBranch() || SecondTerm
->isCall()) &&
183 "Bad second terminator");
184 if (&MI
!= &*SecondTerm
)
186 // Analyze the second branch in the BB.
187 Distance
= std::abs((long long)InstOffset
- BlockToInstOffset
[FBB
])
188 + BranchRelaxSafetyBuffer
;
189 return !HII
->isJumpWithinBranchRange(*SecondTerm
, Distance
);
194 bool HexagonBranchRelaxation::reGenerateBranch(MachineFunction
&MF
,
195 DenseMap
<MachineBasicBlock
*, unsigned> &BlockToInstOffset
) {
196 bool Changed
= false;
200 if (!MI
.isBranch() || !isJumpOutOfRange(MI
, BlockToInstOffset
))
202 LLVM_DEBUG(dbgs() << "Long distance jump. isExtendable("
203 << HII
->isExtendable(MI
) << ") isConstExtended("
204 << HII
->isConstExtended(MI
) << ") " << MI
);
206 // Since we have not merged HW loops relaxation into
207 // this code (yet), soften our approach for the moment.
208 if (!HII
->isExtendable(MI
) && !HII
->isExtended(MI
)) {
209 LLVM_DEBUG(dbgs() << "\tUnderimplemented relax branch instruction.\n");
211 // Find which operand is expandable.
212 int ExtOpNum
= HII
->getCExtOpNum(MI
);
213 MachineOperand
&MO
= MI
.getOperand(ExtOpNum
);
214 // This need to be something we understand. So far we assume all
215 // branches have only MBB address as expandable field.
216 // If it changes, this will need to be expanded.
217 assert(MO
.isMBB() && "Branch with unknown expandable field type");
218 // Mark given operand as extended.
219 MO
.addTargetFlag(HexagonII::HMOTF_ConstExtended
);