OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |