1*9880d681SAndroid Build Coastguard Worker //===-- HexagonCFGOptimizer.cpp - CFG optimizations -----------------------===//
2*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
3*9880d681SAndroid Build Coastguard Worker //
4*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
5*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
6*9880d681SAndroid Build Coastguard Worker //
7*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
8*9880d681SAndroid Build Coastguard Worker
9*9880d681SAndroid Build Coastguard Worker #include "Hexagon.h"
10*9880d681SAndroid Build Coastguard Worker #include "HexagonMachineFunctionInfo.h"
11*9880d681SAndroid Build Coastguard Worker #include "HexagonSubtarget.h"
12*9880d681SAndroid Build Coastguard Worker #include "HexagonTargetMachine.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineDominators.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineLoopInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineRegisterInfo.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/MathExtras.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
24*9880d681SAndroid Build Coastguard Worker
25*9880d681SAndroid Build Coastguard Worker using namespace llvm;
26*9880d681SAndroid Build Coastguard Worker
27*9880d681SAndroid Build Coastguard Worker #define DEBUG_TYPE "hexagon_cfg"
28*9880d681SAndroid Build Coastguard Worker
29*9880d681SAndroid Build Coastguard Worker namespace llvm {
30*9880d681SAndroid Build Coastguard Worker FunctionPass *createHexagonCFGOptimizer();
31*9880d681SAndroid Build Coastguard Worker void initializeHexagonCFGOptimizerPass(PassRegistry&);
32*9880d681SAndroid Build Coastguard Worker }
33*9880d681SAndroid Build Coastguard Worker
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker namespace {
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker class HexagonCFGOptimizer : public MachineFunctionPass {
38*9880d681SAndroid Build Coastguard Worker
39*9880d681SAndroid Build Coastguard Worker private:
40*9880d681SAndroid Build Coastguard Worker void InvertAndChangeJumpTarget(MachineInstr &, MachineBasicBlock *);
41*9880d681SAndroid Build Coastguard Worker
42*9880d681SAndroid Build Coastguard Worker public:
43*9880d681SAndroid Build Coastguard Worker static char ID;
HexagonCFGOptimizer()44*9880d681SAndroid Build Coastguard Worker HexagonCFGOptimizer() : MachineFunctionPass(ID) {
45*9880d681SAndroid Build Coastguard Worker initializeHexagonCFGOptimizerPass(*PassRegistry::getPassRegistry());
46*9880d681SAndroid Build Coastguard Worker }
47*9880d681SAndroid Build Coastguard Worker
getPassName() const48*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override {
49*9880d681SAndroid Build Coastguard Worker return "Hexagon CFG Optimizer";
50*9880d681SAndroid Build Coastguard Worker }
51*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &Fn) override;
getRequiredProperties() const52*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties getRequiredProperties() const override {
53*9880d681SAndroid Build Coastguard Worker return MachineFunctionProperties().set(
54*9880d681SAndroid Build Coastguard Worker MachineFunctionProperties::Property::AllVRegsAllocated);
55*9880d681SAndroid Build Coastguard Worker }
56*9880d681SAndroid Build Coastguard Worker };
57*9880d681SAndroid Build Coastguard Worker
58*9880d681SAndroid Build Coastguard Worker
59*9880d681SAndroid Build Coastguard Worker char HexagonCFGOptimizer::ID = 0;
60*9880d681SAndroid Build Coastguard Worker
IsConditionalBranch(int Opc)61*9880d681SAndroid Build Coastguard Worker static bool IsConditionalBranch(int Opc) {
62*9880d681SAndroid Build Coastguard Worker return (Opc == Hexagon::J2_jumpt) || (Opc == Hexagon::J2_jumpf)
63*9880d681SAndroid Build Coastguard Worker || (Opc == Hexagon::J2_jumptnewpt) || (Opc == Hexagon::J2_jumpfnewpt);
64*9880d681SAndroid Build Coastguard Worker }
65*9880d681SAndroid Build Coastguard Worker
66*9880d681SAndroid Build Coastguard Worker
IsUnconditionalJump(int Opc)67*9880d681SAndroid Build Coastguard Worker static bool IsUnconditionalJump(int Opc) {
68*9880d681SAndroid Build Coastguard Worker return (Opc == Hexagon::J2_jump);
69*9880d681SAndroid Build Coastguard Worker }
70*9880d681SAndroid Build Coastguard Worker
InvertAndChangeJumpTarget(MachineInstr & MI,MachineBasicBlock * NewTarget)71*9880d681SAndroid Build Coastguard Worker void HexagonCFGOptimizer::InvertAndChangeJumpTarget(
72*9880d681SAndroid Build Coastguard Worker MachineInstr &MI, MachineBasicBlock *NewTarget) {
73*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII =
74*9880d681SAndroid Build Coastguard Worker MI.getParent()->getParent()->getSubtarget().getInstrInfo();
75*9880d681SAndroid Build Coastguard Worker int NewOpcode = 0;
76*9880d681SAndroid Build Coastguard Worker switch (MI.getOpcode()) {
77*9880d681SAndroid Build Coastguard Worker case Hexagon::J2_jumpt:
78*9880d681SAndroid Build Coastguard Worker NewOpcode = Hexagon::J2_jumpf;
79*9880d681SAndroid Build Coastguard Worker break;
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker case Hexagon::J2_jumpf:
82*9880d681SAndroid Build Coastguard Worker NewOpcode = Hexagon::J2_jumpt;
83*9880d681SAndroid Build Coastguard Worker break;
84*9880d681SAndroid Build Coastguard Worker
85*9880d681SAndroid Build Coastguard Worker case Hexagon::J2_jumptnewpt:
86*9880d681SAndroid Build Coastguard Worker NewOpcode = Hexagon::J2_jumpfnewpt;
87*9880d681SAndroid Build Coastguard Worker break;
88*9880d681SAndroid Build Coastguard Worker
89*9880d681SAndroid Build Coastguard Worker case Hexagon::J2_jumpfnewpt:
90*9880d681SAndroid Build Coastguard Worker NewOpcode = Hexagon::J2_jumptnewpt;
91*9880d681SAndroid Build Coastguard Worker break;
92*9880d681SAndroid Build Coastguard Worker
93*9880d681SAndroid Build Coastguard Worker default:
94*9880d681SAndroid Build Coastguard Worker llvm_unreachable("Cannot handle this case");
95*9880d681SAndroid Build Coastguard Worker }
96*9880d681SAndroid Build Coastguard Worker
97*9880d681SAndroid Build Coastguard Worker MI.setDesc(TII->get(NewOpcode));
98*9880d681SAndroid Build Coastguard Worker MI.getOperand(1).setMBB(NewTarget);
99*9880d681SAndroid Build Coastguard Worker }
100*9880d681SAndroid Build Coastguard Worker
101*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & Fn)102*9880d681SAndroid Build Coastguard Worker bool HexagonCFGOptimizer::runOnMachineFunction(MachineFunction &Fn) {
103*9880d681SAndroid Build Coastguard Worker if (skipFunction(*Fn.getFunction()))
104*9880d681SAndroid Build Coastguard Worker return false;
105*9880d681SAndroid Build Coastguard Worker
106*9880d681SAndroid Build Coastguard Worker // Loop over all of the basic blocks.
107*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator MBBb = Fn.begin(), MBBe = Fn.end();
108*9880d681SAndroid Build Coastguard Worker MBBb != MBBe; ++MBBb) {
109*9880d681SAndroid Build Coastguard Worker MachineBasicBlock *MBB = &*MBBb;
110*9880d681SAndroid Build Coastguard Worker
111*9880d681SAndroid Build Coastguard Worker // Traverse the basic block.
112*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MII = MBB->getFirstTerminator();
113*9880d681SAndroid Build Coastguard Worker if (MII != MBB->end()) {
114*9880d681SAndroid Build Coastguard Worker MachineInstr &MI = *MII;
115*9880d681SAndroid Build Coastguard Worker int Opc = MI.getOpcode();
116*9880d681SAndroid Build Coastguard Worker if (IsConditionalBranch(Opc)) {
117*9880d681SAndroid Build Coastguard Worker
118*9880d681SAndroid Build Coastguard Worker //
119*9880d681SAndroid Build Coastguard Worker // (Case 1) Transform the code if the following condition occurs:
120*9880d681SAndroid Build Coastguard Worker // BB1: if (p0) jump BB3
121*9880d681SAndroid Build Coastguard Worker // ...falls-through to BB2 ...
122*9880d681SAndroid Build Coastguard Worker // BB2: jump BB4
123*9880d681SAndroid Build Coastguard Worker // ...next block in layout is BB3...
124*9880d681SAndroid Build Coastguard Worker // BB3: ...
125*9880d681SAndroid Build Coastguard Worker //
126*9880d681SAndroid Build Coastguard Worker // Transform this to:
127*9880d681SAndroid Build Coastguard Worker // BB1: if (!p0) jump BB4
128*9880d681SAndroid Build Coastguard Worker // Remove BB2
129*9880d681SAndroid Build Coastguard Worker // BB3: ...
130*9880d681SAndroid Build Coastguard Worker //
131*9880d681SAndroid Build Coastguard Worker // (Case 2) A variation occurs when BB3 contains a JMP to BB4:
132*9880d681SAndroid Build Coastguard Worker // BB1: if (p0) jump BB3
133*9880d681SAndroid Build Coastguard Worker // ...falls-through to BB2 ...
134*9880d681SAndroid Build Coastguard Worker // BB2: jump BB4
135*9880d681SAndroid Build Coastguard Worker // ...other basic blocks ...
136*9880d681SAndroid Build Coastguard Worker // BB4:
137*9880d681SAndroid Build Coastguard Worker // ...not a fall-thru
138*9880d681SAndroid Build Coastguard Worker // BB3: ...
139*9880d681SAndroid Build Coastguard Worker // jump BB4
140*9880d681SAndroid Build Coastguard Worker //
141*9880d681SAndroid Build Coastguard Worker // Transform this to:
142*9880d681SAndroid Build Coastguard Worker // BB1: if (!p0) jump BB4
143*9880d681SAndroid Build Coastguard Worker // Remove BB2
144*9880d681SAndroid Build Coastguard Worker // BB3: ...
145*9880d681SAndroid Build Coastguard Worker // BB4: ...
146*9880d681SAndroid Build Coastguard Worker //
147*9880d681SAndroid Build Coastguard Worker unsigned NumSuccs = MBB->succ_size();
148*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::succ_iterator SI = MBB->succ_begin();
149*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* FirstSucc = *SI;
150*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* SecondSucc = *(++SI);
151*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* LayoutSucc = nullptr;
152*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* JumpAroundTarget = nullptr;
153*9880d681SAndroid Build Coastguard Worker
154*9880d681SAndroid Build Coastguard Worker if (MBB->isLayoutSuccessor(FirstSucc)) {
155*9880d681SAndroid Build Coastguard Worker LayoutSucc = FirstSucc;
156*9880d681SAndroid Build Coastguard Worker JumpAroundTarget = SecondSucc;
157*9880d681SAndroid Build Coastguard Worker } else if (MBB->isLayoutSuccessor(SecondSucc)) {
158*9880d681SAndroid Build Coastguard Worker LayoutSucc = SecondSucc;
159*9880d681SAndroid Build Coastguard Worker JumpAroundTarget = FirstSucc;
160*9880d681SAndroid Build Coastguard Worker } else {
161*9880d681SAndroid Build Coastguard Worker // Odd case...cannot handle.
162*9880d681SAndroid Build Coastguard Worker }
163*9880d681SAndroid Build Coastguard Worker
164*9880d681SAndroid Build Coastguard Worker // The target of the unconditional branch must be JumpAroundTarget.
165*9880d681SAndroid Build Coastguard Worker // TODO: If not, we should not invert the unconditional branch.
166*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* CondBranchTarget = nullptr;
167*9880d681SAndroid Build Coastguard Worker if (MI.getOpcode() == Hexagon::J2_jumpt ||
168*9880d681SAndroid Build Coastguard Worker MI.getOpcode() == Hexagon::J2_jumpf) {
169*9880d681SAndroid Build Coastguard Worker CondBranchTarget = MI.getOperand(1).getMBB();
170*9880d681SAndroid Build Coastguard Worker }
171*9880d681SAndroid Build Coastguard Worker
172*9880d681SAndroid Build Coastguard Worker if (!LayoutSucc || (CondBranchTarget != JumpAroundTarget)) {
173*9880d681SAndroid Build Coastguard Worker continue;
174*9880d681SAndroid Build Coastguard Worker }
175*9880d681SAndroid Build Coastguard Worker
176*9880d681SAndroid Build Coastguard Worker if ((NumSuccs == 2) && LayoutSucc && (LayoutSucc->pred_size() == 1)) {
177*9880d681SAndroid Build Coastguard Worker
178*9880d681SAndroid Build Coastguard Worker // Ensure that BB2 has one instruction -- an unconditional jump.
179*9880d681SAndroid Build Coastguard Worker if ((LayoutSucc->size() == 1) &&
180*9880d681SAndroid Build Coastguard Worker IsUnconditionalJump(LayoutSucc->front().getOpcode())) {
181*9880d681SAndroid Build Coastguard Worker assert(JumpAroundTarget && "jump target is needed to process second basic block");
182*9880d681SAndroid Build Coastguard Worker MachineBasicBlock* UncondTarget =
183*9880d681SAndroid Build Coastguard Worker LayoutSucc->front().getOperand(0).getMBB();
184*9880d681SAndroid Build Coastguard Worker // Check if the layout successor of BB2 is BB3.
185*9880d681SAndroid Build Coastguard Worker bool case1 = LayoutSucc->isLayoutSuccessor(JumpAroundTarget);
186*9880d681SAndroid Build Coastguard Worker bool case2 = JumpAroundTarget->isSuccessor(UncondTarget) &&
187*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->size() >= 1 &&
188*9880d681SAndroid Build Coastguard Worker IsUnconditionalJump(JumpAroundTarget->back().getOpcode()) &&
189*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->pred_size() == 1 &&
190*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->succ_size() == 1;
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker if (case1 || case2) {
193*9880d681SAndroid Build Coastguard Worker InvertAndChangeJumpTarget(MI, UncondTarget);
194*9880d681SAndroid Build Coastguard Worker MBB->replaceSuccessor(JumpAroundTarget, UncondTarget);
195*9880d681SAndroid Build Coastguard Worker
196*9880d681SAndroid Build Coastguard Worker // Remove the unconditional branch in LayoutSucc.
197*9880d681SAndroid Build Coastguard Worker LayoutSucc->erase(LayoutSucc->begin());
198*9880d681SAndroid Build Coastguard Worker LayoutSucc->replaceSuccessor(UncondTarget, JumpAroundTarget);
199*9880d681SAndroid Build Coastguard Worker
200*9880d681SAndroid Build Coastguard Worker // This code performs the conversion for case 2, which moves
201*9880d681SAndroid Build Coastguard Worker // the block to the fall-thru case (BB3 in the code above).
202*9880d681SAndroid Build Coastguard Worker if (case2 && !case1) {
203*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->moveAfter(LayoutSucc);
204*9880d681SAndroid Build Coastguard Worker // only move a block if it doesn't have a fall-thru. otherwise
205*9880d681SAndroid Build Coastguard Worker // the CFG will be incorrect.
206*9880d681SAndroid Build Coastguard Worker if (!UncondTarget->canFallThrough()) {
207*9880d681SAndroid Build Coastguard Worker UncondTarget->moveAfter(JumpAroundTarget);
208*9880d681SAndroid Build Coastguard Worker }
209*9880d681SAndroid Build Coastguard Worker }
210*9880d681SAndroid Build Coastguard Worker
211*9880d681SAndroid Build Coastguard Worker //
212*9880d681SAndroid Build Coastguard Worker // Correct live-in information. Is used by post-RA scheduler
213*9880d681SAndroid Build Coastguard Worker // The live-in to LayoutSucc is now all values live-in to
214*9880d681SAndroid Build Coastguard Worker // JumpAroundTarget.
215*9880d681SAndroid Build Coastguard Worker //
216*9880d681SAndroid Build Coastguard Worker std::vector<MachineBasicBlock::RegisterMaskPair> OrigLiveIn(
217*9880d681SAndroid Build Coastguard Worker LayoutSucc->livein_begin(), LayoutSucc->livein_end());
218*9880d681SAndroid Build Coastguard Worker std::vector<MachineBasicBlock::RegisterMaskPair> NewLiveIn(
219*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->livein_begin(),
220*9880d681SAndroid Build Coastguard Worker JumpAroundTarget->livein_end());
221*9880d681SAndroid Build Coastguard Worker for (const auto &OrigLI : OrigLiveIn)
222*9880d681SAndroid Build Coastguard Worker LayoutSucc->removeLiveIn(OrigLI.PhysReg);
223*9880d681SAndroid Build Coastguard Worker for (const auto &NewLI : NewLiveIn)
224*9880d681SAndroid Build Coastguard Worker LayoutSucc->addLiveIn(NewLI);
225*9880d681SAndroid Build Coastguard Worker }
226*9880d681SAndroid Build Coastguard Worker }
227*9880d681SAndroid Build Coastguard Worker }
228*9880d681SAndroid Build Coastguard Worker }
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker }
231*9880d681SAndroid Build Coastguard Worker return true;
232*9880d681SAndroid Build Coastguard Worker }
233*9880d681SAndroid Build Coastguard Worker }
234*9880d681SAndroid Build Coastguard Worker
235*9880d681SAndroid Build Coastguard Worker
236*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
237*9880d681SAndroid Build Coastguard Worker // Public Constructor Functions
238*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
239*9880d681SAndroid Build Coastguard Worker
240*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(HexagonCFGOptimizer, "hexagon-cfg", "Hexagon CFG Optimizer",
241*9880d681SAndroid Build Coastguard Worker false, false)
242*9880d681SAndroid Build Coastguard Worker
createHexagonCFGOptimizer()243*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createHexagonCFGOptimizer() {
244*9880d681SAndroid Build Coastguard Worker return new HexagonCFGOptimizer();
245*9880d681SAndroid Build Coastguard Worker }
246