Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(123)

Side by Side Diff: src/IceCfg.cpp

Issue 610813002: Subzero: Rewrite the pass timing infrastructure. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Bug fixes and performance improvements Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the Cfg class, including constant pool 10 // This file implements the Cfg class, including constant pool
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 ImplicitArgs.push_back(Arg); 62 ImplicitArgs.push_back(Arg);
63 } 63 }
64 64
65 // Returns whether the stack frame layout has been computed yet. This 65 // Returns whether the stack frame layout has been computed yet. This
66 // is used for dumping the stack frame location of Variables. 66 // is used for dumping the stack frame location of Variables.
67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } 67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
68 68
69 void Cfg::translate() { 69 void Cfg::translate() {
70 if (hasError()) 70 if (hasError())
71 return; 71 return;
72 TimerMarker T("translate", getContext());
72 73
73 dump("Initial CFG"); 74 dump("Initial CFG");
74 75
75 Timer T_translate;
76 // The set of translation passes and their order are determined by 76 // The set of translation passes and their order are determined by
77 // the target. 77 // the target.
78 getTarget()->translate(); 78 getTarget()->translate();
79 T_translate.printElapsedUs(getContext(), "translate()");
80 79
81 dump("Final output"); 80 dump("Final output");
82 } 81 }
83 82
84 void Cfg::computePredecessors() { 83 void Cfg::computePredecessors() {
85 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 84 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
86 (*I)->computePredecessors(); 85 (*I)->computePredecessors();
87 } 86 }
88 } 87 }
89 88
90 void Cfg::renumberInstructions() { 89 void Cfg::renumberInstructions() {
90 TimerMarker T("renumberInstructions", getContext());
91 NextInstNumber = 1; 91 NextInstNumber = 1;
92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
93 (*I)->renumberInstructions(); 93 (*I)->renumberInstructions();
94 } 94 }
95 } 95 }
96 96
97 // placePhiLoads() must be called before placePhiStores(). 97 // placePhiLoads() must be called before placePhiStores().
98 void Cfg::placePhiLoads() { 98 void Cfg::placePhiLoads() {
99 TimerMarker T("placePhiLoads", getContext());
99 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 100 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
100 (*I)->placePhiLoads(); 101 (*I)->placePhiLoads();
101 } 102 }
102 } 103 }
103 104
104 // placePhiStores() must be called after placePhiLoads(). 105 // placePhiStores() must be called after placePhiLoads().
105 void Cfg::placePhiStores() { 106 void Cfg::placePhiStores() {
107 TimerMarker T("placePhiStores", getContext());
106 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 108 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
107 (*I)->placePhiStores(); 109 (*I)->placePhiStores();
108 } 110 }
109 } 111 }
110 112
111 void Cfg::deletePhis() { 113 void Cfg::deletePhis() {
114 TimerMarker T("deletePhis", getContext());
112 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 115 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
113 (*I)->deletePhis(); 116 (*I)->deletePhis();
114 } 117 }
115 } 118 }
116 119
117 void Cfg::doArgLowering() { 120 void Cfg::doArgLowering() {
121 TimerMarker T("doArgLowering", getContext());
118 getTarget()->lowerArguments(); 122 getTarget()->lowerArguments();
119 } 123 }
120 124
121 void Cfg::doAddressOpt() { 125 void Cfg::doAddressOpt() {
126 TimerMarker T("doAddressOpt", getContext());
122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 127 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
123 (*I)->doAddressOpt(); 128 (*I)->doAddressOpt();
124 } 129 }
125 } 130 }
126 131
127 void Cfg::doNopInsertion() { 132 void Cfg::doNopInsertion() {
133 TimerMarker T("doNopInsertion", getContext());
128 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 134 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
129 (*I)->doNopInsertion(); 135 (*I)->doNopInsertion();
130 } 136 }
131 } 137 }
132 138
133 void Cfg::genCode() { 139 void Cfg::genCode() {
140 TimerMarker T("genCode", getContext());
134 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 141 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
135 (*I)->genCode(); 142 (*I)->genCode();
136 } 143 }
137 } 144 }
138 145
139 // Compute the stack frame layout. 146 // Compute the stack frame layout.
140 void Cfg::genFrame() { 147 void Cfg::genFrame() {
148 TimerMarker T("genFrame", getContext());
141 getTarget()->addProlog(Entry); 149 getTarget()->addProlog(Entry);
142 // TODO: Consider folding epilog generation into the final 150 // TODO: Consider folding epilog generation into the final
143 // emission/assembly pass to avoid an extra iteration over the node 151 // emission/assembly pass to avoid an extra iteration over the node
144 // list. Or keep a separate list of exit nodes. 152 // list. Or keep a separate list of exit nodes.
145 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 153 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
146 CfgNode *Node = *I; 154 CfgNode *Node = *I;
147 if (Node->getHasReturn()) 155 if (Node->getHasReturn())
148 getTarget()->addEpilog(Node); 156 getTarget()->addEpilog(Node);
149 } 157 }
150 } 158 }
151 159
152 // This is a lightweight version of live-range-end calculation. Marks 160 // This is a lightweight version of live-range-end calculation. Marks
153 // the last use of only those variables whose definition and uses are 161 // the last use of only those variables whose definition and uses are
154 // completely with a single block. It is a quick single pass and 162 // completely with a single block. It is a quick single pass and
155 // doesn't need to iterate until convergence. 163 // doesn't need to iterate until convergence.
156 void Cfg::livenessLightweight() { 164 void Cfg::livenessLightweight() {
165 TimerMarker T("livenessLightweight", getContext());
157 getVMetadata()->init(); 166 getVMetadata()->init();
158 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 167 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
159 (*I)->livenessLightweight(); 168 (*I)->livenessLightweight();
160 } 169 }
161 } 170 }
162 171
163 void Cfg::liveness(LivenessMode Mode) { 172 void Cfg::liveness(LivenessMode Mode) {
173 TimerMarker T("liveness", getContext());
164 Live.reset(new Liveness(this, Mode)); 174 Live.reset(new Liveness(this, Mode));
165 getVMetadata()->init(); 175 getVMetadata()->init();
166 Live->init(); 176 Live->init();
167 // Initialize with all nodes needing to be processed. 177 // Initialize with all nodes needing to be processed.
168 llvm::BitVector NeedToProcess(Nodes.size(), true); 178 llvm::BitVector NeedToProcess(Nodes.size(), true);
169 while (NeedToProcess.any()) { 179 while (NeedToProcess.any()) {
170 // Iterate in reverse topological order to speed up convergence. 180 // Iterate in reverse topological order to speed up convergence.
171 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend(); 181 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend();
172 I != E; ++I) { 182 I != E; ++I) {
173 CfgNode *Node = *I; 183 CfgNode *Node = *I;
(...skipping 18 matching lines...) Expand all
192 // Reset each variable's live range. 202 // Reset each variable's live range.
193 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); 203 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
194 I != E; ++I) { 204 I != E; ++I) {
195 if (Variable *Var = *I) 205 if (Variable *Var = *I)
196 Var->resetLiveRange(); 206 Var->resetLiveRange();
197 } 207 }
198 } 208 }
199 // Collect timing for just the portion that constructs the live 209 // Collect timing for just the portion that constructs the live
200 // range intervals based on the end-of-live-range computation, for a 210 // range intervals based on the end-of-live-range computation, for a
201 // finer breakdown of the cost. 211 // finer breakdown of the cost.
202 Timer T_liveRange;
203 // Make a final pass over instructions to delete dead instructions 212 // Make a final pass over instructions to delete dead instructions
204 // and build each Variable's live range. 213 // and build each Variable's live range.
205 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 214 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
206 (*I)->livenessPostprocess(Mode, getLiveness()); 215 (*I)->livenessPostprocess(Mode, getLiveness());
207 } 216 }
208 if (Mode == Liveness_Intervals) { 217 if (Mode == Liveness_Intervals) {
209 // Special treatment for live in-args. Their liveness needs to 218 // Special treatment for live in-args. Their liveness needs to
210 // extend beyond the beginning of the function, otherwise an arg 219 // extend beyond the beginning of the function, otherwise an arg
211 // whose only use is in the first instruction will end up having 220 // whose only use is in the first instruction will end up having
212 // the trivial live range [1,1) and will *not* interfere with 221 // the trivial live range [1,1) and will *not* interfere with
(...skipping 21 matching lines...) Expand all
234 // Remove Variable::LiveRange and redirect to 243 // Remove Variable::LiveRange and redirect to
235 // Liveness::LiveRanges. TODO: make sure Variable weights 244 // Liveness::LiveRanges. TODO: make sure Variable weights
236 // are applied properly. 245 // are applied properly.
237 SizeT NumVars = Variables.size(); 246 SizeT NumVars = Variables.size();
238 for (SizeT i = 0; i < NumVars; ++i) { 247 for (SizeT i = 0; i < NumVars; ++i) {
239 Variable *Var = Variables[i]; 248 Variable *Var = Variables[i];
240 Var->setLiveRange(Live->getLiveRange(Var)); 249 Var->setLiveRange(Live->getLiveRange(Var));
241 if (Var->getWeight().isInf()) 250 if (Var->getWeight().isInf())
242 Var->setLiveRangeInfiniteWeight(); 251 Var->setLiveRangeInfiniteWeight();
243 } 252 }
244 T_liveRange.printElapsedUs(getContext(), "live range construction");
245 dump(); 253 dump();
246 } 254 }
247 } 255 }
248 256
249 // Traverse every Variable of every Inst and verify that it 257 // Traverse every Variable of every Inst and verify that it
250 // appears within the Variable's computed live range. 258 // appears within the Variable's computed live range.
251 bool Cfg::validateLiveness() const { 259 bool Cfg::validateLiveness() const {
260 TimerMarker T("validateLiveness", getContext());
252 bool Valid = true; 261 bool Valid = true;
253 Ostream &Str = Ctx->getStrDump(); 262 Ostream &Str = Ctx->getStrDump();
254 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1; 263 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1;
255 ++I1) { 264 ++I1) {
256 CfgNode *Node = *I1; 265 CfgNode *Node = *I1;
257 InstList &Insts = Node->getInsts(); 266 InstList &Insts = Node->getInsts();
258 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end(); 267 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end();
259 I2 != E2; ++I2) { 268 I2 != E2; ++I2) {
260 Inst *Inst = *I2; 269 Inst *Inst = *I2;
261 if (Inst->isDeleted()) 270 if (Inst->isDeleted())
(...skipping 27 matching lines...) Expand all
289 Str << " live range " << Var->getLiveRange() << "\n"; 298 Str << " live range " << Var->getLiveRange() << "\n";
290 } 299 }
291 } 300 }
292 } 301 }
293 } 302 }
294 } 303 }
295 return Valid; 304 return Valid;
296 } 305 }
297 306
298 void Cfg::doBranchOpt() { 307 void Cfg::doBranchOpt() {
308 TimerMarker T("doBranchOpt", getContext());
299 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 309 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
300 NodeList::iterator NextNode = I; 310 NodeList::iterator NextNode = I;
301 ++NextNode; 311 ++NextNode;
302 (*I)->doBranchOpt(*NextNode); 312 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
Jim Stichnoth 2014/09/28 14:26:39 This was a bug pointed out by valgrind.
303 } 313 }
304 } 314 }
305 315
306 // ======================== Dump routines ======================== // 316 // ======================== Dump routines ======================== //
307 317
308 void Cfg::emit() { 318 void Cfg::emit() {
319 TimerMarker T("emit", getContext());
309 Ostream &Str = Ctx->getStrEmit(); 320 Ostream &Str = Ctx->getStrEmit();
310 Timer T_emit;
311 if (!Ctx->testAndSetHasEmittedFirstMethod()) { 321 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
312 // Print a helpful command for assembling the output. 322 // Print a helpful command for assembling the output.
313 // TODO: have the Target emit the header 323 // TODO: have the Target emit the header
314 // TODO: need a per-file emit in addition to per-CFG 324 // TODO: need a per-file emit in addition to per-CFG
315 Str << "# $LLVM_BIN_PATH/llvm-mc" 325 Str << "# $LLVM_BIN_PATH/llvm-mc"
316 << " -arch=x86" 326 << " -arch=x86"
317 << " -x86-asm-syntax=intel" 327 << " -x86-asm-syntax=intel"
318 << " -filetype=obj" 328 << " -filetype=obj"
319 << " -o=MyObj.o" 329 << " -o=MyObj.o"
320 << "\n\n"; 330 << "\n\n";
(...skipping 11 matching lines...) Expand all
332 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end(); 342 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end();
333 I != E; ++I) { 343 I != E; ++I) {
334 Str.write_hex(*I); 344 Str.write_hex(*I);
335 } 345 }
336 Str << "\n"; 346 Str << "\n";
337 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 347 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
338 ++I) { 348 ++I) {
339 (*I)->emit(this); 349 (*I)->emit(this);
340 } 350 }
341 Str << "\n"; 351 Str << "\n";
342 T_emit.printElapsedUs(Ctx, "emit()");
343 } 352 }
344 353
345 // Dumps the IR with an optional introductory message. 354 // Dumps the IR with an optional introductory message.
346 void Cfg::dump(const IceString &Message) { 355 void Cfg::dump(const IceString &Message) {
347 if (!Ctx->isVerbose()) 356 if (!Ctx->isVerbose())
348 return; 357 return;
349 Ostream &Str = Ctx->getStrDump(); 358 Ostream &Str = Ctx->getStrDump();
350 if (!Message.empty()) 359 if (!Message.empty())
351 Str << "================ " << Message << " ================\n"; 360 Str << "================ " << Message << " ================\n";
352 setCurrentNode(getEntryNode()); 361 setCurrentNode(getEntryNode());
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 393 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
385 ++I) { 394 ++I) {
386 (*I)->dump(this); 395 (*I)->dump(this);
387 } 396 }
388 if (getContext()->isVerbose(IceV_Instructions)) { 397 if (getContext()->isVerbose(IceV_Instructions)) {
389 Str << "}\n"; 398 Str << "}\n";
390 } 399 }
391 } 400 }
392 401
393 } // end of namespace Ice 402 } // end of namespace Ice
OLDNEW
« no previous file with comments | « Makefile.standalone ('k') | src/IceConverter.cpp » ('j') | src/IceGlobalContext.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698