blob: f6a8421c43480a69486bb4832ee62a555334aa1b [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 Cheng45e00102009-05-08 06:34:09 +000022#include "llvm/Support/CommandLine.h"
Evan Chengfb8075d2008-02-28 00:43:03 +000023#include "llvm/Support/Compiler.h"
24#include "llvm/Support/Debug.h"
Evan Cheng45e00102009-05-08 06:34:09 +000025#include "llvm/ADT/Statistic.h"
Evan Chengfb8075d2008-02-28 00:43:03 +000026using namespace llvm;
27
Evan Cheng45e00102009-05-08 06:34:09 +000028static cl::opt<bool>
29OptLoopBBPlacement("opt-loop-bb-placement",
30 cl::init(false), cl::Hidden,
31 cl::desc("Optimize block placements in loops"));
32
33STATISTIC(NumHeaderAligned, "Number of loop header aligned");
34STATISTIC(NumIntraElim, "Number of intra loop branches eliminated");
35STATISTIC(NumIntraMoved, "Number of intra loop branches moved");
36
Evan Chengfb8075d2008-02-28 00:43:03 +000037namespace {
Evan Chengbbf1db72009-05-07 05:42:24 +000038 class CodePlacementOpt : public MachineFunctionPass {
Evan Cheng7132e122009-05-07 05:49:39 +000039 const MachineLoopInfo *MLI;
Evan Cheng45e00102009-05-08 06:34:09 +000040 const TargetInstrInfo *TII;
41 const TargetLowering *TLI;
42
43 /// ChangedMBBs - BBs which are modified by OptimizeIntraLoopEdges.
44 SmallPtrSet<MachineBasicBlock*, 8> ChangedMBBs;
45
46 /// UncondJmpMBBs - A list of BBs which are in loops and end with
47 /// unconditional branches.
48 SmallVector<std::pair<MachineBasicBlock*,MachineBasicBlock*>, 4>
49 UncondJmpMBBs;
50
51 /// LoopHeaders - A list of BBs which are loop headers.
52 SmallVector<MachineBasicBlock*, 4> LoopHeaders;
Evan Cheng7132e122009-05-07 05:49:39 +000053
Evan Chengfb8075d2008-02-28 00:43:03 +000054 public:
55 static char ID;
Evan Chengbbf1db72009-05-07 05:42:24 +000056 CodePlacementOpt() : MachineFunctionPass(&ID) {}
Evan Chengfb8075d2008-02-28 00:43:03 +000057
58 virtual bool runOnMachineFunction(MachineFunction &MF);
Evan Chengbbf1db72009-05-07 05:42:24 +000059 virtual const char *getPassName() const {
60 return "Code Placement Optimizater";
61 }
Evan Chengfb8075d2008-02-28 00:43:03 +000062
63 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
64 AU.addRequired<MachineLoopInfo>();
Evan Cheng8b56a902008-09-22 22:21:38 +000065 AU.addPreservedID(MachineDominatorsID);
Evan Chengfb8075d2008-02-28 00:43:03 +000066 MachineFunctionPass::getAnalysisUsage(AU);
67 }
Evan Cheng7132e122009-05-07 05:49:39 +000068
69 private:
Evan Cheng45e00102009-05-08 06:34:09 +000070 bool OptimizeIntraLoopEdges();
Evan Cheng7132e122009-05-07 05:49:39 +000071 bool AlignLoops(MachineFunction &MF);
Evan Chengfb8075d2008-02-28 00:43:03 +000072 };
73
Evan Chengbbf1db72009-05-07 05:42:24 +000074 char CodePlacementOpt::ID = 0;
Evan Chengfb8075d2008-02-28 00:43:03 +000075} // end anonymous namespace
76
Evan Chengbbf1db72009-05-07 05:42:24 +000077FunctionPass *llvm::createCodePlacementOptPass() {
78 return new CodePlacementOpt();
79}
Evan Chengfb8075d2008-02-28 00:43:03 +000080
Evan Cheng45e00102009-05-08 06:34:09 +000081/// OptimizeBackEdges - Place loop back edges to move unconditional branches
82/// out of the loop.
83///
84/// A:
85/// ...
86/// <fallthrough to B>
87///
88/// B: --> loop header
89/// ...
90/// jcc <cond> C, [exit]
91///
92/// C:
93/// ...
94/// jmp B
95///
96/// ==>
97///
98/// A:
99/// ...
100/// jmp B
101///
102/// C: --> new loop header
103/// ...
104/// <fallthough to B>
105///
106/// B:
107/// ...
108/// jcc <cond> C, [exit]
109///
110bool CodePlacementOpt::OptimizeIntraLoopEdges() {
111 if (!OptLoopBBPlacement)
112 return false;
113
114 bool Changed = false;
115 for (unsigned i = 0, e = UncondJmpMBBs.size(); i != e; ++i) {
116 MachineBasicBlock *MBB = UncondJmpMBBs[i].first;
117 MachineBasicBlock *SuccMBB = UncondJmpMBBs[i].second;
118 MachineLoop *L = MLI->getLoopFor(MBB);
119 assert(L && "BB is expected to be in a loop!");
120
121 if (ChangedMBBs.count(MBB)) {
122 // BB has been modified, re-analyze.
123 MachineBasicBlock *TBB = 0, *FBB = 0;
124 SmallVector<MachineOperand, 4> Cond;
125 if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
126 continue;
127 if (MLI->getLoopFor(TBB) != L || TBB->isLandingPad())
128 continue;
129 SuccMBB = TBB;
130 } else {
131 assert(MLI->getLoopFor(SuccMBB) == L &&
132 "Successor is not in the same loop!");
133 }
134
135 if (MBB->isLayoutSuccessor(SuccMBB)) {
136 // Successor is right after MBB, just eliminate the unconditional jmp.
137 // Can this happen?
138 TII->RemoveBranch(*MBB);
139 ChangedMBBs.insert(MBB);
140 ++NumIntraElim;
141 continue;
142 }
143
144 // Now check if the predecessor is fallthrough from any BB. If there is,
145 // that BB should be from outside the loop since edge will become a jmp.
146 bool OkToMove = true;
147 MachineBasicBlock *FtMBB = 0, *FtTBB = 0, *FtFBB = 0;
148 SmallVector<MachineOperand, 4> FtCond;
149 for (MachineBasicBlock::pred_iterator PI = SuccMBB->pred_begin(),
150 PE = SuccMBB->pred_end(); PI != PE; ++PI) {
151 MachineBasicBlock *PredMBB = *PI;
152 if (PredMBB->isLayoutSuccessor(SuccMBB)) {
153 if (TII->AnalyzeBranch(*PredMBB, FtTBB, FtFBB, FtCond)) {
154 OkToMove = false;
155 break;
156 }
157 if (!FtTBB)
158 FtTBB = SuccMBB;
159 else if (!FtFBB) {
160 assert(FtFBB != SuccMBB && "Unexpected control flow!");
161 FtFBB = SuccMBB;
162 }
163
164 // A fallthrough.
165 FtMBB = PredMBB;
166 MachineLoop *PL = MLI->getLoopFor(PredMBB);
167 if (PL && (PL == L || PL->getLoopDepth() >= L->getLoopDepth())) {
168 OkToMove = false;
169 break;
170 }
171 }
172 }
173
174 if (!OkToMove)
175 continue;
176
177 // Is it profitable? If SuccMBB can fallthrough itself, that can be changed
178 // into a jmp.
179 MachineBasicBlock *TBB = 0, *FBB = 0;
180 SmallVector<MachineOperand, 4> Cond;
181 if (TII->AnalyzeBranch(*SuccMBB, TBB, FBB, Cond))
182 continue;
183 if (!TBB && Cond.empty())
184 TBB = next(MachineFunction::iterator(SuccMBB));
185 else if (!FBB && !Cond.empty())
186 FBB = next(MachineFunction::iterator(SuccMBB));
187
188 // This calculate the cost of the transformation. Also, it finds the *only*
189 // intra-loop edge if there is one.
190 int Cost = 0;
191 bool HasOneIntraSucc = true;
192 MachineBasicBlock *IntraSucc = 0;
193 for (MachineBasicBlock::succ_iterator SI = SuccMBB->succ_begin(),
194 SE = SuccMBB->succ_end(); SI != SE; ++SI) {
195 MachineBasicBlock *SSMBB = *SI;
196 if (MLI->getLoopFor(SSMBB) == L) {
197 if (!IntraSucc)
198 IntraSucc = SSMBB;
199 else
200 HasOneIntraSucc = false;
201 }
202
203 if (SuccMBB->isLayoutSuccessor(SSMBB))
204 // This will become a jmp.
205 ++Cost;
Nick Lewycky0ab2dce2009-05-08 06:57:41 +0000206 else if (MBB->isLayoutSuccessor(SSMBB)) {
Evan Cheng45e00102009-05-08 06:34:09 +0000207 // One of the successor will become the new fallthrough.
208 if (SSMBB == FBB) {
209 FBB = 0;
210 --Cost;
211 } else if (!FBB && SSMBB == TBB && Cond.empty()) {
212 TBB = 0;
213 --Cost;
214 } else if (!TII->ReverseBranchCondition(Cond)) {
215 TBB = FBB;
216 FBB = 0;
217 --Cost;
218 }
Nick Lewycky0ab2dce2009-05-08 06:57:41 +0000219 }
Evan Cheng45e00102009-05-08 06:34:09 +0000220 }
221 if (Cost)
222 continue;
223
224 // Now, let's move the successor to below the BB to eliminate the jmp.
225 SuccMBB->moveAfter(MBB);
226 TII->RemoveBranch(*MBB);
227 TII->RemoveBranch(*SuccMBB);
228 if (TBB)
229 TII->InsertBranch(*SuccMBB, TBB, FBB, Cond);
230 ChangedMBBs.insert(MBB);
231 ChangedMBBs.insert(SuccMBB);
232 if (FtMBB) {
233 TII->RemoveBranch(*FtMBB);
234 TII->InsertBranch(*FtMBB, FtTBB, FtFBB, FtCond);
235 ChangedMBBs.insert(FtMBB);
236 }
237
238 // If BB is the loop latch, we may have a new loop headr.
239 if (MBB == L->getLoopLatch()) {
240 assert(MLI->isLoopHeader(SuccMBB) &&
241 "Only succ of loop latch is not the header?");
242 if (HasOneIntraSucc && IntraSucc)
243 std::replace(LoopHeaders.begin(),LoopHeaders.end(), SuccMBB, IntraSucc);
244 }
245 }
246
247 ++NumIntraMoved;
248 return Changed;
249}
250
Evan Cheng7132e122009-05-07 05:49:39 +0000251/// AlignLoops - Align loop headers to target preferred alignments.
252///
253bool CodePlacementOpt::AlignLoops(MachineFunction &MF) {
Evan Cheng45e00102009-05-08 06:34:09 +0000254 const Function *F = MF.getFunction();
255 if (F->hasFnAttr(Attribute::OptimizeForSize))
Evan Cheng4f658e92008-02-29 17:52:15 +0000256 return false;
257
258 unsigned Align = TLI->getPrefLoopAlignment();
Evan Chengfb8075d2008-02-28 00:43:03 +0000259 if (!Align)
260 return false; // Don't care about loop alignment.
261
Evan Cheng45e00102009-05-08 06:34:09 +0000262 // Make sure blocks are numbered in order
263 MF.RenumberBlocks();
Devang Patel4ae641f2008-10-01 23:18:38 +0000264
Evan Cheng7132e122009-05-07 05:49:39 +0000265 bool Changed = false;
Evan Cheng45e00102009-05-08 06:34:09 +0000266 for (unsigned i = 0, e = LoopHeaders.size(); i != e; ++i) {
267 MachineBasicBlock *HeaderMBB = LoopHeaders[i];
268 MachineBasicBlock *PredMBB = prior(MachineFunction::iterator(HeaderMBB));
269 if (MLI->getLoopFor(HeaderMBB) != MLI->getLoopFor(PredMBB)) {
270 // If previously BB is in the same loop, don't align this BB. We want
271 // to prevent adding noop's inside a loop.
272 HeaderMBB->setAlignment(Align);
Evan Cheng7132e122009-05-07 05:49:39 +0000273 Changed = true;
Evan Cheng45e00102009-05-08 06:34:09 +0000274 ++NumHeaderAligned;
Evan Chengdf908412008-11-27 01:16:00 +0000275 }
Evan Chengfb8075d2008-02-28 00:43:03 +0000276 }
277
Evan Cheng7132e122009-05-07 05:49:39 +0000278 return Changed;
279}
280
281bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) {
282 MLI = &getAnalysis<MachineLoopInfo>();
283 if (MLI->empty())
284 return false; // No loops.
285
Evan Cheng45e00102009-05-08 06:34:09 +0000286 TLI = MF.getTarget().getTargetLowering();
287 TII = MF.getTarget().getInstrInfo();
288
289 // Analyze the BBs first and keep track of loop headers and BBs that
290 // end with an unconditional jmp to another block in the same loop.
291 for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
292 MachineBasicBlock *MBB = I;
293 if (MBB->isLandingPad())
294 continue;
295 MachineLoop *L = MLI->getLoopFor(MBB);
296 if (!L)
297 continue;
298 if (MLI->isLoopHeader(MBB))
299 LoopHeaders.push_back(MBB);
300
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();
315 LoopHeaders.clear();
316
Evan Cheng7132e122009-05-07 05:49:39 +0000317 return Changed;
Evan Chengfb8075d2008-02-28 00:43:03 +0000318}