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

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, 7 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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 via assert() that InsertionPoint is a terminator
111 // instruction. Calling getTerminatorEdges() on a non-terminator 128 // instruction. Calling getTerminatorEdges() on a non-terminator
112 // instruction will cause an llvm_unreachable(). 129 // instruction will cause an llvm_unreachable().
113 assert(((*InsertionPoint)->getTerminatorEdges(), true)); 130 assert(((*InsertionPoint)->getTerminatorEdges(), true));
131 if (llvm::isa<InstBr>(*InsertionPoint)) {
132 if (InsertionPoint != Insts.begin()) {
133 --InsertionPoint;
134 if (!llvm::isa<InstIcmp>(*InsertionPoint) &&
135 !llvm::isa<InstFcmp>(*InsertionPoint)) {
136 ++InsertionPoint;
137 }
138 }
139 }
JF 2014/05/25 22:50:50 Can you explain this?
Jim Stichnoth 2014/05/29 01:39:46 Done. Also modified the logic to look only for *c
114 140
115 // Consider every out-edge. 141 // Consider every out-edge.
116 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end(); 142 for (NodeList::const_iterator I1 = OutEdges.begin(), E1 = OutEdges.end();
117 I1 != E1; ++I1) { 143 I1 != E1; ++I1) {
118 CfgNode *Target = *I1; 144 CfgNode *Target = *I1;
119 // Consider every Phi instruction at the out-edge. 145 // Consider every Phi instruction at the out-edge.
120 for (PhiList::const_iterator I2 = Target->Phis.begin(), 146 for (PhiList::const_iterator I2 = Target->Phis.begin(),
121 E2 = Target->Phis.end(); 147 E2 = Target->Phis.end();
122 I2 != E2; ++I2) { 148 I2 != E2; ++I2) {
123 Operand *Operand = (*I2)->getOperandForTarget(this); 149 Operand *Operand = (*I2)->getOperandForTarget(this);
(...skipping 14 matching lines...) Expand all
138 } 164 }
139 } 165 }
140 166
141 // Deletes the phi instructions after the loads and stores are placed. 167 // Deletes the phi instructions after the loads and stores are placed.
142 void CfgNode::deletePhis() { 168 void CfgNode::deletePhis() {
143 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { 169 for (PhiList::iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
144 (*I)->setDeleted(); 170 (*I)->setDeleted();
145 } 171 }
146 } 172 }
147 173
174 // Does address mode optimization. Pass each instruction to the
175 // TargetLowering object. If it returns a new instruction
176 // (representing the optimized address mode), then insert the new
177 // instruction and delete the old.
178 void CfgNode::doAddressOpt() {
179 TargetLowering *Target = Func->getTarget();
180 LoweringContext &Context = Target->getContext();
181 Context.init(this);
182 while (!Context.atEnd()) {
183 Target->doAddressOpt();
184 }
185 }
186
148 // Drives the target lowering. Passes the current instruction and the 187 // Drives the target lowering. Passes the current instruction and the
149 // next non-deleted instruction for target lowering. 188 // next non-deleted instruction for target lowering.
150 void CfgNode::genCode() { 189 void CfgNode::genCode() {
151 TargetLowering *Target = Func->getTarget(); 190 TargetLowering *Target = Func->getTarget();
152 LoweringContext &Context = Target->getContext(); 191 LoweringContext &Context = Target->getContext();
153 // Lower only the regular instructions. Defer the Phi instructions. 192 // Lower only the regular instructions. Defer the Phi instructions.
154 Context.init(this); 193 Context.init(this);
155 while (!Context.atEnd()) { 194 while (!Context.atEnd()) {
156 InstList::iterator Orig = Context.getCur(); 195 InstList::iterator Orig = Context.getCur();
157 if (llvm::isa<InstRet>(*Orig)) 196 if (llvm::isa<InstRet>(*Orig))
158 setHasReturn(); 197 setHasReturn();
159 Target->lower(); 198 Target->lower();
160 // Ensure target lowering actually moved the cursor. 199 // Ensure target lowering actually moved the cursor.
161 assert(Context.getCur() != Orig); 200 assert(Context.getCur() != Orig);
162 } 201 }
163 } 202 }
164 203
204 // Performs liveness analysis on the block. Returns true if the
205 // incoming liveness changed from before, false if it stayed the same.
206 // (If it changes, the node's predecessors need to be processed
207 // again.)
208 bool CfgNode::liveness(LivenessMode Mode, Liveness *Liveness) {
209 SizeT NumVars;
210 if (Mode == Liveness_LREndLightweight)
211 NumVars = Func->getNumVariables();
212 else
213 NumVars = Liveness->getLocalSize(this);
214 llvm::BitVector Live(NumVars);
215 if (Mode != Liveness_LREndLightweight) {
216 // Mark the beginning and ending of each variable's live range
217 // with the sentinel instruction number 0.
218 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this);
219 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this);
220 LiveBegin.assign(NumVars, 0);
221 LiveEnd.assign(NumVars, 0);
222 // Initialize Live to be the union of all successors' LiveIn.
223 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end();
224 I != E; ++I) {
225 CfgNode *Succ = *I;
226 Live |= Liveness->getLiveIn(Succ);
227 // Mark corresponding argument of phis in successor as live.
228 for (PhiList::const_iterator I1 = Succ->Phis.begin(),
229 E1 = Succ->Phis.end();
230 I1 != E1; ++I1) {
231 (*I1)->livenessPhiOperand(Live, this, Liveness);
232 }
233 }
234 Liveness->getLiveOut(this) = Live;
235 }
236
237 // Process regular instructions in reverse order.
238 for (InstList::const_reverse_iterator I = Insts.rbegin(), E = Insts.rend();
239 I != E; ++I) {
240 (*I)->liveness(Mode, (*I)->getNumber(), Live, Liveness, this);
241 }
242 // Process phis in forward order so that we can override the
243 // instruction number to be that of the earliest phi instruction in
244 // the block.
245 int32_t FirstPhiNumber = 0; // sentinel value
246 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
247 if (FirstPhiNumber <= 0)
248 FirstPhiNumber = (*I)->getNumber();
249 (*I)->liveness(Mode, FirstPhiNumber, Live, Liveness, this);
250 }
251
252 // When using the sparse representation, after traversing the
253 // instructions in the block, the Live bitvector should only contain
254 // set bits for global variables upon block entry. We validate this
255 // by shrinking the Live vector and then testing it against the
256 // pre-shrunk version. (The shrinking is required, but the
257 // validation is not.)
258 if (Mode != Liveness_LREndLightweight) {
259 llvm::BitVector LiveOrig = Live;
260 Live.resize(Liveness->getGlobalSize());
261 // Non-global arguments in the entry node are allowed to be live on
262 // entry.
263 bool IsEntry = (Func->getEntryNode() == this);
264 assert(IsEntry || Live == LiveOrig);
265 // The following block helps debug why the previous assertion
266 // failed.
JF 2014/05/25 22:50:50 Shouldn't the block be before the assertion?
Jim Stichnoth 2014/05/29 01:39:46 Good point. Fixed this, including replacing the a
267 if (!(IsEntry || Live == LiveOrig)) {
268 Ostream &Str = Func->getContext()->getStrDump();
269 Func->setCurrentNode(NULL);
270 Str << "LiveOrig-Live =";
271 for (SizeT i = Live.size(); i < LiveOrig.size(); ++i) {
272 if (LiveOrig.test(i)) {
273 Str << " ";
274 Liveness->getVariable(i, this)->dump(Func);
275 }
276 }
277 Str << "\n";
278 }
279 }
280
281 bool Changed = false;
282 if (Mode != Liveness_LREndLightweight) {
283 llvm::BitVector &LiveIn = Liveness->getLiveIn(this);
284 // Add in current LiveIn
285 Live |= LiveIn;
286 // Check result, set LiveIn=Live
287 Changed = (Live != LiveIn);
288 if (Changed)
289 LiveIn = Live;
290 }
291 return Changed;
292 }
293
294 // Now that basic liveness is complete, remove dead instructions that
295 // were tentatively marked as dead, and compute actual live ranges.
296 // It is assumed that within a single basic block, a live range begins
297 // at most once and ends at most once. This is certainly true for
298 // pure SSA form. It is also true once phis are lowered, since each
299 // assignment to the phi-based temporary is in a different basic
300 // block, and there is a single read that ends the live in the basic
301 // block that contained the actual phi instruction.
302 void CfgNode::livenessPostprocess(LivenessMode Mode, Liveness *Liveness) {
303 int32_t FirstInstNum = 0;
304 int32_t LastInstNum = 0;
305 // Process phis in any order. Process only Dest operands.
306 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
307 InstPhi *Inst = *I;
308 Inst->deleteIfDead();
309 if (Inst->isDeleted())
310 continue;
311 if (FirstInstNum <= 0)
312 FirstInstNum = Inst->getNumber();
313 assert(Inst->getNumber() > LastInstNum);
314 LastInstNum = Inst->getNumber();
315 }
316 // Process instructions
317 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E;
318 ++I) {
319 Inst *Inst = *I;
320 Inst->deleteIfDead();
321 if (Inst->isDeleted())
322 continue;
323 if (FirstInstNum <= 0)
324 FirstInstNum = Inst->getNumber();
325 assert(Inst->getNumber() > LastInstNum);
326 LastInstNum = Inst->getNumber();
327 // Create fake live ranges for a Kill instruction, but only if the
328 // linked instruction is still alive.
329 if (Mode == Liveness_RangesFull) {
330 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(Inst)) {
331 if (!Kill->getLinked()->isDeleted()) {
332 SizeT NumSrcs = Inst->getSrcSize();
333 for (SizeT i = 0; i < NumSrcs; ++i) {
334 Variable *Var = llvm::cast<Variable>(Inst->getSrc(i));
335 int32_t InstNumber = Inst->getNumber();
336 Liveness->addLiveRange(Var, InstNumber, InstNumber, 1);
337 }
338 }
339 }
340 }
341 }
342 if (Mode != Liveness_RangesFull)
343 return;
344
345 SizeT NumVars = Liveness->getLocalSize(this);
346 SizeT NumGlobals = Liveness->getGlobalSize();
347 llvm::BitVector &LiveIn = Liveness->getLiveIn(this);
348 llvm::BitVector &LiveOut = Liveness->getLiveOut(this);
349 std::vector<int> &LiveBegin = Liveness->getLiveBegin(this);
350 std::vector<int> &LiveEnd = Liveness->getLiveEnd(this);
351 for (SizeT i = 0; i < NumVars; ++i) {
352 // Deal with the case where the variable is both live-in and
353 // live-out, but LiveEnd comes before LiveBegin. In this case, we
354 // need to add two segments to the live range because there is a
355 // hole in the middle. This would typically happen as a result of
356 // phi lowering in the presence of loopback edges.
357 bool IsGlobal = (i < NumGlobals);
358 if (IsGlobal && LiveIn[i] && LiveOut[i] && LiveBegin[i] > LiveEnd[i]) {
359 Variable *Var = Liveness->getVariable(i, this);
360 Liveness->addLiveRange(Var, FirstInstNum, LiveEnd[i], 1);
361 Liveness->addLiveRange(Var, LiveBegin[i], LastInstNum + 1, 1);
362 continue;
363 }
364 int32_t Begin = (IsGlobal && LiveIn[i]) ? FirstInstNum : LiveBegin[i];
365 int32_t End = (IsGlobal && LiveOut[i]) ? LastInstNum + 1 : LiveEnd[i];
366 if (Begin <= 0 && End <= 0)
367 continue;
368 if (Begin <= FirstInstNum)
369 Begin = FirstInstNum;
370 if (End <= 0)
371 End = LastInstNum + 1;
372 Variable *Var = Liveness->getVariable(i, this);
373 Liveness->addLiveRange(Var, Begin, End, 1);
374 }
375 }
376
165 // ======================== Dump routines ======================== // 377 // ======================== Dump routines ======================== //
166 378
167 void CfgNode::emit(Cfg *Func) const { 379 void CfgNode::emit(Cfg *Func) const {
168 Func->setCurrentNode(this); 380 Func->setCurrentNode(this);
169 Ostream &Str = Func->getContext()->getStrEmit(); 381 Ostream &Str = Func->getContext()->getStrEmit();
170 if (Func->getEntryNode() == this) { 382 if (Func->getEntryNode() == this) {
171 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n"; 383 Str << Func->getContext()->mangleName(Func->getFunctionName()) << ":\n";
172 } 384 }
173 Str << getAsmName() << ":\n"; 385 Str << getAsmName() << ":\n";
174 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) { 386 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; ++I) {
(...skipping 12 matching lines...) Expand all
187 // suppress them. 399 // suppress them.
188 if (Inst->isRedundantAssign()) 400 if (Inst->isRedundantAssign())
189 continue; 401 continue;
190 (*I)->emit(Func); 402 (*I)->emit(Func);
191 } 403 }
192 } 404 }
193 405
194 void CfgNode::dump(Cfg *Func) const { 406 void CfgNode::dump(Cfg *Func) const {
195 Func->setCurrentNode(this); 407 Func->setCurrentNode(this);
196 Ostream &Str = Func->getContext()->getStrDump(); 408 Ostream &Str = Func->getContext()->getStrDump();
409 Liveness *Liveness = Func->getLiveness();
197 if (Func->getContext()->isVerbose(IceV_Instructions)) { 410 if (Func->getContext()->isVerbose(IceV_Instructions)) {
198 Str << getName() << ":\n"; 411 Str << getName() << ":\n";
199 } 412 }
200 // Dump list of predecessor nodes. 413 // Dump list of predecessor nodes.
201 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) { 414 if (Func->getContext()->isVerbose(IceV_Preds) && !InEdges.empty()) {
202 Str << " // preds = "; 415 Str << " // preds = ";
203 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end(); 416 for (NodeList::const_iterator I = InEdges.begin(), E = InEdges.end();
204 I != E; ++I) { 417 I != E; ++I) {
205 if (I != InEdges.begin()) 418 if (I != InEdges.begin())
206 Str << ", "; 419 Str << ", ";
207 Str << "%" << (*I)->getName(); 420 Str << "%" << (*I)->getName();
208 } 421 }
209 Str << "\n"; 422 Str << "\n";
210 } 423 }
424 // Dump the live-in variables.
425 llvm::BitVector LiveIn;
426 if (Liveness)
427 LiveIn = Liveness->getLiveIn(this);
428 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveIn.empty()) {
429 Str << " // LiveIn:";
430 for (SizeT i = 0; i < LiveIn.size(); ++i) {
431 if (LiveIn[i]) {
432 Str << " %" << Liveness->getVariable(i, this)->getName();
433 }
434 }
435 Str << "\n";
436 }
211 // Dump each instruction. 437 // Dump each instruction.
212 if (Func->getContext()->isVerbose(IceV_Instructions)) { 438 if (Func->getContext()->isVerbose(IceV_Instructions)) {
213 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E; 439 for (PhiList::const_iterator I = Phis.begin(), E = Phis.end(); I != E;
214 ++I) { 440 ++I) {
215 const Inst *Inst = *I; 441 const Inst *Inst = *I;
216 Inst->dumpDecorated(Func); 442 Inst->dumpDecorated(Func);
217 } 443 }
218 InstList::const_iterator I = Insts.begin(), E = Insts.end(); 444 InstList::const_iterator I = Insts.begin(), E = Insts.end();
219 while (I != E) { 445 while (I != E) {
220 Inst *Inst = *I++; 446 Inst *Inst = *I++;
221 Inst->dumpDecorated(Func); 447 Inst->dumpDecorated(Func);
222 } 448 }
223 } 449 }
450 // Dump the live-out variables.
451 llvm::BitVector LiveOut;
452 if (Liveness)
453 LiveOut = Liveness->getLiveOut(this);
454 if (Func->getContext()->isVerbose(IceV_Liveness) && !LiveOut.empty()) {
455 Str << " // LiveOut:";
456 for (SizeT i = 0; i < LiveOut.size(); ++i) {
457 if (LiveOut[i]) {
458 Str << " %" << Liveness->getVariable(i, this)->getName();
459 }
460 }
461 Str << "\n";
462 }
224 // Dump list of successor nodes. 463 // Dump list of successor nodes.
225 if (Func->getContext()->isVerbose(IceV_Succs)) { 464 if (Func->getContext()->isVerbose(IceV_Succs)) {
226 Str << " // succs = "; 465 Str << " // succs = ";
227 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end(); 466 for (NodeList::const_iterator I = OutEdges.begin(), E = OutEdges.end();
228 I != E; ++I) { 467 I != E; ++I) {
229 if (I != OutEdges.begin()) 468 if (I != OutEdges.begin())
230 Str << ", "; 469 Str << ", ";
231 Str << "%" << (*I)->getName(); 470 Str << "%" << (*I)->getName();
232 } 471 }
233 Str << "\n"; 472 Str << "\n";
234 } 473 }
235 } 474 }
236 475
237 } // end of namespace Ice 476 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698