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