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

Side by Side Diff: src/IceCfgNode.cpp

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years, 6 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/IceCfgNode.cpp - Basic block (node) implementation -----===// 1 //===- subzero/src/IceCfgNode.cpp - Basic block (node) 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 CfgNode class, including the complexities 10 // This file implements the CfgNode class, including the complexities
11 // of instruction insertion and in-edge calculation. 11 // of instruction insertion and in-edge calculation.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "IceCfg.h" 15 #include "IceCfg.h"
16 #include "IceCfgNode.h" 16 #include "IceCfgNode.h"
17 #include "IceInst.h" 17 #include "IceInst.h"
18 #include "IceLiveness.h"
18 #include "IceOperand.h" 19 #include "IceOperand.h"
19 #include "IceTargetLowering.h" 20 #include "IceTargetLowering.h"
20 21
21 namespace Ice { 22 namespace Ice {
22 23
23 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name) 24 CfgNode::CfgNode(Cfg *Func, SizeT LabelNumber, IceString Name)
24 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false) {} 25 : Func(Func), Number(LabelNumber), Name(Name), HasReturn(false) {}
25 26
26 // Returns the name the node was created with. If no name was given, 27 // Returns the name the node was created with. If no name was given,
27 // it synthesizes a (hopefully) unique name. 28 // it synthesizes a (hopefully) unique name.
(...skipping 14 matching lines...) Expand all
42 Func->setError("Phi instruction added to the middle of a block"); 43 Func->setError("Phi instruction added to the middle of a block");
43 return; 44 return;
44 } 45 }
45 Phis.push_back(Phi); 46 Phis.push_back(Phi);
46 } else { 47 } else {
47 Insts.push_back(Inst); 48 Insts.push_back(Inst);
48 } 49 }
49 Inst->updateVars(this); 50 Inst->updateVars(this);
50 } 51 }
51 52
53 // Renumbers the non-deleted instructions in the node. This needs to
54 // be done in preparation for live range analysis. The instruction
55 // numbers in a block must be monotonically increasing. The range of
56 // instruction numbers in a block, from lowest to highest, must not
57 // overlap with the range of any other block.
58 void CfgNode::renumberInstructions() {
59 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
60 (*I)->renumber(Func);
61 }
62 InstList::const_iterator I = Insts.begin(), E = Insts.end();
63 while (I != E) {
64 Inst *Inst = *I++;
65 Inst->renumber(Func);
66 }
67 }
68
52 // When a node is created, the OutEdges are immediately knows, but the 69 // When a node is created, the OutEdges are immediately knows, but the
53 // InEdges have to be built up incrementally. After the CFG has been 70 // InEdges have to be built up incrementally. After the CFG has been
54 // constructed, the computePredecessors() pass finalizes it by 71 // constructed, the computePredecessors() pass finalizes it by
55 // creating the InEdges list. 72 // creating the InEdges list.
56 void CfgNode::computePredecessors() { 73 void CfgNode::computePredecessors() {
57 OutEdges = (*Insts.rbegin())->getTerminatorEdges(); 74 OutEdges = (*Insts.rbegin())->getTerminatorEdges();
58 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); 75 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end();
59 I != E; ++I) { 76 I != E; ++I) {
60 CfgNode *Node = *I; 77 CfgNode *Node = *I;
61 Node->InEdges.push_back(this); 78 Node->InEdges.push_back(this);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 // Find the insertion point. TODO: After branch/compare fusing is 117 // Find the insertion point. TODO: After branch/compare fusing is
101 // implemented, try not to insert Phi stores between the compare and 118 // implemented, try not to insert Phi stores between the compare and
102 // conditional branch instructions, otherwise the branch/compare 119 // conditional branch instructions, otherwise the branch/compare
103 // pattern matching may fail. However, the branch/compare sequence 120 // pattern matching may fail. However, the branch/compare sequence
104 // will have to be broken if the compare result is read (by the 121 // will have to be broken if the compare result is read (by the
105 // assignment) before it is written (by the compare). 122 // assignment) before it is written (by the compare).
106 InstList::iterator InsertionPoint = Insts.end(); 123 InstList::iterator InsertionPoint = Insts.end();
107 // Every block must end in a terminator instruction. 124 // Every block must end in a terminator instruction.
108 assert(InsertionPoint != Insts.begin()); 125 assert(InsertionPoint != Insts.begin());
109 --InsertionPoint; 126 --InsertionPoint;
110 // Confirm via assert() that InsertionPoint is a terminator 127 // Confirm that InsertionPoint is a terminator instruction. Calling
111 // instruction. Calling getTerminatorEdges() on a non-terminator 128 // getTerminatorEdges() on a non-terminator instruction will cause
112 // instruction will cause an llvm_unreachable(). 129 // an llvm_unreachable().
113 assert(((*InsertionPoint)->getTerminatorEdges(), true)); 130 (void)(*InsertionPoint)->getTerminatorEdges();
131 // If the current insertion point is at a conditional branch
132 // instruction, and the previous instruction is a compare
133 // instruction, then we move the insertion point before the compare
134 // instruction so as not to interfere with compare/branch fusing.
135 if (InstBr *Branch = llvm::dyn_cast<InstBr>(*InsertionPoint)) {
136 if (!Branch->isUnconditional()) {
137 if (InsertionPoint != Insts.begin()) {
138 --InsertionPoint;
139 if (!llvm::isa<InstIcmp>(*InsertionPoint) &&
140 !llvm::isa<InstFcmp>(*InsertionPoint)) {
141 ++InsertionPoint;
142 }
143 }
144 }
145 }
114 146
115 // Consider every out-edge. 147 // Consider every out-edge.
116 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); 148 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end();
117 I1 != E1; ++I1) { 149 I1 != E1; ++I1) {
118 CfgNode *Target = *I1; 150 CfgNode *Target = *I1;
119 // Consider every Phi instruction at the out-edge. 151 // Consider every Phi instruction at the out-edge.
120 for (PhiList::const_iterator I2 = Target->Phis.begin(), 152 for (PhiList::const_iterator I2 = Target->Phis.begin(),
121 E2 = Target->Phis.end(); 153 E2 = Target->Phis.end();
122 I2 != E2; ++I2) { 154 I2 != E2; ++I2) {
123 Operand *Operand = (*I2)->getOperandForTarget(this); 155 Operand *Operand = (*I2)->getOperandForTarget(this);
(...skipping 14 matching lines...) Expand all
138 } 170 }
139 } 171 }
140 172
141 // Deletes the phi instructions after the loads and stores are placed. 173 // Deletes the phi instructions after the loads and stores are placed.
142 void CfgNode::deletePhis() { 174 void CfgNode::deletePhis() {
143 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { 175 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
144 (*I)->setDeleted(); 176 (*I)->setDeleted();
145 } 177 }
146 } 178 }
147 179
180 // Does address mode optimization. Pass each instruction to the
181 // TargetLowering object. If it returns a new instruction
182 // (representing the optimized address mode), then insert the new
183 // instruction and delete the old.
184 void CfgNode::doAddressOpt() {
185 TargetLowering *Target = Func->getTarget();
186 LoweringContext &Context = Target->getContext();
187 Context.init(this);
188 while (!Context.atEnd()) {
189 Target->doAddressOpt();
190 }
191 }
192
148 // Drives the target lowering. Passes the current instruction and the 193 // Drives the target lowering. Passes the current instruction and the
149 // next non-deleted instruction for target lowering. 194 // next non-deleted instruction for target lowering.
150 void CfgNode::genCode() { 195 void CfgNode::genCode() {
151 TargetLowering *Target = Func->getTarget(); 196 TargetLowering *Target = Func->getTarget();
152 LoweringContext &Context = Target->getContext(); 197 LoweringContext &Context = Target->getContext();
153 // Lower only the regular instructions. Defer the Phi instructions. 198 // Lower only the regular instructions. Defer the Phi instructions.
154 Context.init(this); 199 Context.init(this);
155 while (!Context.atEnd()) { 200 while (!Context.atEnd()) {
156 InstList::iterator Orig = Context.getCur(); 201 InstList::iterator Orig = Context.getCur();
157 if (llvm::isa<InstRet>(*Orig)) 202 if (llvm::isa<InstRet>(*Orig))
158 setHasReturn(); 203 setHasReturn();
159 Target->lower(); 204 Target->lower();
160 // Ensure target lowering actually moved the cursor. 205 // Ensure target lowering actually moved the cursor.
161 assert(Context.getCur() != Orig); 206 assert(Context.getCur() != Orig);
162 } 207 }
163 } 208 }
164 209
210 void CfgNode::livenessLightweight() {
211 SizeT NumVars = Func->getNumVariables();
212 llvm::BitVector Live(NumVars);
213 // Process regular instructions in reverse order.
214 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend();
215 I != E; ++I) {
216 (*I)->livenessLightweight(Live);
217 }
218 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
219 (*I)->livenessLightweight(Live);
220 }
221 }
222
223 // Performs liveness analysis on the block. Returns true if the
224 // incoming liveness changed from before, false if it stayed the same.
225 // (If it changes, the node's predecessors need to be processed
226 // again.)
227 bool CfgNode::liveness(Liveness *Liveness) {
228 SizeT NumVars = Liveness->getLocalSize(this);
229 llvm::BitVector Live(NumVars);
230 // Mark the beginning and ending of each variable's live range
231 // with the sentinel instruction number 0.
232 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this);
233 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this);
234 LiveBegin.assign(NumVars, 0);
235 LiveEnd.assign(NumVars, 0);
236 // Initialize Live to be the union of all successors' LiveIn.
237 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end();
238 I != E; ++I) {
239 CfgNode *Succ = *I;
240 Live |= Liveness->getLiveIn(Succ);
241 // Mark corresponding argument of phis in successor as live.
242 for (PhiList::const_iterator I1 = Succ->Phis.begin(), E1 = Succ->Phis.end();
243 I1 != E1; ++I1) {
244 (*I1)->livenessPhiOperand(Live, this, Liveness);
245 }
246 }
247 Liveness->getLiveOut(this) = Live;
248
249 // Process regular instructions in reverse order.
250 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend();
251 I != E; ++I) {
252 (*I)->liveness((*I)->getNumber(), Live, Liveness, this);
253 }
254 // Process phis in forward order so that we can override the
255 // instruction number to be that of the earliest phi instruction in
256 // the block.
257 int32_t FirstPhiNumber = 0; // sentinel value
258 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
259 if (FirstPhiNumber <= 0)
jvoung (off chromium) 2014/05/30 15:41:31 nit: could be a strict == test, since you're just
Jim Stichnoth 2014/05/30 23:06:18 As it turns out, the <= test also makes us ignore
260 FirstPhiNumber = (*I)->getNumber();
261 (*I)->liveness(FirstPhiNumber, Live, Liveness, this);
262 }
263
264 // When using the sparse representation, after traversing the
265 // instructions in the block, the Live bitvector should only contain
266 // set bits for global variables upon block entry. We validate this
267 // by shrinking the Live vector and then testing it against the
268 // pre-shrunk version. (The shrinking is required, but the
269 // validation is not.)
270 llvm::BitVector LiveOrig = Live;
271 Live.resize(Liveness->getGlobalSize());
272 // Non-global arguments in the entry node are allowed to be live on
273 // entry.
274 bool IsEntry = (Func->getEntryNode() == this);
275 if (!(IsEntry || Live == LiveOrig)) {
276 // This is a fatal liveness consistency error. Print some
277 // diagnostics and abort.
278 Ostream &Str = Func->getContext()->getStrDump();
279 Func->setCurrentNode(NULL);
280 Str << "LiveOrig-Live =";
281 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) {
282 if (LiveOrig.test(i)) {
283 Str << " ";
284 Liveness->getVariable(i, this)->dump(Func);
285 }
286 }
287 Str << "\n";
288 llvm_unreachable("Fatal inconsistency in liveness analysis");
289 }
290
291 bool Changed = false;
292 llvm::BitVector &LiveIn = Liveness->getLiveIn(this);
293 // Add in current LiveIn
294 Live |= LiveIn;
295 // Check result, set LiveIn=Live
296 Changed = (Live != LiveIn);
297 if (Changed)
298 LiveIn = Live;
299 return Changed;
300 }
301
302 // Now that basic liveness is complete, remove dead instructions that
303 // were tentatively marked as dead, and compute actual live ranges.
304 // It is assumed that within a single basic block, a live range begins
305 // at most once and ends at most once. This is certainly true for
306 // pure SSA form. It is also true once phis are lowered, since each
307 // assignment to the phi-based temporary is in a different basic
308 // block, and there is a single read that ends the live in the basic
309 // block that contained the actual phi instruction.
310 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
311 int32_t FirstInstNum = 0;
312 int32_t LastInstNum = 0;
313 // Process phis in any order. Process only Dest operands.
314 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
315 InstPhi *Inst = *I;
316 Inst->deleteIfDead();
317 if (Inst->isDeleted())
318 continue;
319 if (FirstInstNum <= 0)
320 FirstInstNum = Inst->getNumber();
321 assert(Inst->getNumber() > LastInstNum);
322 LastInstNum = Inst->getNumber();
323 }
324 // Process instructions
325 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E;
326 ++I) {
327 Inst *Inst = *I;
328 Inst->deleteIfDead();
329 if (Inst->isDeleted())
330 continue;
331 if (FirstInstNum <= 0)
332 FirstInstNum = Inst->getNumber();
333 assert(Inst->getNumber() > LastInstNum);
334 LastInstNum = Inst->getNumber();
335 // Create fake live ranges for a Kill instruction, but only if the
336 // linked instruction is still alive.
337 if (Mode == Liveness_Intervals) {
338 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(Inst)) {
339 if (!Kill->getLinked()->isDeleted()) {
340 SizeT NumSrcs = Inst->getSrcSize();
341 for (SizeT i = 0; i < NumSrcs; ++i) {
342 Variable *Var = llvm::cast<Variable>(Inst->getSrc(i));
343 int32_t InstNumber = Inst->getNumber();
344 Liveness->addLiveRange(Var, InstNumber, InstNumber, 1);
345 }
346 }
347 }
348 }
349 }
350 if (Mode != Liveness_Intervals)
351 return;
352
353 SizeT NumVars = Liveness->getLocalSize(this);
354 SizeT NumGlobals = Liveness->getGlobalSize();
355 llvm::BitVector &LiveIn = Liveness->getLiveIn(this);
356 llvm::BitVector &LiveOut = Liveness->getLiveOut(this);
357 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this);
358 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this);
359 for (SizeT i = 0; i < NumVars; ++i) {
360 // Deal with the case where the variable is both live-in and
361 // live-out, but LiveEnd comes before LiveBegin. In this case, we
362 // need to add two segments to the live range because there is a
363 // hole in the middle. This would typically happen as a result of
364 // phi lowering in the presence of loopback edges.
365 bool IsGlobal = (i < NumGlobals);
366 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) {
367 Variable *Var = Liveness->getVariable(i, this);
368 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1);
369 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1);
370 continue;
371 }
372 int32_t Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i];
373 int32_t End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i];
374 if (Begin <= 0 && End <= 0)
375 continue;
376 if (Begin <= FirstInstNum)
377 Begin = FirstInstNum;
378 if (End <= 0)
379 End = LastInstNum + 1;
380 Variable *Var = Liveness->getVariable(i, this);
381 Liveness->addLiveRange(Var, Begin, End, 1);
382 }
383 }
384
165 // ======================== Dump routines ======================== // 385 // ======================== Dump routines ======================== //
166 386
167 void CfgNode::emit(Cfg *Func) const { 387 void CfgNode::emit(Cfg *Func) const {
168 Func->setCurrentNode(this); 388 Func->setCurrentNode(this);
169 Ostream &Str = Func->getContext()->getStrEmit(); 389 Ostream &Str = Func->getContext()->getStrEmit();
170 if (Func->getEntryNode() == this) { 390 if (Func->getEntryNode() == this) {
171 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; 391 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n";
172 } 392 }
173 Str << getAsmName() << ":\n"; 393 Str << getAsmName() << ":\n";
174 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { 394 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
(...skipping 12 matching lines...) Expand all
187 // suppress them. 407 // suppress them.
188 if (Inst->isRedundantAssign()) 408 if (Inst->isRedundantAssign())
189 continue; 409 continue;
190 (*I)->emit(Func); 410 (*I)->emit(Func);
191 } 411 }
192 } 412 }
193 413
194 void CfgNode::dump(Cfg *Func) const { 414 void CfgNode::dump(Cfg *Func) const {
195 Func->setCurrentNode(this); 415 Func->setCurrentNode(this);
196 Ostream &Str = Func->getContext()->getStrDump(); 416 Ostream &Str = Func->getContext()->getStrDump();
417 Liveness *Liveness = Func->getLiveness();
197 if (Func->getContext()->isVerbose(IceV_Instructions)) { 418 if (Func->getContext()->isVerbose(IceV_Instructions)) {
198 Str << getName() << ":\n"; 419 Str << getName() << ":\n";
199 } 420 }
200 // Dump list of predecessor nodes. 421 // Dump list of predecessor nodes.
201 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { 422 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) {
202 Str << " // preds = "; 423 Str << " // preds = ";
203 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); 424 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end();
204 I != E; ++I) { 425 I != E; ++I) {
205 if (I != InEdges.begin()) 426 if (I != InEdges.begin())
206 Str << ", "; 427 Str << ", ";
207 Str << "%" << (*I)->getName(); 428 Str << "%" << (*I)->getName();
208 } 429 }
209 Str << "\n"; 430 Str << "\n";
210 } 431 }
432 // Dump the live-in variables.
433 llvm::BitVector LiveIn;
434 if (Liveness)
435 LiveIn = Liveness->getLiveIn(this);
436 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) {
437 Str << " // LiveIn:";
438 for (SizeT i = 0; i < LiveIn.size(); ++i) {
439 if (LiveIn[i]) {
440 Str << " %" << Liveness->getVariable(i, this)->getName();
441 }
442 }
443 Str << "\n";
444 }
211 // Dump each instruction. 445 // Dump each instruction.
212 if (Func->getContext()->isVerbose(IceV_Instructions)) { 446 if (Func->getContext()->isVerbose(IceV_Instructions)) {
213 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; 447 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E;
214 ++I) { 448 ++I) {
215 const Inst *Inst = *I; 449 const Inst *Inst = *I;
216 Inst->dumpDecorated(Func); 450 Inst->dumpDecorated(Func);
217 } 451 }
218 InstList::const_iterator I = Insts.begin(), E = Insts.end(); 452 InstList::const_iterator I = Insts.begin(), E = Insts.end();
219 while (I != E) { 453 while (I != E) {
220 Inst *Inst = *I++; 454 Inst *Inst = *I++;
221 Inst->dumpDecorated(Func); 455 Inst->dumpDecorated(Func);
222 } 456 }
223 } 457 }
458 // Dump the live-out variables.
459 llvm::BitVector LiveOut;
460 if (Liveness)
461 LiveOut = Liveness->getLiveOut(this);
462 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) {
463 Str << " // LiveOut:";
464 for (SizeT i = 0; i < LiveOut.size(); ++i) {
465 if (LiveOut[i]) {
466 Str << " %" << Liveness->getVariable(i, this)->getName();
467 }
468 }
469 Str << "\n";
470 }
224 // Dump list of successor nodes. 471 // Dump list of successor nodes.
225 if (Func->getContext()->isVerbose(IceV_Succs)) { 472 if (Func->getContext()->isVerbose(IceV_Succs)) {
226 Str << " // succs = "; 473 Str << " // succs = ";
227 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); 474 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end();
228 I != E; ++I) { 475 I != E; ++I) {
229 if (I != OutEdges.begin()) 476 if (I != OutEdges.begin())
230 Str << ", "; 477 Str << ", ";
231 Str << "%" << (*I)->getName(); 478 Str << "%" << (*I)->getName();
232 } 479 }
233 Str << "\n"; 480 Str << "\n";
234 } 481 }
235 } 482 }
236 483
237 } // end of namespace Ice 484 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698