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 |
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
189 LiveEnd[VarNum] = InstNumber; | 189 LiveEnd[VarNum] = InstNumber; |
190 } | 190 } |
191 } | 191 } |
192 } | 192 } |
193 } | 193 } |
194 } | 194 } |
195 } | 195 } |
196 | 196 |
197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 197 InstAlloca::InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
198 Variable *Dest) | 198 Variable *Dest) |
199 : Inst(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { | 199 : InstHighLevel(Func, Inst::Alloca, 1, Dest), AlignInBytes(AlignInBytes) { |
200 // Verify AlignInBytes is 0 or a power of 2. | 200 // Verify AlignInBytes is 0 or a power of 2. |
201 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); | 201 assert(AlignInBytes == 0 || llvm::isPowerOf2_32(AlignInBytes)); |
202 addSource(ByteCount); | 202 addSource(ByteCount); |
203 } | 203 } |
204 | 204 |
205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, | 205 InstArithmetic::InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, |
206 Operand *Source1, Operand *Source2) | 206 Operand *Source1, Operand *Source2) |
207 : Inst(Func, Inst::Arithmetic, 2, Dest), Op(Op) { | 207 : InstHighLevel(Func, Inst::Arithmetic, 2, Dest), Op(Op) { |
208 addSource(Source1); | 208 addSource(Source1); |
209 addSource(Source2); | 209 addSource(Source2); |
210 } | 210 } |
211 | 211 |
212 const char *InstArithmetic::getOpName(OpKind Op) { | 212 const char *InstArithmetic::getOpName(OpKind Op) { |
213 size_t OpIndex = static_cast<size_t>(Op); | 213 size_t OpIndex = static_cast<size_t>(Op); |
214 return OpIndex < InstArithmetic::_num | 214 return OpIndex < InstArithmetic::_num |
215 ? InstArithmeticAttributes[OpIndex].DisplayString | 215 ? InstArithmeticAttributes[OpIndex].DisplayString |
216 : "???"; | 216 : "???"; |
217 } | 217 } |
218 | 218 |
219 bool InstArithmetic::isCommutative() const { | 219 bool InstArithmetic::isCommutative() const { |
220 return InstArithmeticAttributes[getOp()].IsCommutative; | 220 return InstArithmeticAttributes[getOp()].IsCommutative; |
221 } | 221 } |
222 | 222 |
223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) | 223 InstAssign::InstAssign(Cfg *Func, Variable *Dest, Operand *Source) |
224 : Inst(Func, Inst::Assign, 1, Dest) { | 224 : InstHighLevel(Func, Inst::Assign, 1, Dest) { |
225 addSource(Source); | 225 addSource(Source); |
226 } | 226 } |
227 | 227 |
228 // If TargetTrue==TargetFalse, we turn it into an unconditional | 228 // If TargetTrue==TargetFalse, we turn it into an unconditional |
229 // branch. This ensures that, along with the 'switch' instruction | 229 // branch. This ensures that, along with the 'switch' instruction |
230 // semantics, there is at most one edge from one node to another. | 230 // semantics, there is at most one edge from one node to another. |
231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 231 InstBr::InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |
232 CfgNode *TargetFalse) | 232 CfgNode *TargetFalse) |
233 : Inst(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), | 233 : InstHighLevel(Func, Inst::Br, 1, NULL), TargetFalse(TargetFalse), |
234 TargetTrue(TargetTrue) { | 234 TargetTrue(TargetTrue) { |
235 if (TargetTrue == TargetFalse) { | 235 if (TargetTrue == TargetFalse) { |
236 TargetTrue = NULL; // turn into unconditional version | 236 TargetTrue = NULL; // turn into unconditional version |
237 } else { | 237 } else { |
238 addSource(Source); | 238 addSource(Source); |
239 } | 239 } |
240 } | 240 } |
241 | 241 |
242 InstBr::InstBr(Cfg *Func, CfgNode *Target) | 242 InstBr::InstBr(Cfg *Func, CfgNode *Target) |
243 : Inst(Func, Inst::Br, 0, NULL), TargetFalse(Target), TargetTrue(NULL) {} | 243 : InstHighLevel(Func, Inst::Br, 0, NULL), TargetFalse(Target), |
| 244 TargetTrue(NULL) {} |
244 | 245 |
245 NodeList InstBr::getTerminatorEdges() const { | 246 NodeList InstBr::getTerminatorEdges() const { |
246 NodeList OutEdges; | 247 NodeList OutEdges; |
247 OutEdges.push_back(TargetFalse); | 248 OutEdges.push_back(TargetFalse); |
248 if (TargetTrue) | 249 if (TargetTrue) |
249 OutEdges.push_back(TargetTrue); | 250 OutEdges.push_back(TargetTrue); |
250 return OutEdges; | 251 return OutEdges; |
251 } | 252 } |
252 | 253 |
253 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) | 254 InstCast::InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source) |
254 : Inst(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { | 255 : InstHighLevel(Func, Inst::Cast, 1, Dest), CastKind(CastKind) { |
255 addSource(Source); | 256 addSource(Source); |
256 } | 257 } |
257 | 258 |
258 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, | 259 InstExtractElement::InstExtractElement(Cfg *Func, Variable *Dest, |
259 Operand *Source1, Operand *Source2) | 260 Operand *Source1, Operand *Source2) |
260 : Inst(Func, Inst::ExtractElement, 2, Dest) { | 261 : InstHighLevel(Func, Inst::ExtractElement, 2, Dest) { |
261 addSource(Source1); | 262 addSource(Source1); |
262 addSource(Source2); | 263 addSource(Source2); |
263 } | 264 } |
264 | 265 |
265 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 266 InstFcmp::InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
266 Operand *Source2) | 267 Operand *Source2) |
267 : Inst(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { | 268 : InstHighLevel(Func, Inst::Fcmp, 2, Dest), Condition(Condition) { |
268 addSource(Source1); | 269 addSource(Source1); |
269 addSource(Source2); | 270 addSource(Source2); |
270 } | 271 } |
271 | 272 |
272 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 273 InstIcmp::InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
273 Operand *Source2) | 274 Operand *Source2) |
274 : Inst(Func, Inst::Icmp, 2, Dest), Condition(Condition) { | 275 : InstHighLevel(Func, Inst::Icmp, 2, Dest), Condition(Condition) { |
275 addSource(Source1); | 276 addSource(Source1); |
276 addSource(Source2); | 277 addSource(Source2); |
277 } | 278 } |
278 | 279 |
279 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, | 280 InstInsertElement::InstInsertElement(Cfg *Func, Variable *Dest, |
280 Operand *Source1, Operand *Source2, | 281 Operand *Source1, Operand *Source2, |
281 Operand *Source3) | 282 Operand *Source3) |
282 : Inst(Func, Inst::InsertElement, 3, Dest) { | 283 : InstHighLevel(Func, Inst::InsertElement, 3, Dest) { |
283 addSource(Source1); | 284 addSource(Source1); |
284 addSource(Source2); | 285 addSource(Source2); |
285 addSource(Source3); | 286 addSource(Source3); |
286 } | 287 } |
287 | 288 |
288 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) | 289 InstLoad::InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr) |
289 : Inst(Func, Inst::Load, 1, Dest) { | 290 : InstHighLevel(Func, Inst::Load, 1, Dest) { |
290 addSource(SourceAddr); | 291 addSource(SourceAddr); |
291 } | 292 } |
292 | 293 |
293 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) | 294 InstPhi::InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest) |
294 : Inst(Func, Phi, MaxSrcs, Dest) { | 295 : InstHighLevel(Func, Phi, MaxSrcs, Dest) { |
295 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); | 296 Labels = Func->allocateArrayOf<CfgNode *>(MaxSrcs); |
296 } | 297 } |
297 | 298 |
298 // TODO: A Switch instruction (and maybe others) can add duplicate | 299 // TODO: A Switch instruction (and maybe others) can add duplicate |
299 // edges. We may want to de-dup Phis and validate consistency (i.e., | 300 // edges. We may want to de-dup Phis and validate consistency (i.e., |
300 // the source operands are the same for duplicate edges), though it | 301 // the source operands are the same for duplicate edges), though it |
301 // seems the current lowering code is OK with this situation. | 302 // seems the current lowering code is OK with this situation. |
302 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { | 303 void InstPhi::addArgument(Operand *Source, CfgNode *Label) { |
303 Labels[getSrcSize()] = Label; | 304 Labels[getSrcSize()] = Label; |
304 addSource(Source); | 305 addSource(Source); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
343 Inst *InstPhi::lower(Cfg *Func) { | 344 Inst *InstPhi::lower(Cfg *Func) { |
344 Variable *Dest = getDest(); | 345 Variable *Dest = getDest(); |
345 assert(Dest); | 346 assert(Dest); |
346 IceString PhiName = Dest->getName() + "_phi"; | 347 IceString PhiName = Dest->getName() + "_phi"; |
347 Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); | 348 Variable *NewSrc = Func->makeVariable(Dest->getType(), PhiName); |
348 this->Dest = NewSrc; | 349 this->Dest = NewSrc; |
349 return InstAssign::create(Func, Dest, NewSrc); | 350 return InstAssign::create(Func, Dest, NewSrc); |
350 } | 351 } |
351 | 352 |
352 InstRet::InstRet(Cfg *Func, Operand *RetValue) | 353 InstRet::InstRet(Cfg *Func, Operand *RetValue) |
353 : Inst(Func, Ret, RetValue ? 1 : 0, NULL) { | 354 : InstHighLevel(Func, Ret, RetValue ? 1 : 0, NULL) { |
354 if (RetValue) | 355 if (RetValue) |
355 addSource(RetValue); | 356 addSource(RetValue); |
356 } | 357 } |
357 | 358 |
358 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, | 359 InstSelect::InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, |
359 Operand *SourceTrue, Operand *SourceFalse) | 360 Operand *SourceTrue, Operand *SourceFalse) |
360 : Inst(Func, Inst::Select, 3, Dest) { | 361 : InstHighLevel(Func, Inst::Select, 3, Dest) { |
361 assert(typeElementType(Condition->getType()) == IceType_i1); | 362 assert(typeElementType(Condition->getType()) == IceType_i1); |
362 addSource(Condition); | 363 addSource(Condition); |
363 addSource(SourceTrue); | 364 addSource(SourceTrue); |
364 addSource(SourceFalse); | 365 addSource(SourceFalse); |
365 } | 366 } |
366 | 367 |
367 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) | 368 InstStore::InstStore(Cfg *Func, Operand *Data, Operand *Addr) |
368 : Inst(Func, Inst::Store, 2, NULL) { | 369 : InstHighLevel(Func, Inst::Store, 2, NULL) { |
369 addSource(Data); | 370 addSource(Data); |
370 addSource(Addr); | 371 addSource(Addr); |
371 } | 372 } |
372 | 373 |
373 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, | 374 InstSwitch::InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, |
374 CfgNode *LabelDefault) | 375 CfgNode *LabelDefault) |
375 : Inst(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), | 376 : InstHighLevel(Func, Inst::Switch, 1, NULL), LabelDefault(LabelDefault), |
376 NumCases(NumCases) { | 377 NumCases(NumCases) { |
377 addSource(Source); | 378 addSource(Source); |
378 Values = Func->allocateArrayOf<uint64_t>(NumCases); | 379 Values = Func->allocateArrayOf<uint64_t>(NumCases); |
379 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); | 380 Labels = Func->allocateArrayOf<CfgNode *>(NumCases); |
380 // Initialize in case buggy code doesn't set all entries | 381 // Initialize in case buggy code doesn't set all entries |
381 for (SizeT I = 0; I < NumCases; ++I) { | 382 for (SizeT I = 0; I < NumCases; ++I) { |
382 Values[I] = 0; | 383 Values[I] = 0; |
383 Labels[I] = NULL; | 384 Labels[I] = NULL; |
384 } | 385 } |
385 } | 386 } |
386 | 387 |
387 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { | 388 void InstSwitch::addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label) { |
388 assert(CaseIndex < NumCases); | 389 assert(CaseIndex < NumCases); |
389 Values[CaseIndex] = Value; | 390 Values[CaseIndex] = Value; |
390 Labels[CaseIndex] = Label; | 391 Labels[CaseIndex] = Label; |
391 } | 392 } |
392 | 393 |
393 NodeList InstSwitch::getTerminatorEdges() const { | 394 NodeList InstSwitch::getTerminatorEdges() const { |
394 NodeList OutEdges; | 395 NodeList OutEdges; |
395 OutEdges.push_back(LabelDefault); | 396 OutEdges.push_back(LabelDefault); |
396 for (SizeT I = 0; I < NumCases; ++I) { | 397 for (SizeT I = 0; I < NumCases; ++I) { |
397 OutEdges.push_back(Labels[I]); | 398 OutEdges.push_back(Labels[I]); |
398 } | 399 } |
399 return OutEdges; | 400 return OutEdges; |
400 } | 401 } |
401 | 402 |
402 InstUnreachable::InstUnreachable(Cfg *Func) | 403 InstUnreachable::InstUnreachable(Cfg *Func) |
403 : Inst(Func, Inst::Unreachable, 0, NULL) {} | 404 : InstHighLevel(Func, Inst::Unreachable, 0, NULL) {} |
404 | 405 |
405 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) | 406 InstFakeDef::InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src) |
406 : Inst(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { | 407 : InstHighLevel(Func, Inst::FakeDef, Src ? 1 : 0, Dest) { |
407 assert(Dest); | 408 assert(Dest); |
408 if (Src) | 409 if (Src) |
409 addSource(Src); | 410 addSource(Src); |
410 } | 411 } |
411 | 412 |
412 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) | 413 InstFakeUse::InstFakeUse(Cfg *Func, Variable *Src) |
413 : Inst(Func, Inst::FakeUse, 1, NULL) { | 414 : InstHighLevel(Func, Inst::FakeUse, 1, NULL) { |
414 assert(Src); | 415 assert(Src); |
415 addSource(Src); | 416 addSource(Src); |
416 } | 417 } |
417 | 418 |
418 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, | 419 InstFakeKill::InstFakeKill(Cfg *Func, const VarList &KilledRegs, |
419 const Inst *Linked) | 420 const Inst *Linked) |
420 : Inst(Func, Inst::FakeKill, KilledRegs.size(), NULL), Linked(Linked) { | 421 : InstHighLevel(Func, Inst::FakeKill, KilledRegs.size(), NULL), |
| 422 Linked(Linked) { |
421 for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); | 423 for (VarList::const_iterator I = KilledRegs.begin(), E = KilledRegs.end(); |
422 I != E; ++I) { | 424 I != E; ++I) { |
423 Variable *Var = *I; | 425 Variable *Var = *I; |
424 addSource(Var); | 426 addSource(Var); |
425 } | 427 } |
426 } | 428 } |
427 | 429 |
428 // ======================== Dump routines ======================== // | 430 // ======================== Dump routines ======================== // |
429 | 431 |
430 void Inst::dumpDecorated(const Cfg *Func) const { | 432 void Inst::dumpDecorated(const Cfg *Func) const { |
(...skipping 11 matching lines...) Expand all Loading... |
442 Str << buf; | 444 Str << buf; |
443 } | 445 } |
444 Str << " "; | 446 Str << " "; |
445 if (isDeleted()) | 447 if (isDeleted()) |
446 Str << " //"; | 448 Str << " //"; |
447 dump(Func); | 449 dump(Func); |
448 dumpExtras(Func); | 450 dumpExtras(Func); |
449 Str << "\n"; | 451 Str << "\n"; |
450 } | 452 } |
451 | 453 |
452 void Inst::emit(const Cfg * /*Func*/) const { | |
453 llvm_unreachable("emit() called on a non-lowered instruction"); | |
454 } | |
455 | |
456 void Inst::emitIAS(const Cfg *Func) const { emit(Func); } | |
457 | |
458 void Inst::dump(const Cfg *Func) const { | 454 void Inst::dump(const Cfg *Func) const { |
459 Ostream &Str = Func->getContext()->getStrDump(); | 455 Ostream &Str = Func->getContext()->getStrDump(); |
460 dumpDest(Func); | 456 dumpDest(Func); |
461 Str << " =~ "; | 457 Str << " =~ "; |
462 dumpSources(Func); | 458 dumpSources(Func); |
463 } | 459 } |
464 | 460 |
465 void Inst::dumpExtras(const Cfg *Func) const { | 461 void Inst::dumpExtras(const Cfg *Func) const { |
466 Ostream &Str = Func->getContext()->getStrDump(); | 462 Ostream &Str = Func->getContext()->getStrDump(); |
467 bool First = true; | 463 bool First = true; |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
747 Str << "kill.pseudo "; | 743 Str << "kill.pseudo "; |
748 dumpSources(Func); | 744 dumpSources(Func); |
749 } | 745 } |
750 | 746 |
751 void InstTarget::dump(const Cfg *Func) const { | 747 void InstTarget::dump(const Cfg *Func) const { |
752 Ostream &Str = Func->getContext()->getStrDump(); | 748 Ostream &Str = Func->getContext()->getStrDump(); |
753 Str << "[TARGET] "; | 749 Str << "[TARGET] "; |
754 Inst::dump(Func); | 750 Inst::dump(Func); |
755 } | 751 } |
756 | 752 |
757 void InstTarget::dumpExtras(const Cfg *Func) const { Inst::dumpExtras(Func); } | |
758 | |
759 } // end of namespace Ice | 753 } // end of namespace Ice |
OLD | NEW |