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

Side by Side Diff: src/IceInst.cpp

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Jan's third-round comments 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
« no previous file with comments | « src/IceInst.h ('k') | src/IceLiveness.h » ('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/IceInst.cpp - High-level instruction implementation ----===// 1 //===- subzero/src/IceInst.cpp - High-level instruction 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 Inst class, primarily the various 10 // This file implements the Inst class, primarily the various
11 // subclass constructors and dump routines. 11 // subclass constructors and dump routines.
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 20
20 namespace Ice { 21 namespace Ice {
21 22
22 namespace { 23 namespace {
23 24
24 // Using non-anonymous struct so that array_lengthof works. 25 // Using non-anonymous struct so that array_lengthof works.
25 const struct InstArithmeticAttributes_ { 26 const struct InstArithmeticAttributes_ {
26 const char *DisplayString; 27 const char *DisplayString;
27 bool IsCommutative; 28 bool IsCommutative;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 { str } \ 68 { str } \
68 , 69 ,
69 ICEINSTICMP_TABLE 70 ICEINSTICMP_TABLE
70 #undef X 71 #undef X
71 }; 72 };
72 const size_t InstIcmpAttributesSize = llvm::array_lengthof(InstIcmpAttributes); 73 const size_t InstIcmpAttributesSize = llvm::array_lengthof(InstIcmpAttributes);
73 74
74 } // end of anonymous namespace 75 } // end of anonymous namespace
75 76
76 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) 77 Inst::Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest)
77 : Kind(Kind), Number(Func->newInstNumber()), Deleted(false), 78 : Kind(Kind), Number(Func->newInstNumber()), Deleted(false), Dead(false),
78 HasSideEffects(false), Dest(Dest), MaxSrcs(MaxSrcs), NumSrcs(0), 79 HasSideEffects(false), Dest(Dest), MaxSrcs(MaxSrcs), NumSrcs(0),
79 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)) {} 80 Srcs(Func->allocateArrayOf<Operand *>(MaxSrcs)), LiveRangesEnded(0) {}
81
82 // Assign the instruction a new number.
83 void Inst::renumber(Cfg *Func) {
84 Number = isDeleted() ? NumberDeleted : Func->newInstNumber();
85 }
86
87 // Delete the instruction if its tentative Dead flag is still set
88 // after liveness analysis.
89 void Inst::deleteIfDead() {
90 if (Dead)
91 setDeleted();
92 }
93
94 // If Src is a Variable, it returns true if this instruction ends
95 // Src's live range. Otherwise, returns false.
96 bool Inst::isLastUse(const Operand *TestSrc) const {
97 if (LiveRangesEnded == 0)
98 return false; // early-exit optimization
99 if (const Variable *TestVar = llvm::dyn_cast<const Variable>(TestSrc)) {
100 LREndedBits Mask = LiveRangesEnded;
101 for (SizeT I = 0; I < getSrcSize(); ++I) {
102 Operand *Src = getSrc(I);
103 SizeT NumVars = Src->getNumVars();
104 for (SizeT J = 0; J < NumVars; ++J) {
105 const Variable *Var = Src->getVar(J);
106 if (Var == TestVar) {
107 // We've found where the variable is used in the instruction.
108 return Mask & 1;
109 }
110 Mask >>= 1;
111 if (Mask == 0)
112 return false; // another early-exit optimization
113 }
114 }
115 }
116 return false;
117 }
80 118
81 void Inst::updateVars(CfgNode *Node) { 119 void Inst::updateVars(CfgNode *Node) {
82 if (Dest) 120 if (Dest)
83 Dest->setDefinition(this, Node); 121 Dest->setDefinition(this, Node);
84 122
123 for (SizeT I = 0; I < getSrcSize(); ++I) {
124 Operand *Src = getSrc(I);
125 SizeT NumVars = Src->getNumVars();
126 for (SizeT J = 0; J < NumVars; ++J) {
127 Variable *Var = Src->getVar(J);
128 Var->setUse(this, Node);
129 }
130 }
131 }
132
133 void Inst::livenessLightweight(llvm::BitVector &Live) {
134 assert(!isDeleted());
135 if (llvm::isa<InstFakeKill>(this))
136 return;
137 resetLastUses();
85 SizeT VarIndex = 0; 138 SizeT VarIndex = 0;
86 for (SizeT I = 0; I < getSrcSize(); ++I) { 139 for (SizeT I = 0; I < getSrcSize(); ++I) {
87 Operand *Src = getSrc(I); 140 Operand *Src = getSrc(I);
88 SizeT NumVars = Src->getNumVars(); 141 SizeT NumVars = Src->getNumVars();
89 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) { 142 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
90 Variable *Var = Src->getVar(J); 143 const Variable *Var = Src->getVar(J);
91 Var->setUse(this, Node); 144 if (Var->isMultiblockLife())
145 continue;
146 SizeT Index = Var->getIndex();
147 if (Live[Index])
148 continue;
149 Live[Index] = true;
150 setLastUse(VarIndex);
151 }
152 }
153 }
154
155 void Inst::liveness(InstNumberT InstNumber, llvm::BitVector &Live,
156 Liveness *Liveness, const CfgNode *Node) {
157 assert(!isDeleted());
158 if (llvm::isa<InstFakeKill>(this))
159 return;
160
161 std::vector<InstNumberT> &LiveBegin = Liveness->getLiveBegin(Node);
162 std::vector<InstNumberT> &LiveEnd = Liveness->getLiveEnd(Node);
163 Dead = false;
164 if (Dest) {
165 SizeT VarNum = Liveness->getLiveIndex(Dest);
166 if (Live[VarNum]) {
167 Live[VarNum] = false;
168 LiveBegin[VarNum] = InstNumber;
169 } else {
170 if (!hasSideEffects())
171 Dead = true;
172 }
173 }
174 if (Dead)
175 return;
176 // Phi arguments only get added to Live in the predecessor node, but
177 // we still need to update LiveRangesEnded.
178 bool IsPhi = llvm::isa<InstPhi>(this);
179 resetLastUses();
180 SizeT VarIndex = 0;
181 for (SizeT I = 0; I < getSrcSize(); ++I) {
182 Operand *Src = getSrc(I);
183 SizeT NumVars = Src->getNumVars();
184 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
185 const Variable *Var = Src->getVar(J);
186 SizeT VarNum = Liveness->getLiveIndex(Var);
187 if (!Live[VarNum]) {
188 setLastUse(VarIndex);
189 if (!IsPhi) {
190 Live[VarNum] = true;
191 // For a variable in SSA form, its live range can end at
192 // most once in a basic block. However, after lowering to
193 // two-address instructions, we end up with sequences like
194 // "t=b;t+=c;a=t" where t's live range begins and ends
195 // twice. ICE only allows a variable to have a single
196 // liveness interval in a basic block (except for blocks
197 // where a variable is live-in and live-out but there is a
198 // gap in the middle, and except for the special
199 // InstFakeKill instruction that can appear multiple
200 // times in the same block). Therefore, this lowered
201 // sequence needs to represent a single conservative live
202 // range for t. Since the instructions are being traversed
203 // backwards, we make sure LiveEnd is only set once by
204 // setting it only when LiveEnd[VarNum]==0 (sentinel value).
205 // Note that it's OK to set LiveBegin multiple times because
206 // of the backwards traversal.
207 if (LiveEnd[VarNum] == 0) {
208 LiveEnd[VarNum] = InstNumber;
209 }
210 }
211 }
92 } 212 }
93 } 213 }
94 } 214 }
95 215
96 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 216 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
97 Variable *Dest) 217 Variable *Dest)
98 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { 218 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
99 // Verify AlignInBytes is 0 or a power of 2. 219 // Verify AlignInBytes is 0 or a power of 2.
100 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); 220 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
101 addSource(ByteCount); 221 addSource(ByteCount);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // improved if it becomes a problem. 305 // improved if it becomes a problem.
186 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const { 306 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
187 for (SizeT I = 0; I < getSrcSize(); ++I) { 307 for (SizeT I = 0; I < getSrcSize(); ++I) {
188 if (Labels[I] == Target) 308 if (Labels[I] == Target)
189 return getSrc(I); 309 return getSrc(I);
190 } 310 }
191 llvm_unreachable("Phi target not found"); 311 llvm_unreachable("Phi target not found");
192 return NULL; 312 return NULL;
193 } 313 }
194 314
315 // Updates liveness for a particular operand based on the given
316 // predecessor edge. Doesn't mark the operand as live if the Phi
317 // instruction is dead or deleted.
318 void InstPhi::livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target,
319 Liveness *Liveness) {
320 if (isDeleted() || Dead)
321 return;
322 for (SizeT I = 0; I < getSrcSize(); ++I) {
323 if (Labels[I] == Target) {
324 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
325 SizeT SrcIndex = Liveness->getLiveIndex(Var);
326 if (!Live[SrcIndex]) {
327 setLastUse(I);
328 Live[SrcIndex] = true;
329 }
330 }
331 return;
332 }
333 }
334 llvm_unreachable("Phi operand not found for specified target node");
335 }
336
195 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new 337 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new
196 // instruction "a=a_phi". 338 // instruction "a=a_phi".
197 Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) { 339 Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) {
198 Variable *Dest = getDest(); 340 Variable *Dest = getDest();
199 assert(Dest); 341 assert(Dest);
200 IceString PhiName = Dest->getName() + "_phi"; 342 IceString PhiName = Dest->getName() + "_phi";
201 Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName); 343 Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName);
202 this->Dest = NewSrc; 344 this->Dest = NewSrc;
203 InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc); 345 InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc);
204 // Set Dest and NewSrc to have affinity with each other, as a hint 346 // Set Dest and NewSrc to have affinity with each other, as a hint
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 429
288 // ======================== Dump routines ======================== // 430 // ======================== Dump routines ======================== //
289 431
290 void Inst::dumpDecorated(const Cfg *Func) const { 432 void Inst::dumpDecorated(const Cfg *Func) const {
291 Ostream &Str = Func->getContext()->getStrDump(); 433 Ostream &Str = Func->getContext()->getStrDump();
292 if (!Func->getContext()->isVerbose(IceV_Deleted) && 434 if (!Func->getContext()->isVerbose(IceV_Deleted) &&
293 (isDeleted() || isRedundantAssign())) 435 (isDeleted() || isRedundantAssign()))
294 return; 436 return;
295 if (Func->getContext()->isVerbose(IceV_InstNumbers)) { 437 if (Func->getContext()->isVerbose(IceV_InstNumbers)) {
296 char buf[30]; 438 char buf[30];
297 int32_t Number = getNumber(); 439 InstNumberT Number = getNumber();
298 if (Number < 0) 440 if (Number == NumberDeleted)
299 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); 441 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
300 else 442 else
301 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number); 443 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
302 Str << buf; 444 Str << buf;
303 } 445 }
304 Str << " "; 446 Str << " ";
305 if (isDeleted()) 447 if (isDeleted())
306 Str << " //"; 448 Str << " //";
307 dump(Func); 449 dump(Func);
450 dumpExtras(Func);
308 Str << "\n"; 451 Str << "\n";
309 } 452 }
310 453
311 void Inst::emit(const Cfg * /*Func*/) const { 454 void Inst::emit(const Cfg * /*Func*/) const {
312 llvm_unreachable("emit() called on a non-lowered instruction"); 455 llvm_unreachable("emit() called on a non-lowered instruction");
313 } 456 }
314 457
315 void Inst::dump(const Cfg *Func) const { 458 void Inst::dump(const Cfg *Func) const {
316 Ostream &Str = Func->getContext()->getStrDump(); 459 Ostream &Str = Func->getContext()->getStrDump();
317 dumpDest(Func); 460 dumpDest(Func);
318 Str << " =~ "; 461 Str << " =~ ";
319 dumpSources(Func); 462 dumpSources(Func);
320 } 463 }
321 464
465 void Inst::dumpExtras(const Cfg *Func) const {
466 Ostream &Str = Func->getContext()->getStrDump();
467 bool First = true;
468 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges
469 // are known to end at this instruction.
470 if (Func->getContext()->isVerbose(IceV_Liveness)) {
471 for (SizeT I = 0; I < getSrcSize(); ++I) {
472 Operand *Src = getSrc(I);
473 SizeT NumVars = Src->getNumVars();
474 for (SizeT J = 0; J < NumVars; ++J) {
475 const Variable *Var = Src->getVar(J);
476 if (isLastUse(Var)) {
477 if (First)
478 Str << " // LIVEEND={";
479 else
480 Str << ",";
481 Var->dump(Func);
482 First = false;
483 }
484 }
485 }
486 if (!First)
487 Str << "}";
488 }
489 }
490
322 void Inst::dumpSources(const Cfg *Func) const { 491 void Inst::dumpSources(const Cfg *Func) const {
323 Ostream &Str = Func->getContext()->getStrDump(); 492 Ostream &Str = Func->getContext()->getStrDump();
324 for (SizeT I = 0; I < getSrcSize(); ++I) { 493 for (SizeT I = 0; I < getSrcSize(); ++I) {
325 if (I > 0) 494 if (I > 0)
326 Str << ", "; 495 Str << ", ";
327 getSrc(I)->dump(Func); 496 getSrc(I)->dump(Func);
328 } 497 }
329 } 498 }
330 499
331 void Inst::emitSources(const Cfg *Func) const { 500 void Inst::emitSources(const Cfg *Func) const {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 Str << "kill.pseudo "; 715 Str << "kill.pseudo ";
547 dumpSources(Func); 716 dumpSources(Func);
548 } 717 }
549 718
550 void InstTarget::dump(const Cfg *Func) const { 719 void InstTarget::dump(const Cfg *Func) const {
551 Ostream &Str = Func->getContext()->getStrDump(); 720 Ostream &Str = Func->getContext()->getStrDump();
552 Str << "[TARGET] "; 721 Str << "[TARGET] ";
553 Inst::dump(Func); 722 Inst::dump(Func);
554 } 723 }
555 724
725 void InstTarget::dumpExtras(const Cfg *Func) const { Inst::dumpExtras(Func); }
726
556 } // end of namespace Ice 727 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceInst.h ('k') | src/IceLiveness.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698