LLVM 20.0.0git
HexagonCFGOptimizer.cpp
Go to the documentation of this file.
1//===- HexagonCFGOptimizer.cpp - CFG optimizations ------------------------===//
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
9#include "Hexagon.h"
18#include "llvm/Pass.h"
20#include <cassert>
21#include <vector>
22
23using namespace llvm;
24
25#define DEBUG_TYPE "hexagon_cfg"
26
27namespace llvm {
28
31
32} // end namespace llvm
33
34namespace {
35
36class HexagonCFGOptimizer : public MachineFunctionPass {
37private:
38 void InvertAndChangeJumpTarget(MachineInstr &, MachineBasicBlock *);
39 bool isOnFallThroughPath(MachineBasicBlock *MBB);
40
41public:
42 static char ID;
43
44 HexagonCFGOptimizer() : MachineFunctionPass(ID) {
46 }
47
48 StringRef getPassName() const override { return "Hexagon CFG Optimizer"; }
49 bool runOnMachineFunction(MachineFunction &Fn) override;
50
53 MachineFunctionProperties::Property::NoVRegs);
54 }
55};
56
57} // end anonymous namespace
58
59char HexagonCFGOptimizer::ID = 0;
60
61static bool IsConditionalBranch(int Opc) {
62 switch (Opc) {
63 case Hexagon::J2_jumpt:
64 case Hexagon::J2_jumptpt:
65 case Hexagon::J2_jumpf:
66 case Hexagon::J2_jumpfpt:
67 case Hexagon::J2_jumptnew:
68 case Hexagon::J2_jumpfnew:
69 case Hexagon::J2_jumptnewpt:
70 case Hexagon::J2_jumpfnewpt:
71 return true;
72 }
73 return false;
74}
75
76static bool IsUnconditionalJump(int Opc) {
77 return (Opc == Hexagon::J2_jump);
78}
79
80void HexagonCFGOptimizer::InvertAndChangeJumpTarget(
81 MachineInstr &MI, MachineBasicBlock *NewTarget) {
82 const TargetInstrInfo *TII =
83 MI.getParent()->getParent()->getSubtarget().getInstrInfo();
84 int NewOpcode = 0;
85 switch (MI.getOpcode()) {
86 case Hexagon::J2_jumpt:
87 NewOpcode = Hexagon::J2_jumpf;
88 break;
89 case Hexagon::J2_jumpf:
90 NewOpcode = Hexagon::J2_jumpt;
91 break;
92 case Hexagon::J2_jumptnewpt:
93 NewOpcode = Hexagon::J2_jumpfnewpt;
94 break;
95 case Hexagon::J2_jumpfnewpt:
96 NewOpcode = Hexagon::J2_jumptnewpt;
97 break;
98 default:
99 llvm_unreachable("Cannot handle this case");
100 }
101
102 MI.setDesc(TII->get(NewOpcode));
103 MI.getOperand(1).setMBB(NewTarget);
104}
105
106bool HexagonCFGOptimizer::isOnFallThroughPath(MachineBasicBlock *MBB) {
107 if (MBB->canFallThrough())
108 return true;
110 if (PB->isLayoutSuccessor(MBB) && PB->canFallThrough())
111 return true;
112 return false;
113}
114
115bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
116 if (skipFunction(Fn.getFunction()))
117 return false;
118
119 // Loop over all of the basic blocks.
120 for (MachineBasicBlock &MBB : Fn) {
121 // Traverse the basic block.
123 if (MII != MBB.end()) {
124 MachineInstr &MI = *MII;
125 int Opc = MI.getOpcode();
126 if (IsConditionalBranch(Opc)) {
127 // (Case 1) Transform the code if the following condition occurs:
128 // BB1: if (p0) jump BB3
129 // ...falls-through to BB2 ...
130 // BB2: jump BB4
131 // ...next block in layout is BB3...
132 // BB3: ...
133 //
134 // Transform this to:
135 // BB1: if (!p0) jump BB4
136 // Remove BB2
137 // BB3: ...
138 //
139 // (Case 2) A variation occurs when BB3 contains a JMP to BB4:
140 // BB1: if (p0) jump BB3
141 // ...falls-through to BB2 ...
142 // BB2: jump BB4
143 // ...other basic blocks ...
144 // BB4:
145 // ...not a fall-thru
146 // BB3: ...
147 // jump BB4
148 //
149 // Transform this to:
150 // BB1: if (!p0) jump BB4
151 // Remove BB2
152 // BB3: ...
153 // BB4: ...
154 unsigned NumSuccs = MBB.succ_size();
156 MachineBasicBlock* FirstSucc = *SI;
157 MachineBasicBlock* SecondSucc = *(++SI);
158 MachineBasicBlock* LayoutSucc = nullptr;
159 MachineBasicBlock* JumpAroundTarget = nullptr;
160
161 if (MBB.isLayoutSuccessor(FirstSucc)) {
162 LayoutSucc = FirstSucc;
163 JumpAroundTarget = SecondSucc;
164 } else if (MBB.isLayoutSuccessor(SecondSucc)) {
165 LayoutSucc = SecondSucc;
166 JumpAroundTarget = FirstSucc;
167 } else {
168 // Odd case...cannot handle.
169 }
170
171 // The target of the unconditional branch must be JumpAroundTarget.
172 // TODO: If not, we should not invert the unconditional branch.
173 MachineBasicBlock* CondBranchTarget = nullptr;
174 if (MI.getOpcode() == Hexagon::J2_jumpt ||
175 MI.getOpcode() == Hexagon::J2_jumpf) {
176 CondBranchTarget = MI.getOperand(1).getMBB();
177 }
178
179 if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
180 continue;
181 }
182
183 if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
184 // Ensure that BB2 has one instruction -- an unconditional jump.
185 if ((LayoutSucc->size() == 1) &&
186 IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
187 assert(JumpAroundTarget && "jump target is needed to process second basic block");
188 MachineBasicBlock* UncondTarget =
189 LayoutSucc->front().getOperand(0).getMBB();
190 // Check if the layout successor of BB2 is BB3.
191 bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
192 bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
193 !JumpAroundTarget->empty() &&
194 IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
195 JumpAroundTarget->pred_size() == 1 &&
196 JumpAroundTarget->succ_size() == 1;
197
198 if (case1 || case2) {
199 InvertAndChangeJumpTarget(MI, UncondTarget);
200 MBB.replaceSuccessor(JumpAroundTarget, UncondTarget);
201
202 // Remove the unconditional branch in LayoutSucc.
203 LayoutSucc->erase(LayoutSucc->begin());
204 LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget);
205
206 // This code performs the conversion for case 2, which moves
207 // the block to the fall-thru case (BB3 in the code above).
208 if (case2 && !case1) {
209 JumpAroundTarget->moveAfter(LayoutSucc);
210 // only move a block if it doesn't have a fall-thru. otherwise
211 // the CFG will be incorrect.
212 if (!isOnFallThroughPath(UncondTarget))
213 UncondTarget->moveAfter(JumpAroundTarget);
214 }
215
216 // Correct live-in information. Is used by post-RA scheduler
217 // The live-in to LayoutSucc is now all values live-in to
218 // JumpAroundTarget.
219 std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn(
220 LayoutSucc->livein_begin(), LayoutSucc->livein_end());
221 std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn(
222 JumpAroundTarget->livein_begin(),
223 JumpAroundTarget->livein_end());
224 for (const auto &OrigLI : OrigLiveIn)
225 LayoutSucc->removeLiveIn(OrigLI.PhysReg);
226 for (const auto &NewLI : NewLiveIn)
227 LayoutSucc->addLiveIn(NewLI);
228 }
229 }
230 }
231 }
232 }
233 }
234 return true;
235}
236
237//===----------------------------------------------------------------------===//
238// Public Constructor Functions
239//===----------------------------------------------------------------------===//
240
241INITIALIZE_PASS(HexagonCFGOptimizer, "hexagon-cfg", "Hexagon CFG Optimizer",
242 false, false)
243
245 return new HexagonCFGOptimizer();
246}
MachineBasicBlock & MBB
static bool IsConditionalBranch(int Opc)
static bool IsUnconditionalJump(int Opc)
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
PassBuilder PB(Machine, PassOpts->PTO, std::nullopt, &PIC)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:310
unsigned pred_size() const
livein_iterator livein_end() const
void replaceSuccessor(MachineBasicBlock *Old, MachineBasicBlock *New)
Replace successor OLD with NEW and update probability info.
bool canFallThrough()
Return true if the block can implicitly transfer control to the block after it by falling off the end...
void removeLiveIn(MCRegister Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Remove the specified register from the live in set.
iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
livein_iterator livein_begin() const
unsigned succ_size() const
SmallVectorImpl< MachineBasicBlock * >::iterator succ_iterator
bool isLayoutSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB will be emitted immediately after this block, such that if this bloc...
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
bool isSuccessor(const MachineBasicBlock *MBB) const
Return true if the specified MBB is a successor of this block.
iterator_range< pred_iterator > predecessors()
void moveAfter(MachineBasicBlock *NewBefore)
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
virtual MachineFunctionProperties getRequiredProperties() const
Properties which a MachineFunction may have at a given point in time.
MachineFunctionProperties & set(Property P)
Function & getFunction()
Return the LLVM function that this machine code represents.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
MachineBasicBlock * getMBB() const
PassRegistry - This class manages the registration and intitialization of the pass subsystem as appli...
Definition: PassRegistry.h:37
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
TargetInstrInfo - Interface to description of machine instruction set.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
FunctionPass * createHexagonCFGOptimizer()
void initializeHexagonCFGOptimizerPass(PassRegistry &)