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

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: 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/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() ? -1 : 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 if (isDeleted())
135 return;
136 if (llvm::isa<InstFakeKill>(this))
137 return;
138 resetLastUses();
85 SizeT VarIndex = 0; 139 SizeT VarIndex = 0;
86 for (SizeT I = 0; I < getSrcSize(); ++I) { 140 for (SizeT I = 0; I < getSrcSize(); ++I) {
87 Operand *Src = getSrc(I); 141 Operand *Src = getSrc(I);
88 SizeT NumVars = Src->getNumVars(); 142 SizeT NumVars = Src->getNumVars();
89 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) { 143 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
90 Variable *Var = Src->getVar(J); 144 const Variable *Var = Src->getVar(J);
91 Var->setUse(this, Node); 145 if (Var->isMultiblockLife())
146 continue;
147 SizeT Index = Var->getIndex();
148 if (Live[Index])
149 continue;
150 Live[Index] = true;
151 setLastUse(VarIndex);
152 }
153 }
154 }
155
156 void Inst::liveness(int32_t InstNumber, llvm::BitVector &Live,
157 Liveness *Liveness, const CfgNode *Node) {
158 if (isDeleted())
159 return;
160 if (llvm::isa<InstFakeKill>(this))
161 return;
162
163 std::vector<int32_t> &LiveBegin = Liveness->getLiveBegin(Node);
164 std::vector<int32_t> &LiveEnd = Liveness->getLiveEnd(Node);
165 Dead = false;
166 if (Dest) {
167 SizeT VarNum = Liveness->getLiveIndex(Dest);
168 if (Live[VarNum]) {
169 Live[VarNum] = false;
170 LiveBegin[VarNum] = InstNumber;
171 } else {
172 if (!hasSideEffects())
173 Dead = true;
174 }
175 }
176 if (Dead)
177 return;
178 // Phi arguments only get added to Live in the predecessor node, but
179 // we still need to update LiveRangesEnded.
180 bool IsPhi = llvm::isa<InstPhi>(this);
181 resetLastUses();
182 SizeT VarIndex = 0;
183 for (SizeT I = 0; I < getSrcSize(); ++I) {
184 Operand *Src = getSrc(I);
185 SizeT NumVars = Src->getNumVars();
186 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
187 const Variable *Var = Src->getVar(J);
188 SizeT VarNum = Liveness->getLiveIndex(Var);
189 if (!Live[VarNum]) {
190 setLastUse(VarIndex);
191 if (!IsPhi) {
192 Live[VarNum] = true;
193 // For a variable in SSA form, its live range can end at
194 // most once in a basic block. However, after lowering to
195 // two-address instructions, we end up with sequences like
196 // "t=b;t+=c;a=t" where t's live range begins and ends
197 // twice. ICE only allows a variable to have a single
198 // liveness interval in a basic block (except for blocks
199 // where a variable is live-in and live-out but there is a
200 // gap in the middle, and except for the special
201 // InstFakeKill instruction that can appear multiple
202 // times in the same block). Therefore, this lowered
203 // sequence needs to represent a single conservative live
204 // range for t. Since the instructions are being traversed
205 // backwards, we make sure LiveEnd is only set once by
206 // setting it only when LiveEnd[VarNum]==0 (sentinel value).
207 // Note that it's OK to set LiveBegin multiple times because
208 // of the backwards traversal.
209 if (LiveEnd[VarNum] == 0) {
210 LiveEnd[VarNum] = InstNumber;
211 }
212 }
213 }
92 } 214 }
93 } 215 }
94 } 216 }
95 217
96 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, 218 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes,
97 Variable *Dest) 219 Variable *Dest)
98 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { 220 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) {
99 // Verify AlignInBytes is 0 or a power of 2. 221 // Verify AlignInBytes is 0 or a power of 2.
100 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); 222 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes));
101 addSource(ByteCount); 223 addSource(ByteCount);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
185 // improved if it becomes a problem. 307 // improved if it becomes a problem.
186 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const { 308 Operand *InstPhi::getOperandForTarget(CfgNode *Target) const {
187 for (SizeT I = 0; I < getSrcSize(); ++I) { 309 for (SizeT I = 0; I < getSrcSize(); ++I) {
188 if (Labels[I] == Target) 310 if (Labels[I] == Target)
189 return getSrc(I); 311 return getSrc(I);
190 } 312 }
191 llvm_unreachable("Phi target not found"); 313 llvm_unreachable("Phi target not found");
192 return NULL; 314 return NULL;
193 } 315 }
194 316
317 // Updates liveness for a particular operand based on the given
318 // predecessor edge. Doesn't mark the operand as live if the Phi
319 // instruction is dead or deleted.
320 void InstPhi::livenessPhiOperand(llvm::BitVector &Live, CfgNode *Target,
321 Liveness *Liveness) {
322 if (isDeleted() || Dead)
323 return;
324 for (SizeT I = 0; I < getSrcSize(); ++I) {
325 if (Labels[I] == Target) {
326 if (Variable *Var = llvm::dyn_cast<Variable>(getSrc(I))) {
327 SizeT SrcIndex = Liveness->getLiveIndex(Var);
328 if (!Live[SrcIndex]) {
329 setLastUse(I);
330 Live[SrcIndex] = true;
331 }
332 }
333 return;
334 }
335 }
336 llvm_unreachable("Phi operand not found for specified target node");
337 }
338
195 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new 339 // Change "a=phi(...)" to "a_phi=phi(...)" and return a new
196 // instruction "a=a_phi". 340 // instruction "a=a_phi".
197 Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) { 341 Inst *InstPhi::lower(Cfg *Func, CfgNode *Node) {
198 Variable *Dest = getDest(); 342 Variable *Dest = getDest();
199 assert(Dest); 343 assert(Dest);
200 IceString PhiName = Dest->getName() + "_phi"; 344 IceString PhiName = Dest->getName() + "_phi";
201 Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName); 345 Variable *NewSrc = Func->makeVariable(Dest->getType(), Node, PhiName);
202 this->Dest = NewSrc; 346 this->Dest = NewSrc;
203 InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc); 347 InstAssign *NewInst = InstAssign::create(Func, Dest, NewSrc);
204 // Set Dest and NewSrc to have affinity with each other, as a hint 348 // Set Dest and NewSrc to have affinity with each other, as a hint
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 if (Number < 0) 442 if (Number < 0)
299 snprintf(buf, llvm::array_lengthof(buf), "[XXX]"); 443 snprintf(buf, llvm::array_lengthof(buf), "[XXX]");
300 else 444 else
301 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number); 445 snprintf(buf, llvm::array_lengthof(buf), "[%3d]", Number);
302 Str << buf; 446 Str << buf;
303 } 447 }
304 Str << " "; 448 Str << " ";
305 if (isDeleted()) 449 if (isDeleted())
306 Str << " //"; 450 Str << " //";
307 dump(Func); 451 dump(Func);
452 dumpExtras(Func);
308 Str << "\n"; 453 Str << "\n";
309 } 454 }
310 455
311 void Inst::emit(const Cfg * /*Func*/) const { 456 void Inst::emit(const Cfg * /*Func*/) const {
312 llvm_unreachable("emit() called on a non-lowered instruction"); 457 llvm_unreachable("emit() called on a non-lowered instruction");
313 } 458 }
314 459
315 void Inst::dump(const Cfg *Func) const { 460 void Inst::dump(const Cfg *Func) const {
316 Ostream &Str = Func->getContext()->getStrDump(); 461 Ostream &Str = Func->getContext()->getStrDump();
317 dumpDest(Func); 462 dumpDest(Func);
318 Str << " =~ "; 463 Str << " =~ ";
319 dumpSources(Func); 464 dumpSources(Func);
320 } 465 }
321 466
467 void Inst::dumpExtras(const Cfg *Func) const {
468 Ostream &Str = Func->getContext()->getStrDump();
469 bool First = true;
470 // Print "LIVEEND={a,b,c}" for all source operands whose live ranges
471 // are known to end at this instruction.
472 if (Func->getContext()->isVerbose(IceV_Liveness)) {
473 for (SizeT I = 0; I < getSrcSize(); ++I) {
474 Operand *Src = getSrc(I);
475 SizeT NumVars = Src->getNumVars();
476 for (SizeT J = 0; J < NumVars; ++J) {
477 const Variable *Var = Src->getVar(J);
478 if (isLastUse(Var)) {
479 if (First)
480 Str << " // LIVEEND={";
481 else
482 Str << ",";
483 Var->dump(Func);
484 First = false;
485 }
486 }
487 }
488 if (!First)
489 Str << "}";
490 }
491 }
492
322 void Inst::dumpSources(const Cfg *Func) const { 493 void Inst::dumpSources(const Cfg *Func) const {
323 Ostream &Str = Func->getContext()->getStrDump(); 494 Ostream &Str = Func->getContext()->getStrDump();
324 for (SizeT I = 0; I < getSrcSize(); ++I) { 495 for (SizeT I = 0; I < getSrcSize(); ++I) {
325 if (I > 0) 496 if (I > 0)
326 Str << ", "; 497 Str << ", ";
327 getSrc(I)->dump(Func); 498 getSrc(I)->dump(Func);
328 } 499 }
329 } 500 }
330 501
331 void Inst::emitSources(const Cfg *Func) const { 502 void Inst::emitSources(const Cfg *Func) const {
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
546 Str << "kill.pseudo "; 717 Str << "kill.pseudo ";
547 dumpSources(Func); 718 dumpSources(Func);
548 } 719 }
549 720
550 void InstTarget::dump(const Cfg *Func) const { 721 void InstTarget::dump(const Cfg *Func) const {
551 Ostream &Str = Func->getContext()->getStrDump(); 722 Ostream &Str = Func->getContext()->getStrDump();
552 Str << "[TARGET] "; 723 Str << "[TARGET] ";
553 Inst::dump(Func); 724 Inst::dump(Func);
554 } 725 }
555 726
727 void InstTarget::dumpExtras(const Cfg *Func) const { Inst::dumpExtras(Func); }
728
556 } // end of namespace Ice 729 } // end of namespace Ice
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698