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

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

Powered by Google App Engine
This is Rietveld 408576698