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

Side by Side Diff: src/IceCfg.cpp

Issue 619893002: Subzero: Auto-awesome iterators. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Use AsmCodeByte instead of uint8_t 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
« no previous file with comments | « no previous file | src/IceCfgNode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 dump("Initial CFG"); 75 dump("Initial CFG");
76 76
77 // The set of translation passes and their order are determined by 77 // The set of translation passes and their order are determined by
78 // the target. 78 // the target.
79 getTarget()->translate(); 79 getTarget()->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 (CfgNode *Node : Nodes)
86 (*I)->computePredecessors(); 86 Node->computePredecessors();
87 }
88 } 87 }
89 88
90 void Cfg::renumberInstructions() { 89 void Cfg::renumberInstructions() {
91 static TimerIdT IDrenumberInstructions = 90 static TimerIdT IDrenumberInstructions =
92 GlobalContext::getTimerID("renumberInstructions"); 91 GlobalContext::getTimerID("renumberInstructions");
93 TimerMarker T(IDrenumberInstructions, getContext()); 92 TimerMarker T(IDrenumberInstructions, getContext());
94 NextInstNumber = 1; 93 NextInstNumber = 1;
95 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 94 for (CfgNode *Node : Nodes)
96 (*I)->renumberInstructions(); 95 Node->renumberInstructions();
97 }
98 } 96 }
99 97
100 // placePhiLoads() must be called before placePhiStores(). 98 // placePhiLoads() must be called before placePhiStores().
101 void Cfg::placePhiLoads() { 99 void Cfg::placePhiLoads() {
102 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads"); 100 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads");
103 TimerMarker T(IDplacePhiLoads, getContext()); 101 TimerMarker T(IDplacePhiLoads, getContext());
104 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 102 for (CfgNode *Node : Nodes)
105 (*I)->placePhiLoads(); 103 Node->placePhiLoads();
106 }
107 } 104 }
108 105
109 // placePhiStores() must be called after placePhiLoads(). 106 // placePhiStores() must be called after placePhiLoads().
110 void Cfg::placePhiStores() { 107 void Cfg::placePhiStores() {
111 static TimerIdT IDplacePhiStores = 108 static TimerIdT IDplacePhiStores =
112 GlobalContext::getTimerID("placePhiStores"); 109 GlobalContext::getTimerID("placePhiStores");
113 TimerMarker T(IDplacePhiStores, getContext()); 110 TimerMarker T(IDplacePhiStores, getContext());
114 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 111 for (CfgNode *Node : Nodes)
115 (*I)->placePhiStores(); 112 Node->placePhiStores();
116 }
117 } 113 }
118 114
119 void Cfg::deletePhis() { 115 void Cfg::deletePhis() {
120 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis"); 116 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis");
121 TimerMarker T(IDdeletePhis, getContext()); 117 TimerMarker T(IDdeletePhis, getContext());
122 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 118 for (CfgNode *Node : Nodes)
123 (*I)->deletePhis(); 119 Node->deletePhis();
124 }
125 } 120 }
126 121
127 void Cfg::doArgLowering() { 122 void Cfg::doArgLowering() {
128 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering"); 123 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering");
129 TimerMarker T(IDdoArgLowering, getContext()); 124 TimerMarker T(IDdoArgLowering, getContext());
130 getTarget()->lowerArguments(); 125 getTarget()->lowerArguments();
131 } 126 }
132 127
133 void Cfg::doAddressOpt() { 128 void Cfg::doAddressOpt() {
134 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt"); 129 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt");
135 TimerMarker T(IDdoAddressOpt, getContext()); 130 TimerMarker T(IDdoAddressOpt, getContext());
136 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 131 for (CfgNode *Node : Nodes)
137 (*I)->doAddressOpt(); 132 Node->doAddressOpt();
138 }
139 } 133 }
140 134
141 void Cfg::doNopInsertion() { 135 void Cfg::doNopInsertion() {
142 static TimerIdT IDdoNopInsertion = 136 static TimerIdT IDdoNopInsertion =
143 GlobalContext::getTimerID("doNopInsertion"); 137 GlobalContext::getTimerID("doNopInsertion");
144 TimerMarker T(IDdoNopInsertion, getContext()); 138 TimerMarker T(IDdoNopInsertion, getContext());
145 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 139 for (CfgNode *Node : Nodes)
146 (*I)->doNopInsertion(); 140 Node->doNopInsertion();
147 }
148 } 141 }
149 142
150 void Cfg::genCode() { 143 void Cfg::genCode() {
151 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode"); 144 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode");
152 TimerMarker T(IDgenCode, getContext()); 145 TimerMarker T(IDgenCode, getContext());
153 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 146 for (CfgNode *Node : Nodes)
154 (*I)->genCode(); 147 Node->genCode();
155 }
156 } 148 }
157 149
158 // Compute the stack frame layout. 150 // Compute the stack frame layout.
159 void Cfg::genFrame() { 151 void Cfg::genFrame() {
160 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame"); 152 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame");
161 TimerMarker T(IDgenFrame, getContext()); 153 TimerMarker T(IDgenFrame, getContext());
162 getTarget()->addProlog(Entry); 154 getTarget()->addProlog(Entry);
163 // TODO: Consider folding epilog generation into the final 155 // TODO: Consider folding epilog generation into the final
164 // emission/assembly pass to avoid an extra iteration over the node 156 // emission/assembly pass to avoid an extra iteration over the node
165 // list. Or keep a separate list of exit nodes. 157 // list. Or keep a separate list of exit nodes.
166 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 158 for (CfgNode *Node : Nodes)
167 CfgNode *Node = *I;
168 if (Node->getHasReturn()) 159 if (Node->getHasReturn())
169 getTarget()->addEpilog(Node); 160 getTarget()->addEpilog(Node);
170 }
171 } 161 }
172 162
173 // This is a lightweight version of live-range-end calculation. Marks 163 // This is a lightweight version of live-range-end calculation. Marks
174 // the last use of only those variables whose definition and uses are 164 // the last use of only those variables whose definition and uses are
175 // completely with a single block. It is a quick single pass and 165 // completely with a single block. It is a quick single pass and
176 // doesn't need to iterate until convergence. 166 // doesn't need to iterate until convergence.
177 void Cfg::livenessLightweight() { 167 void Cfg::livenessLightweight() {
178 static TimerIdT IDlivenessLightweight = 168 static TimerIdT IDlivenessLightweight =
179 GlobalContext::getTimerID("livenessLightweight"); 169 GlobalContext::getTimerID("livenessLightweight");
180 TimerMarker T(IDlivenessLightweight, getContext()); 170 TimerMarker T(IDlivenessLightweight, getContext());
181 getVMetadata()->init(); 171 getVMetadata()->init();
182 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 172 for (CfgNode *Node : Nodes)
183 (*I)->livenessLightweight(); 173 Node->livenessLightweight();
184 }
185 } 174 }
186 175
187 void Cfg::liveness(LivenessMode Mode) { 176 void Cfg::liveness(LivenessMode Mode) {
188 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness"); 177 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness");
189 TimerMarker T(IDliveness, getContext()); 178 TimerMarker T(IDliveness, getContext());
190 Live.reset(new Liveness(this, Mode)); 179 Live.reset(new Liveness(this, Mode));
191 getVMetadata()->init(); 180 getVMetadata()->init();
192 Live->init(); 181 Live->init();
193 // Initialize with all nodes needing to be processed. 182 // Initialize with all nodes needing to be processed.
194 llvm::BitVector NeedToProcess(Nodes.size(), true); 183 llvm::BitVector NeedToProcess(Nodes.size(), true);
195 while (NeedToProcess.any()) { 184 while (NeedToProcess.any()) {
196 // Iterate in reverse topological order to speed up convergence. 185 // Iterate in reverse topological order to speed up convergence.
197 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend(); 186 // TODO(stichnot): Use llvm::make_range with LLVM 3.5.
198 I != E; ++I) { 187 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) {
199 CfgNode *Node = *I; 188 CfgNode *Node = *I;
200 if (NeedToProcess[Node->getIndex()]) { 189 if (NeedToProcess[Node->getIndex()]) {
201 NeedToProcess[Node->getIndex()] = false; 190 NeedToProcess[Node->getIndex()] = false;
202 bool Changed = Node->liveness(getLiveness()); 191 bool Changed = Node->liveness(getLiveness());
203 if (Changed) { 192 if (Changed) {
204 // If the beginning-of-block liveness changed since the last 193 // If the beginning-of-block liveness changed since the last
205 // iteration, mark all in-edges as needing to be processed. 194 // iteration, mark all in-edges as needing to be processed.
206 const NodeList &InEdges = Node->getInEdges(); 195 for (CfgNode *Pred : Node->getInEdges())
207 for (NodeList::const_iterator I1 = InEdges.begin(),
208 E1 = InEdges.end();
209 I1 != E1; ++I1) {
210 CfgNode *Pred = *I1;
211 NeedToProcess[Pred->getIndex()] = true; 196 NeedToProcess[Pred->getIndex()] = true;
212 }
213 } 197 }
214 } 198 }
215 } 199 }
216 } 200 }
217 if (Mode == Liveness_Intervals) { 201 if (Mode == Liveness_Intervals) {
218 // Reset each variable's live range. 202 // Reset each variable's live range.
219 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); 203 for (Variable *Var : Variables)
220 I != E; ++I) { 204 Var->resetLiveRange();
221 if (Variable *Var = *I)
222 Var->resetLiveRange();
223 }
224 } 205 }
225 // Collect timing for just the portion that constructs the live 206 // Collect timing for just the portion that constructs the live
226 // range intervals based on the end-of-live-range computation, for a 207 // range intervals based on the end-of-live-range computation, for a
227 // finer breakdown of the cost. 208 // finer breakdown of the cost.
228 // Make a final pass over instructions to delete dead instructions 209 // Make a final pass over instructions to delete dead instructions
229 // and build each Variable's live range. 210 // and build each Variable's live range.
230 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange"); 211 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange");
231 TimerMarker T1(IDliveRange, getContext()); 212 TimerMarker T1(IDliveRange, getContext());
232 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 213 for (CfgNode *Node : Nodes)
233 (*I)->livenessPostprocess(Mode, getLiveness()); 214 Node->livenessPostprocess(Mode, getLiveness());
234 }
235 if (Mode == Liveness_Intervals) { 215 if (Mode == Liveness_Intervals) {
236 // Special treatment for live in-args. Their liveness needs to 216 // Special treatment for live in-args. Their liveness needs to
237 // extend beyond the beginning of the function, otherwise an arg 217 // extend beyond the beginning of the function, otherwise an arg
238 // whose only use is in the first instruction will end up having 218 // whose only use is in the first instruction will end up having
239 // the trivial live range [1,1) and will *not* interfere with 219 // the trivial live range [1,1) and will *not* interfere with
240 // other arguments. So if the first instruction of the method is 220 // other arguments. So if the first instruction of the method is
241 // "r=arg1+arg2", both args may be assigned the same register. 221 // "r=arg1+arg2", both args may be assigned the same register.
242 for (SizeT I = 0; I < Args.size(); ++I) { 222 for (SizeT I = 0; I < Args.size(); ++I) {
243 Variable *Arg = Args[I]; 223 Variable *Arg = Args[I];
244 if (!Live->getLiveRange(Arg).isEmpty()) { 224 if (!Live->getLiveRange(Arg).isEmpty()) {
(...skipping 28 matching lines...) Expand all
273 } 253 }
274 254
275 // Traverse every Variable of every Inst and verify that it 255 // Traverse every Variable of every Inst and verify that it
276 // appears within the Variable's computed live range. 256 // appears within the Variable's computed live range.
277 bool Cfg::validateLiveness() const { 257 bool Cfg::validateLiveness() const {
278 static TimerIdT IDvalidateLiveness = 258 static TimerIdT IDvalidateLiveness =
279 GlobalContext::getTimerID("validateLiveness"); 259 GlobalContext::getTimerID("validateLiveness");
280 TimerMarker T(IDvalidateLiveness, getContext()); 260 TimerMarker T(IDvalidateLiveness, getContext());
281 bool Valid = true; 261 bool Valid = true;
282 Ostream &Str = Ctx->getStrDump(); 262 Ostream &Str = Ctx->getStrDump();
283 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1; 263 for (CfgNode *Node : Nodes) {
284 ++I1) { 264 for (Inst *Inst : Node->getInsts()) {
285 CfgNode *Node = *I1;
286 InstList &Insts = Node->getInsts();
287 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end();
288 I2 != E2; ++I2) {
289 Inst *Inst = *I2;
290 if (Inst->isDeleted()) 265 if (Inst->isDeleted())
291 continue; 266 continue;
292 if (llvm::isa<InstFakeKill>(Inst)) 267 if (llvm::isa<InstFakeKill>(Inst))
293 continue; 268 continue;
294 InstNumberT InstNumber = Inst->getNumber(); 269 InstNumberT InstNumber = Inst->getNumber();
295 Variable *Dest = Inst->getDest(); 270 Variable *Dest = Inst->getDest();
296 if (Dest) { 271 if (Dest) {
297 // TODO: This instruction should actually begin Dest's live 272 // TODO: This instruction should actually begin Dest's live
298 // range, so we could probably test that this instruction is 273 // range, so we could probably test that this instruction is
299 // the beginning of some segment of Dest's live range. But 274 // the beginning of some segment of Dest's live range. But
(...skipping 20 matching lines...) Expand all
320 } 295 }
321 } 296 }
322 } 297 }
323 } 298 }
324 return Valid; 299 return Valid;
325 } 300 }
326 301
327 void Cfg::doBranchOpt() { 302 void Cfg::doBranchOpt() {
328 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt"); 303 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt");
329 TimerMarker T(IDdoBranchOpt, getContext()); 304 TimerMarker T(IDdoBranchOpt, getContext());
330 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 305 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
331 NodeList::iterator NextNode = I; 306 auto NextNode = I;
332 ++NextNode; 307 ++NextNode;
333 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode); 308 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
334 } 309 }
335 } 310 }
336 311
337 // ======================== Dump routines ======================== // 312 // ======================== Dump routines ======================== //
338 313
339 void Cfg::emit() { 314 void Cfg::emit() {
340 static TimerIdT IDemit = GlobalContext::getTimerID("emit"); 315 static TimerIdT IDemit = GlobalContext::getTimerID("emit");
341 TimerMarker T(IDemit, getContext()); 316 TimerMarker T(IDemit, getContext());
(...skipping 11 matching lines...) Expand all
353 } 328 }
354 Str << "\t.text\n"; 329 Str << "\t.text\n";
355 IceString MangledName = getContext()->mangleName(getFunctionName()); 330 IceString MangledName = getContext()->mangleName(getFunctionName());
356 if (Ctx->getFlags().FunctionSections) 331 if (Ctx->getFlags().FunctionSections)
357 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n"; 332 Str << "\t.section\t.text." << MangledName << ",\"ax\",@progbits\n";
358 if (!getInternal()) { 333 if (!getInternal()) {
359 Str << "\t.globl\t" << MangledName << "\n"; 334 Str << "\t.globl\t" << MangledName << "\n";
360 Str << "\t.type\t" << MangledName << ",@function\n"; 335 Str << "\t.type\t" << MangledName << ",@function\n";
361 } 336 }
362 Str << "\t.p2align " << getTarget()->getBundleAlignLog2Bytes() << ",0x"; 337 Str << "\t.p2align " << getTarget()->getBundleAlignLog2Bytes() << ",0x";
363 llvm::ArrayRef<uint8_t> Pad = getTarget()->getNonExecBundlePadding(); 338 for (AsmCodeByte I : getTarget()->getNonExecBundlePadding())
364 for (llvm::ArrayRef<uint8_t>::iterator I = Pad.begin(), E = Pad.end(); 339 Str.write_hex(I);
365 I != E; ++I) {
366 Str.write_hex(*I);
367 }
368 Str << "\n"; 340 Str << "\n";
369 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 341 for (CfgNode *Node : Nodes)
370 ++I) { 342 Node->emit(this);
371 (*I)->emit(this);
372 }
373 Str << "\n"; 343 Str << "\n";
374 } 344 }
375 345
376 // Dumps the IR with an optional introductory message. 346 // Dumps the IR with an optional introductory message.
377 void Cfg::dump(const IceString &Message) { 347 void Cfg::dump(const IceString &Message) {
378 if (!Ctx->isVerbose()) 348 if (!Ctx->isVerbose())
379 return; 349 return;
380 Ostream &Str = Ctx->getStrDump(); 350 Ostream &Str = Ctx->getStrDump();
381 if (!Message.empty()) 351 if (!Message.empty())
382 Str << "================ " << Message << " ================\n"; 352 Str << "================ " << Message << " ================\n";
383 setCurrentNode(getEntryNode()); 353 setCurrentNode(getEntryNode());
384 // Print function name+args 354 // Print function name+args
385 if (getContext()->isVerbose(IceV_Instructions)) { 355 if (getContext()->isVerbose(IceV_Instructions)) {
386 Str << "define "; 356 Str << "define ";
387 if (getInternal()) 357 if (getInternal())
388 Str << "internal "; 358 Str << "internal ";
389 Str << ReturnType << " @" << getFunctionName() << "("; 359 Str << ReturnType << " @" << getFunctionName() << "(";
390 for (SizeT i = 0; i < Args.size(); ++i) { 360 for (SizeT i = 0; i < Args.size(); ++i) {
391 if (i > 0) 361 if (i > 0)
392 Str << ", "; 362 Str << ", ";
393 Str << Args[i]->getType() << " "; 363 Str << Args[i]->getType() << " ";
394 Args[i]->dump(this); 364 Args[i]->dump(this);
395 } 365 }
396 Str << ") {\n"; 366 Str << ") {\n";
397 } 367 }
398 resetCurrentNode(); 368 resetCurrentNode();
399 if (getContext()->isVerbose(IceV_Liveness)) { 369 if (getContext()->isVerbose(IceV_Liveness)) {
400 // Print summary info about variables 370 // Print summary info about variables
401 for (VarList::const_iterator I = Variables.begin(), E = Variables.end(); 371 for (Variable *Var : Variables) {
402 I != E; ++I) {
403 Variable *Var = *I;
404 Str << "// multiblock="; 372 Str << "// multiblock=";
405 if (getVMetadata()->isTracked(Var)) 373 if (getVMetadata()->isTracked(Var))
406 Str << getVMetadata()->isMultiBlock(Var); 374 Str << getVMetadata()->isMultiBlock(Var);
407 else 375 else
408 Str << "?"; 376 Str << "?";
409 Str << " weight=" << Var->getWeight() << " "; 377 Str << " weight=" << Var->getWeight() << " ";
410 Var->dump(this); 378 Var->dump(this);
411 Str << " LIVE=" << Var->getLiveRange() << "\n"; 379 Str << " LIVE=" << Var->getLiveRange() << "\n";
412 } 380 }
413 } 381 }
414 // Print each basic block 382 // Print each basic block
415 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 383 for (CfgNode *Node : Nodes)
416 ++I) { 384 Node->dump(this);
417 (*I)->dump(this); 385 if (getContext()->isVerbose(IceV_Instructions))
418 }
419 if (getContext()->isVerbose(IceV_Instructions)) {
420 Str << "}\n"; 386 Str << "}\n";
421 }
422 } 387 }
423 388
424 } // end of namespace Ice 389 } // end of namespace Ice
OLDNEW
« no previous file with comments | « no previous file | src/IceCfgNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698