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

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: Make the optimized overlaps() implementation actually correct 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 static TimerIdT IDtranslate = GlobalContext::getTimerID("translate");
73 TimerMarker T(IDtranslate, getContext());
72 74
73 dump("Initial CFG"); 75 dump("Initial CFG");
74 76
75 Timer T_translate;
76 // The set of translation passes and their order are determined by 77 // The set of translation passes and their order are determined by
77 // the target. 78 // the target.
78 getTarget()->translate(); 79 getTarget()->translate();
79 T_translate.printElapsedUs(getContext(), "translate()");
80 80
81 dump("Final output"); 81 dump("Final output");
82 } 82 }
83 83
84 void Cfg::computePredecessors() { 84 void Cfg::computePredecessors() {
85 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 85 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
86 (*I)->computePredecessors(); 86 (*I)->computePredecessors();
87 } 87 }
88 } 88 }
89 89
90 void Cfg::renumberInstructions() { 90 void Cfg::renumberInstructions() {
91 static TimerIdT IDrenumberInstructions =
92 GlobalContext::getTimerID("renumberInstructions");
93 TimerMarker T(IDrenumberInstructions, getContext());
91 NextInstNumber = 1; 94 NextInstNumber = 1;
92 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 95 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
93 (*I)->renumberInstructions(); 96 (*I)->renumberInstructions();
94 } 97 }
95 } 98 }
96 99
97 // placePhiLoads() must be called before placePhiStores(). 100 // placePhiLoads() must be called before placePhiStores().
98 void Cfg::placePhiLoads() { 101 void Cfg::placePhiLoads() {
102 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads");
103 TimerMarker T(IDplacePhiLoads, getContext());
99 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 104 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
100 (*I)->placePhiLoads(); 105 (*I)->placePhiLoads();
101 } 106 }
102 } 107 }
103 108
104 // placePhiStores() must be called after placePhiLoads(). 109 // placePhiStores() must be called after placePhiLoads().
105 void Cfg::placePhiStores() { 110 void Cfg::placePhiStores() {
111 static TimerIdT IDplacePhiStores =
112 GlobalContext::getTimerID("placePhiStores");
113 TimerMarker T(IDplacePhiStores, getContext());
106 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 114 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
107 (*I)->placePhiStores(); 115 (*I)->placePhiStores();
108 } 116 }
109 } 117 }
110 118
111 void Cfg::deletePhis() { 119 void Cfg::deletePhis() {
120 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis");
121 TimerMarker T(IDdeletePhis, getContext());
112 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
113 (*I)->deletePhis(); 123 (*I)->deletePhis();
114 } 124 }
115 } 125 }
116 126
117 void Cfg::doArgLowering() { 127 void Cfg::doArgLowering() {
128 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering");
129 TimerMarker T(IDdoArgLowering, getContext());
118 getTarget()->lowerArguments(); 130 getTarget()->lowerArguments();
119 } 131 }
120 132
121 void Cfg::doAddressOpt() { 133 void Cfg::doAddressOpt() {
134 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt");
135 TimerMarker T(IDdoAddressOpt, getContext());
122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 136 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
123 (*I)->doAddressOpt(); 137 (*I)->doAddressOpt();
124 } 138 }
125 } 139 }
126 140
127 void Cfg::doNopInsertion() { 141 void Cfg::doNopInsertion() {
142 static TimerIdT IDdoNopInsertion =
143 GlobalContext::getTimerID("doNopInsertion");
144 TimerMarker T(IDdoNopInsertion, getContext());
128 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 145 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
129 (*I)->doNopInsertion(); 146 (*I)->doNopInsertion();
130 } 147 }
131 } 148 }
132 149
133 void Cfg::genCode() { 150 void Cfg::genCode() {
151 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode");
152 TimerMarker T(IDgenCode, getContext());
134 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) {
135 (*I)->genCode(); 154 (*I)->genCode();
136 } 155 }
137 } 156 }
138 157
139 // Compute the stack frame layout. 158 // Compute the stack frame layout.
140 void Cfg::genFrame() { 159 void Cfg::genFrame() {
160 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame");
161 TimerMarker T(IDgenFrame, getContext());
141 getTarget()->addProlog(Entry); 162 getTarget()->addProlog(Entry);
142 // TODO: Consider folding epilog generation into the final 163 // TODO: Consider folding epilog generation into the final
143 // emission/assembly pass to avoid an extra iteration over the node 164 // emission/assembly pass to avoid an extra iteration over the node
144 // list. Or keep a separate list of exit nodes. 165 // list. Or keep a separate list of exit nodes.
145 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 166 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
146 CfgNode *Node = *I; 167 CfgNode *Node = *I;
147 if (Node->getHasReturn()) 168 if (Node->getHasReturn())
148 getTarget()->addEpilog(Node); 169 getTarget()->addEpilog(Node);
149 } 170 }
150 } 171 }
151 172
152 // This is a lightweight version of live-range-end calculation. Marks 173 // This is a lightweight version of live-range-end calculation. Marks
153 // the last use of only those variables whose definition and uses are 174 // 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 175 // completely with a single block. It is a quick single pass and
155 // doesn't need to iterate until convergence. 176 // doesn't need to iterate until convergence.
156 void Cfg::livenessLightweight() { 177 void Cfg::livenessLightweight() {
178 static TimerIdT IDlivenessLightweight =
179 GlobalContext::getTimerID("livenessLightweight");
180 TimerMarker T(IDlivenessLightweight, getContext());
157 getVMetadata()->init(); 181 getVMetadata()->init();
158 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 182 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
159 (*I)->livenessLightweight(); 183 (*I)->livenessLightweight();
160 } 184 }
161 } 185 }
162 186
163 void Cfg::liveness(LivenessMode Mode) { 187 void Cfg::liveness(LivenessMode Mode) {
188 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness");
189 TimerMarker T(IDliveness, getContext());
164 Live.reset(new Liveness(this, Mode)); 190 Live.reset(new Liveness(this, Mode));
165 getVMetadata()->init(); 191 getVMetadata()->init();
166 Live->init(); 192 Live->init();
167 // Initialize with all nodes needing to be processed. 193 // Initialize with all nodes needing to be processed.
168 llvm::BitVector NeedToProcess(Nodes.size(), true); 194 llvm::BitVector NeedToProcess(Nodes.size(), true);
169 while (NeedToProcess.any()) { 195 while (NeedToProcess.any()) {
170 // Iterate in reverse topological order to speed up convergence. 196 // Iterate in reverse topological order to speed up convergence.
171 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend(); 197 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend();
172 I != E; ++I) { 198 I != E; ++I) {
173 CfgNode *Node = *I; 199 CfgNode *Node = *I;
(...skipping 18 matching lines...) Expand all
192 // Reset each variable's live range. 218 // Reset each variable's live range.
193 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); 219 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
194 I != E; ++I) { 220 I != E; ++I) {
195 if (Variable *Var = *I) 221 if (Variable *Var = *I)
196 Var->resetLiveRange(); 222 Var->resetLiveRange();
197 } 223 }
198 } 224 }
199 // Collect timing for just the portion that constructs the live 225 // Collect timing for just the portion that constructs the live
200 // range intervals based on the end-of-live-range computation, for a 226 // range intervals based on the end-of-live-range computation, for a
201 // finer breakdown of the cost. 227 // finer breakdown of the cost.
202 Timer T_liveRange;
203 // Make a final pass over instructions to delete dead instructions 228 // Make a final pass over instructions to delete dead instructions
204 // and build each Variable's live range. 229 // and build each Variable's live range.
230 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange");
231 TimerMarker T1(IDliveRange, getContext());
205 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 232 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
206 (*I)->livenessPostprocess(Mode, getLiveness()); 233 (*I)->livenessPostprocess(Mode, getLiveness());
207 } 234 }
208 if (Mode == Liveness_Intervals) { 235 if (Mode == Liveness_Intervals) {
209 // Special treatment for live in-args. Their liveness needs to 236 // Special treatment for live in-args. Their liveness needs to
210 // extend beyond the beginning of the function, otherwise an arg 237 // extend beyond the beginning of the function, otherwise an arg
211 // whose only use is in the first instruction will end up having 238 // whose only use is in the first instruction will end up having
212 // the trivial live range [1,1) and will *not* interfere with 239 // the trivial live range [1,1) and will *not* interfere with
213 // other arguments. So if the first instruction of the method is 240 // other arguments. So if the first instruction of the method is
214 // "r=arg1+arg2", both args may be assigned the same register. 241 // "r=arg1+arg2", both args may be assigned the same register.
(...skipping 19 matching lines...) Expand all
234 // Remove Variable::LiveRange and redirect to 261 // Remove Variable::LiveRange and redirect to
235 // Liveness::LiveRanges. TODO: make sure Variable weights 262 // Liveness::LiveRanges. TODO: make sure Variable weights
236 // are applied properly. 263 // are applied properly.
237 SizeT NumVars = Variables.size(); 264 SizeT NumVars = Variables.size();
238 for (SizeT i = 0; i < NumVars; ++i) { 265 for (SizeT i = 0; i < NumVars; ++i) {
239 Variable *Var = Variables[i]; 266 Variable *Var = Variables[i];
240 Var->setLiveRange(Live->getLiveRange(Var)); 267 Var->setLiveRange(Live->getLiveRange(Var));
241 if (Var->getWeight().isInf()) 268 if (Var->getWeight().isInf())
242 Var->setLiveRangeInfiniteWeight(); 269 Var->setLiveRangeInfiniteWeight();
243 } 270 }
244 T_liveRange.printElapsedUs(getContext(), "live range construction");
245 dump(); 271 dump();
246 } 272 }
247 } 273 }
248 274
249 // Traverse every Variable of every Inst and verify that it 275 // Traverse every Variable of every Inst and verify that it
250 // appears within the Variable's computed live range. 276 // appears within the Variable's computed live range.
251 bool Cfg::validateLiveness() const { 277 bool Cfg::validateLiveness() const {
278 static TimerIdT IDvalidateLiveness =
279 GlobalContext::getTimerID("validateLiveness");
280 TimerMarker T(IDvalidateLiveness, getContext());
252 bool Valid = true; 281 bool Valid = true;
253 Ostream &Str = Ctx->getStrDump(); 282 Ostream &Str = Ctx->getStrDump();
254 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1; 283 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1;
255 ++I1) { 284 ++I1) {
256 CfgNode *Node = *I1; 285 CfgNode *Node = *I1;
257 InstList &Insts = Node->getInsts(); 286 InstList &Insts = Node->getInsts();
258 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end(); 287 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end();
259 I2 != E2; ++I2) { 288 I2 != E2; ++I2) {
260 Inst *Inst = *I2; 289 Inst *Inst = *I2;
261 if (Inst->isDeleted()) 290 if (Inst->isDeleted())
(...skipping 27 matching lines...) Expand all
289 Str << " live range " << Var->getLiveRange() << "\n"; 318 Str << " live range " << Var->getLiveRange() << "\n";
290 } 319 }
291 } 320 }
292 } 321 }
293 } 322 }
294 } 323 }
295 return Valid; 324 return Valid;
296 } 325 }
297 326
298 void Cfg::doBranchOpt() { 327 void Cfg::doBranchOpt() {
328 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt");
329 TimerMarker T(IDdoBranchOpt, getContext());
299 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 330 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
300 NodeList::iterator NextNode = I; 331 NodeList::iterator NextNode = I;
301 ++NextNode; 332 ++NextNode;
302 (*I)->doBranchOpt(*NextNode); 333 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
303 } 334 }
304 } 335 }
305 336
306 // ======================== Dump routines ======================== // 337 // ======================== Dump routines ======================== //
307 338
308 void Cfg::emit() { 339 void Cfg::emit() {
340 static TimerIdT IDemit = GlobalContext::getTimerID("emit");
341 TimerMarker T(IDemit, getContext());
309 Ostream &Str = Ctx->getStrEmit(); 342 Ostream &Str = Ctx->getStrEmit();
310 Timer T_emit;
311 if (!Ctx->testAndSetHasEmittedFirstMethod()) { 343 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
312 // Print a helpful command for assembling the output. 344 // Print a helpful command for assembling the output.
313 // TODO: have the Target emit the header 345 // TODO: have the Target emit the header
314 // TODO: need a per-file emit in addition to per-CFG 346 // TODO: need a per-file emit in addition to per-CFG
315 Str << "# $LLVM_BIN_PATH/llvm-mc" 347 Str << "# $LLVM_BIN_PATH/llvm-mc"
316 << " -arch=x86" 348 << " -arch=x86"
317 << " -x86-asm-syntax=intel" 349 << " -x86-asm-syntax=intel"
318 << " -filetype=obj" 350 << " -filetype=obj"
319 << " -o=MyObj.o" 351 << " -o=MyObj.o"
320 << "\n\n"; 352 << "\n\n";
(...skipping 11 matching lines...) Expand all
332 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end(); 364 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end();
333 I != E; ++I) { 365 I != E; ++I) {
334 Str.write_hex(*I); 366 Str.write_hex(*I);
335 } 367 }
336 Str << "\n"; 368 Str << "\n";
337 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 369 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
338 ++I) { 370 ++I) {
339 (*I)->emit(this); 371 (*I)->emit(this);
340 } 372 }
341 Str << "\n"; 373 Str << "\n";
342 T_emit.printElapsedUs(Ctx, "emit()");
343 } 374 }
344 375
345 // Dumps the IR with an optional introductory message. 376 // Dumps the IR with an optional introductory message.
346 void Cfg::dump(const IceString &Message) { 377 void Cfg::dump(const IceString &Message) {
347 if (!Ctx->isVerbose()) 378 if (!Ctx->isVerbose())
348 return; 379 return;
349 Ostream &Str = Ctx->getStrDump(); 380 Ostream &Str = Ctx->getStrDump();
350 if (!Message.empty()) 381 if (!Message.empty())
351 Str << "================ " << Message << " ================\n"; 382 Str << "================ " << Message << " ================\n";
352 setCurrentNode(getEntryNode()); 383 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; 415 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
385 ++I) { 416 ++I) {
386 (*I)->dump(this); 417 (*I)->dump(this);
387 } 418 }
388 if (getContext()->isVerbose(IceV_Instructions)) { 419 if (getContext()->isVerbose(IceV_Instructions)) {
389 Str << "}\n"; 420 Str << "}\n";
390 } 421 }
391 } 422 }
392 423
393 } // end of namespace Ice 424 } // end of namespace Ice
OLDNEW
« no previous file with comments | « Makefile.standalone ('k') | src/IceConverter.cpp » ('j') | src/IceOperand.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698