blob: 42b24a65b450d4b854df1ae47e2f823258c97e94 [file] [log] [blame]
Evan Chengbbf1db72009-05-07 05:42:24 +00001//===-- CodePlacementOpt.cpp - Code Placement pass. -----------------------===//
Evan Chengfb8075d2008-02-28 00:43:03 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Evan Chengbbf1db72009-05-07 05:42:24 +000010// This file implements the pass that optimize code placement and align loop
11// headers to target specific alignment boundary.
Evan Chengfb8075d2008-02-28 00:43:03 +000012//
13//===----------------------------------------------------------------------===//
14
Evan Chengbbf1db72009-05-07 05:42:24 +000015#define DEBUG_TYPE "code-placement"
Evan Chengfb8075d2008-02-28 00:43:03 +000016#include "llvm/CodeGen/MachineLoopInfo.h"
17#include "llvm/CodeGen/MachineFunctionPass.h"
18#include "llvm/CodeGen/Passes.h"
Evan Cheng45e00102009-05-08 06:34:09 +000019#include "llvm/Target/TargetInstrInfo.h"
Evan Chengfb8075d2008-02-28 00:43:03 +000020#include "llvm/Target/TargetLowering.h"
21#include "llvm/Target/TargetMachine.h"
Evan Chengfb8075d2008-02-28 00:43:03 +000022#include "llvm/Support/Compiler.h"
23#include "llvm/Support/Debug.h"
Evan Cheng45e00102009-05-08 06:34:09 +000024#include "llvm/ADT/Statistic.h"
Evan Chengfb8075d2008-02-28 00:43:03 +000025using namespace llvm;
26
Dan Gohmancd2ae142009-10-15 00:36:22 +000027STATISTIC(NumLoopsAligned, "Number of loops aligned");
Evan Cheng45e00102009-05-08 06:34:09 +000028STATISTIC(NumIntraElim, "Number of intra loop branches eliminated");
29STATISTIC(NumIntraMoved, "Number of intra loop branches moved");
30
Evan Chengfb8075d2008-02-28 00:43:03 +000031namespace {
Evan Chengbbf1db72009-05-07 05:42:24 +000032 class CodePlacementOpt : public MachineFunctionPass {
Evan Cheng7132e122009-05-07 05:49:39 +000033 const MachineLoopInfo *MLI;
Evan Cheng45e00102009-05-08 06:34:09 +000034 const TargetInstrInfo *TII;
35 const TargetLowering *TLI;
36
37 /// ChangedMBBs - BBs which are modified by OptimizeIntraLoopEdges.
38 SmallPtrSet<MachineBasicBlock*, 8> ChangedMBBs;
39
40 /// UncondJmpMBBs - A list of BBs which are in loops and end with
41 /// unconditional branches.
42 SmallVector<std::pair<MachineBasicBlock*,MachineBasicBlock*>, 4>
43 UncondJmpMBBs;
44
Evan Chengfb8075d2008-02-28 00:43:03 +000045 public:
46 static char ID;
Evan Chengbbf1db72009-05-07 05:42:24 +000047 CodePlacementOpt() : MachineFunctionPass(&ID) {}
Evan Chengfb8075d2008-02-28 00:43:03 +000048
49 virtual bool runOnMachineFunction(MachineFunction &MF);
Evan Chengbbf1db72009-05-07 05:42:24 +000050 virtual const char *getPassName() const {
51 return "Code Placement Optimizater";
52 }
Evan Chengfb8075d2008-02-28 00:43:03 +000053
54 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
55 AU.addRequired<MachineLoopInfo>();
Evan Cheng8b56a902008-09-22 22:21:38 +000056 AU.addPreservedID(MachineDominatorsID);
Evan Chengfb8075d2008-02-28 00:43:03 +000057 MachineFunctionPass::getAnalysisUsage(AU);
58 }
Evan Cheng7132e122009-05-07 05:49:39 +000059
60 private:
Evan Cheng45e00102009-05-08 06:34:09 +000061 bool OptimizeIntraLoopEdges();
Evan Cheng7132e122009-05-07 05:49:39 +000062 bool AlignLoops(MachineFunction &MF);
Dan Gohmancd2ae142009-10-15 00:36:22 +000063 bool AlignLoop(MachineFunction &MF, MachineLoop *L, unsigned Align);
Evan Chengfb8075d2008-02-28 00:43:03 +000064 };
65
Evan Chengbbf1db72009-05-07 05:42:24 +000066 char CodePlacementOpt::ID = 0;
Evan Chengfb8075d2008-02-28 00:43:03 +000067} // end anonymous namespace
68
Evan Chengbbf1db72009-05-07 05:42:24 +000069FunctionPass *llvm::createCodePlacementOptPass() {
70 return new CodePlacementOpt();
71}
Evan Chengfb8075d2008-02-28 00:43:03 +000072
Evan Cheng45e00102009-05-08 06:34:09 +000073/// OptimizeBackEdges - Place loop back edges to move unconditional branches
74/// out of the loop.
75///
76/// A:
77/// ...
78/// <fallthrough to B>
79///
80/// B: --> loop header
81/// ...
82/// jcc <cond> C, [exit]
83///
84/// C:
85/// ...
86/// jmp B
87///
88/// ==>
89///
90/// A:
91/// ...
92/// jmp B
93///
Dan Gohmanbd31b172009-10-07 00:33:10 +000094/// C:
Evan Cheng45e00102009-05-08 06:34:09 +000095/// ...
96/// <fallthough to B>
97///
Dan Gohmanbd31b172009-10-07 00:33:10 +000098/// B: --> loop header
Evan Cheng45e00102009-05-08 06:34:09 +000099/// ...
100/// jcc <cond> C, [exit]
101///
102bool CodePlacementOpt::OptimizeIntraLoopEdges() {
Evan Cheng6ebf7bc2009-05-13 21:42:09 +0000103 if (!TLI->shouldOptimizeCodePlacement())
104 return false;
105
Evan Cheng45e00102009-05-08 06:34:09 +0000106 bool Changed = false;
107 for (unsigned i = 0, e = UncondJmpMBBs.size(); i != e; ++i) {
108 MachineBasicBlock *MBB = UncondJmpMBBs[i].first;
109 MachineBasicBlock *SuccMBB = UncondJmpMBBs[i].second;
110 MachineLoop *L = MLI->getLoopFor(MBB);
111 assert(L && "BB is expected to be in a loop!");
112
113 if (ChangedMBBs.count(MBB)) {
114 // BB has been modified, re-analyze.
115 MachineBasicBlock *TBB = 0, *FBB = 0;
116 SmallVector<MachineOperand, 4> Cond;
117 if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
118 continue;
119 if (MLI->getLoopFor(TBB) != L || TBB->isLandingPad())
120 continue;
121 SuccMBB = TBB;
122 } else {
123 assert(MLI->getLoopFor(SuccMBB) == L &&
124 "Successor is not in the same loop!");
125 }
126
127 if (MBB->isLayoutSuccessor(SuccMBB)) {
128 // Successor is right after MBB, just eliminate the unconditional jmp.
129 // Can this happen?
130 TII->RemoveBranch(*MBB);
131 ChangedMBBs.insert(MBB);
132 ++NumIntraElim;
Bob Wilson8ad05c42009-05-18 21:02:18 +0000133 Changed = true;
Evan Cheng45e00102009-05-08 06:34:09 +0000134 continue;
135 }
136
137 // Now check if the predecessor is fallthrough from any BB. If there is,
138 // that BB should be from outside the loop since edge will become a jmp.
139 bool OkToMove = true;
140 MachineBasicBlock *FtMBB = 0, *FtTBB = 0, *FtFBB = 0;
141 SmallVector<MachineOperand, 4> FtCond;
142 for (MachineBasicBlock::pred_iterator PI = SuccMBB->pred_begin(),
143 PE = SuccMBB->pred_end(); PI != PE; ++PI) {
144 MachineBasicBlock *PredMBB = *PI;
145 if (PredMBB->isLayoutSuccessor(SuccMBB)) {
146 if (TII->AnalyzeBranch(*PredMBB, FtTBB, FtFBB, FtCond)) {
147 OkToMove = false;
148 break;
149 }
150 if (!FtTBB)
151 FtTBB = SuccMBB;
152 else if (!FtFBB) {
153 assert(FtFBB != SuccMBB && "Unexpected control flow!");
154 FtFBB = SuccMBB;
155 }
156
157 // A fallthrough.
158 FtMBB = PredMBB;
159 MachineLoop *PL = MLI->getLoopFor(PredMBB);
Bob Wilson74b0ccc2009-05-12 03:48:10 +0000160 if (PL && (PL == L || PL->getLoopDepth() >= L->getLoopDepth()))
Evan Cheng45e00102009-05-08 06:34:09 +0000161 OkToMove = false;
Bob Wilson74b0ccc2009-05-12 03:48:10 +0000162
163 break;
Evan Cheng45e00102009-05-08 06:34:09 +0000164 }
165 }
166
167 if (!OkToMove)
168 continue;
169
170 // Is it profitable? If SuccMBB can fallthrough itself, that can be changed
171 // into a jmp.
172 MachineBasicBlock *TBB = 0, *FBB = 0;
173 SmallVector<MachineOperand, 4> Cond;
174 if (TII->AnalyzeBranch(*SuccMBB, TBB, FBB, Cond))
175 continue;
176 if (!TBB && Cond.empty())
177 TBB = next(MachineFunction::iterator(SuccMBB));
178 else if (!FBB && !Cond.empty())
179 FBB = next(MachineFunction::iterator(SuccMBB));
180
181 // This calculate the cost of the transformation. Also, it finds the *only*
182 // intra-loop edge if there is one.
183 int Cost = 0;
184 bool HasOneIntraSucc = true;
185 MachineBasicBlock *IntraSucc = 0;
186 for (MachineBasicBlock::succ_iterator SI = SuccMBB->succ_begin(),
187 SE = SuccMBB->succ_end(); SI != SE; ++SI) {
188 MachineBasicBlock *SSMBB = *SI;
189 if (MLI->getLoopFor(SSMBB) == L) {
190 if (!IntraSucc)
191 IntraSucc = SSMBB;
192 else
193 HasOneIntraSucc = false;
194 }
195
196 if (SuccMBB->isLayoutSuccessor(SSMBB))
197 // This will become a jmp.
198 ++Cost;
Nick Lewycky0ab2dce2009-05-08 06:57:41 +0000199 else if (MBB->isLayoutSuccessor(SSMBB)) {
Evan Cheng45e00102009-05-08 06:34:09 +0000200 // One of the successor will become the new fallthrough.
201 if (SSMBB == FBB) {
202 FBB = 0;
203 --Cost;
204 } else if (!FBB && SSMBB == TBB && Cond.empty()) {
205 TBB = 0;
206 --Cost;
Evan Cheng4b7f7a62009-05-08 09:35:53 +0000207 } else if (!Cond.empty() && !TII->ReverseBranchCondition(Cond)) {
208 assert(SSMBB == TBB);
Evan Cheng45e00102009-05-08 06:34:09 +0000209 TBB = FBB;
210 FBB = 0;
211 --Cost;
212 }
Nick Lewycky0ab2dce2009-05-08 06:57:41 +0000213 }
Evan Cheng45e00102009-05-08 06:34:09 +0000214 }
215 if (Cost)
216 continue;
217
218 // Now, let's move the successor to below the BB to eliminate the jmp.
219 SuccMBB->moveAfter(MBB);
220 TII->RemoveBranch(*MBB);
221 TII->RemoveBranch(*SuccMBB);
222 if (TBB)
223 TII->InsertBranch(*SuccMBB, TBB, FBB, Cond);
224 ChangedMBBs.insert(MBB);
225 ChangedMBBs.insert(SuccMBB);
226 if (FtMBB) {
227 TII->RemoveBranch(*FtMBB);
228 TII->InsertBranch(*FtMBB, FtTBB, FtFBB, FtCond);
229 ChangedMBBs.insert(FtMBB);
230 }
Bob Wilson8ad05c42009-05-18 21:02:18 +0000231 Changed = true;
Evan Cheng45e00102009-05-08 06:34:09 +0000232 }
233
234 ++NumIntraMoved;
235 return Changed;
236}
237
Evan Cheng7132e122009-05-07 05:49:39 +0000238/// AlignLoops - Align loop headers to target preferred alignments.
239///
240bool CodePlacementOpt::AlignLoops(MachineFunction &MF) {
Evan Cheng45e00102009-05-08 06:34:09 +0000241 const Function *F = MF.getFunction();
242 if (F->hasFnAttr(Attribute::OptimizeForSize))
Evan Cheng4f658e92008-02-29 17:52:15 +0000243 return false;
244
245 unsigned Align = TLI->getPrefLoopAlignment();
Evan Chengfb8075d2008-02-28 00:43:03 +0000246 if (!Align)
247 return false; // Don't care about loop alignment.
248
Evan Cheng7132e122009-05-07 05:49:39 +0000249 bool Changed = false;
Dan Gohmancd2ae142009-10-15 00:36:22 +0000250
251 for (MachineLoopInfo::iterator I = MLI->begin(), E = MLI->end();
252 I != E; ++I)
253 Changed |= AlignLoop(MF, *I, Align);
254
255 return Changed;
256}
257
258bool CodePlacementOpt::AlignLoop(MachineFunction &MF, MachineLoop *L,
259 unsigned Align) {
260 bool Changed = false;
261
262 // Do alignment for nested loops.
263 for (MachineLoop::iterator I = L->begin(), E = L->end(); I != E; ++I)
264 Changed |= AlignLoop(MF, *I, Align);
265
266 MachineBasicBlock *TopMBB = L->getHeader();
267 if (TopMBB == MF.begin()) return Changed;
268
269 MachineBasicBlock *PredMBB = prior(MachineFunction::iterator(TopMBB));
270 while (MLI->getLoopFor(PredMBB) == L) {
271 TopMBB = PredMBB;
272 if (TopMBB == MF.begin()) return Changed;
273 PredMBB = prior(MachineFunction::iterator(TopMBB));
Evan Chengfb8075d2008-02-28 00:43:03 +0000274 }
275
Dan Gohmancd2ae142009-10-15 00:36:22 +0000276 TopMBB->setAlignment(Align);
277 Changed = true;
278 ++NumLoopsAligned;
279
Evan Cheng7132e122009-05-07 05:49:39 +0000280 return Changed;
281}
282
283bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) {
284 MLI = &getAnalysis<MachineLoopInfo>();
285 if (MLI->empty())
286 return false; // No loops.
287
Evan Cheng45e00102009-05-08 06:34:09 +0000288 TLI = MF.getTarget().getTargetLowering();
289 TII = MF.getTarget().getInstrInfo();
290
Dan Gohmancd2ae142009-10-15 00:36:22 +0000291 // Analyze the BBs first and keep track of BBs that
Evan Cheng45e00102009-05-08 06:34:09 +0000292 // end with an unconditional jmp to another block in the same loop.
293 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
294 MachineBasicBlock *MBB = I;
295 if (MBB->isLandingPad())
296 continue;
297 MachineLoop *L = MLI->getLoopFor(MBB);
298 if (!L)
299 continue;
Evan Cheng45e00102009-05-08 06:34:09 +0000300
301 MachineBasicBlock *TBB = 0, *FBB = 0;
302 SmallVector<MachineOperand, 4> Cond;
303 if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
304 continue;
305 if (MLI->getLoopFor(TBB) == L && !TBB->isLandingPad())
306 UncondJmpMBBs.push_back(std::make_pair(MBB, TBB));
307 }
308
309 bool Changed = OptimizeIntraLoopEdges();
310
Evan Cheng7132e122009-05-07 05:49:39 +0000311 Changed |= AlignLoops(MF);
312
Evan Cheng45e00102009-05-08 06:34:09 +0000313 ChangedMBBs.clear();
314 UncondJmpMBBs.clear();
Evan Cheng45e00102009-05-08 06:34:09 +0000315
Evan Cheng7132e122009-05-07 05:49:39 +0000316 return Changed;
Evan Chengfb8075d2008-02-28 00:43:03 +0000317}