OLD | NEW |
1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// | 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// |
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 declares the Inst class and its target-independent | 10 // This file declares the Inst class and its target-independent |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
223 // Alloca instruction. This captures the size in bytes as getSrc(0), | 223 // Alloca instruction. This captures the size in bytes as getSrc(0), |
224 // and the required alignment in bytes. The alignment must be either | 224 // and the required alignment in bytes. The alignment must be either |
225 // 0 (no alignment required) or a power of 2. | 225 // 0 (no alignment required) or a power of 2. |
226 class InstAlloca : public InstHighLevel { | 226 class InstAlloca : public InstHighLevel { |
227 InstAlloca(const InstAlloca &) = delete; | 227 InstAlloca(const InstAlloca &) = delete; |
228 InstAlloca &operator=(const InstAlloca &) = delete; | 228 InstAlloca &operator=(const InstAlloca &) = delete; |
229 | 229 |
230 public: | 230 public: |
231 static InstAlloca *create(Cfg *Func, Operand *ByteCount, | 231 static InstAlloca *create(Cfg *Func, Operand *ByteCount, |
232 uint32_t AlignInBytes, Variable *Dest) { | 232 uint32_t AlignInBytes, Variable *Dest) { |
233 return new (Func->allocateInst<InstAlloca>()) | 233 return new (Func->allocate<InstAlloca>()) |
234 InstAlloca(Func, ByteCount, AlignInBytes, Dest); | 234 InstAlloca(Func, ByteCount, AlignInBytes, Dest); |
235 } | 235 } |
236 uint32_t getAlignInBytes() const { return AlignInBytes; } | 236 uint32_t getAlignInBytes() const { return AlignInBytes; } |
237 Operand *getSizeInBytes() const { return getSrc(0); } | 237 Operand *getSizeInBytes() const { return getSrc(0); } |
238 void dump(const Cfg *Func) const override; | 238 void dump(const Cfg *Func) const override; |
239 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } | 239 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } |
240 | 240 |
241 private: | 241 private: |
242 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 242 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
243 Variable *Dest); | 243 Variable *Dest); |
(...skipping 10 matching lines...) Expand all Loading... |
254 public: | 254 public: |
255 enum OpKind { | 255 enum OpKind { |
256 #define X(tag, str, commutative) tag, | 256 #define X(tag, str, commutative) tag, |
257 ICEINSTARITHMETIC_TABLE | 257 ICEINSTARITHMETIC_TABLE |
258 #undef X | 258 #undef X |
259 _num | 259 _num |
260 }; | 260 }; |
261 | 261 |
262 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, | 262 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, |
263 Operand *Source1, Operand *Source2) { | 263 Operand *Source1, Operand *Source2) { |
264 return new (Func->allocateInst<InstArithmetic>()) | 264 return new (Func->allocate<InstArithmetic>()) |
265 InstArithmetic(Func, Op, Dest, Source1, Source2); | 265 InstArithmetic(Func, Op, Dest, Source1, Source2); |
266 } | 266 } |
267 OpKind getOp() const { return Op; } | 267 OpKind getOp() const { return Op; } |
268 static const char *getOpName(OpKind Op); | 268 static const char *getOpName(OpKind Op); |
269 bool isCommutative() const; | 269 bool isCommutative() const; |
270 void dump(const Cfg *Func) const override; | 270 void dump(const Cfg *Func) const override; |
271 static bool classof(const Inst *Inst) { | 271 static bool classof(const Inst *Inst) { |
272 return Inst->getKind() == Arithmetic; | 272 return Inst->getKind() == Arithmetic; |
273 } | 273 } |
274 | 274 |
(...skipping 10 matching lines...) Expand all Loading... |
285 // abstraction for some of the lowering. E.g., if Phi instruction | 285 // abstraction for some of the lowering. E.g., if Phi instruction |
286 // lowering happens before target lowering, or for representing an | 286 // lowering happens before target lowering, or for representing an |
287 // Inttoptr instruction, or as an intermediate step for lowering a | 287 // Inttoptr instruction, or as an intermediate step for lowering a |
288 // Load instruction. | 288 // Load instruction. |
289 class InstAssign : public InstHighLevel { | 289 class InstAssign : public InstHighLevel { |
290 InstAssign(const InstAssign &) = delete; | 290 InstAssign(const InstAssign &) = delete; |
291 InstAssign &operator=(const InstAssign &) = delete; | 291 InstAssign &operator=(const InstAssign &) = delete; |
292 | 292 |
293 public: | 293 public: |
294 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 294 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
295 return new (Func->allocateInst<InstAssign>()) | 295 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
296 InstAssign(Func, Dest, Source); | |
297 } | 296 } |
298 bool isSimpleAssign() const override { return true; } | 297 bool isSimpleAssign() const override { return true; } |
299 void dump(const Cfg *Func) const override; | 298 void dump(const Cfg *Func) const override; |
300 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } | 299 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } |
301 | 300 |
302 private: | 301 private: |
303 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 302 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
304 ~InstAssign() override {} | 303 ~InstAssign() override {} |
305 }; | 304 }; |
306 | 305 |
307 // Branch instruction. This represents both conditional and | 306 // Branch instruction. This represents both conditional and |
308 // unconditional branches. | 307 // unconditional branches. |
309 class InstBr : public InstHighLevel { | 308 class InstBr : public InstHighLevel { |
310 InstBr(const InstBr &) = delete; | 309 InstBr(const InstBr &) = delete; |
311 InstBr &operator=(const InstBr &) = delete; | 310 InstBr &operator=(const InstBr &) = delete; |
312 | 311 |
313 public: | 312 public: |
314 // Create a conditional branch. If TargetTrue==TargetFalse, it is | 313 // Create a conditional branch. If TargetTrue==TargetFalse, it is |
315 // optimized to an unconditional branch. | 314 // optimized to an unconditional branch. |
316 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 315 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |
317 CfgNode *TargetFalse) { | 316 CfgNode *TargetFalse) { |
318 return new (Func->allocateInst<InstBr>()) | 317 return new (Func->allocate<InstBr>()) |
319 InstBr(Func, Source, TargetTrue, TargetFalse); | 318 InstBr(Func, Source, TargetTrue, TargetFalse); |
320 } | 319 } |
321 // Create an unconditional branch. | 320 // Create an unconditional branch. |
322 static InstBr *create(Cfg *Func, CfgNode *Target) { | 321 static InstBr *create(Cfg *Func, CfgNode *Target) { |
323 return new (Func->allocateInst<InstBr>()) InstBr(Func, Target); | 322 return new (Func->allocate<InstBr>()) InstBr(Func, Target); |
324 } | 323 } |
325 bool isUnconditional() const { return getTargetTrue() == NULL; } | 324 bool isUnconditional() const { return getTargetTrue() == NULL; } |
326 Operand *getCondition() const { | 325 Operand *getCondition() const { |
327 assert(!isUnconditional()); | 326 assert(!isUnconditional()); |
328 return getSrc(0); | 327 return getSrc(0); |
329 } | 328 } |
330 CfgNode *getTargetTrue() const { return TargetTrue; } | 329 CfgNode *getTargetTrue() const { return TargetTrue; } |
331 CfgNode *getTargetFalse() const { return TargetFalse; } | 330 CfgNode *getTargetFalse() const { return TargetFalse; } |
332 CfgNode *getTargetUnconditional() const { | 331 CfgNode *getTargetUnconditional() const { |
333 assert(isUnconditional()); | 332 assert(isUnconditional()); |
(...skipping 23 matching lines...) Expand all Loading... |
357 InstCall &operator=(const InstCall &) = delete; | 356 InstCall &operator=(const InstCall &) = delete; |
358 | 357 |
359 public: | 358 public: |
360 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 359 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
361 Operand *CallTarget, bool HasTailCall) { | 360 Operand *CallTarget, bool HasTailCall) { |
362 // Set HasSideEffects to true so that the call instruction can't be | 361 // Set HasSideEffects to true so that the call instruction can't be |
363 // dead-code eliminated. IntrinsicCalls can override this if the | 362 // dead-code eliminated. IntrinsicCalls can override this if the |
364 // particular intrinsic is deletable and has no side-effects. | 363 // particular intrinsic is deletable and has no side-effects. |
365 const bool HasSideEffects = true; | 364 const bool HasSideEffects = true; |
366 const InstKind Kind = Inst::Call; | 365 const InstKind Kind = Inst::Call; |
367 return new (Func->allocateInst<InstCall>()) InstCall( | 366 return new (Func->allocate<InstCall>()) InstCall( |
368 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); | 367 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); |
369 } | 368 } |
370 void addArg(Operand *Arg) { addSource(Arg); } | 369 void addArg(Operand *Arg) { addSource(Arg); } |
371 Operand *getCallTarget() const { return getSrc(0); } | 370 Operand *getCallTarget() const { return getSrc(0); } |
372 Operand *getArg(SizeT I) const { return getSrc(I + 1); } | 371 Operand *getArg(SizeT I) const { return getSrc(I + 1); } |
373 SizeT getNumArgs() const { return getSrcSize() - 1; } | 372 SizeT getNumArgs() const { return getSrcSize() - 1; } |
374 bool isTailcall() const { return HasTailCall; } | 373 bool isTailcall() const { return HasTailCall; } |
375 void dump(const Cfg *Func) const; | 374 void dump(const Cfg *Func) const; |
376 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } | 375 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } |
377 Type getReturnType() const; | 376 Type getReturnType() const; |
(...skipping 21 matching lines...) Expand all Loading... |
399 #define X(tag, str) tag, | 398 #define X(tag, str) tag, |
400 ICEINSTCAST_TABLE | 399 ICEINSTCAST_TABLE |
401 #undef X | 400 #undef X |
402 _num | 401 _num |
403 }; | 402 }; |
404 | 403 |
405 static const char *getCastName(OpKind Kind); | 404 static const char *getCastName(OpKind Kind); |
406 | 405 |
407 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, | 406 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
408 Operand *Source) { | 407 Operand *Source) { |
409 return new (Func->allocateInst<InstCast>()) | 408 return new (Func->allocate<InstCast>()) |
410 InstCast(Func, CastKind, Dest, Source); | 409 InstCast(Func, CastKind, Dest, Source); |
411 } | 410 } |
412 OpKind getCastKind() const { return CastKind; } | 411 OpKind getCastKind() const { return CastKind; } |
413 void dump(const Cfg *Func) const override; | 412 void dump(const Cfg *Func) const override; |
414 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 413 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } |
415 | 414 |
416 private: | 415 private: |
417 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 416 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
418 ~InstCast() override {} | 417 ~InstCast() override {} |
419 const OpKind CastKind; | 418 const OpKind CastKind; |
420 }; | 419 }; |
421 | 420 |
422 // ExtractElement instruction. | 421 // ExtractElement instruction. |
423 class InstExtractElement : public InstHighLevel { | 422 class InstExtractElement : public InstHighLevel { |
424 InstExtractElement(const InstExtractElement &) = delete; | 423 InstExtractElement(const InstExtractElement &) = delete; |
425 InstExtractElement &operator=(const InstExtractElement &) = delete; | 424 InstExtractElement &operator=(const InstExtractElement &) = delete; |
426 | 425 |
427 public: | 426 public: |
428 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 427 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
429 Operand *Source2) { | 428 Operand *Source2) { |
430 return new (Func->allocateInst<InstExtractElement>()) | 429 return new (Func->allocate<InstExtractElement>()) |
431 InstExtractElement(Func, Dest, Source1, Source2); | 430 InstExtractElement(Func, Dest, Source1, Source2); |
432 } | 431 } |
433 | 432 |
434 void dump(const Cfg *Func) const override; | 433 void dump(const Cfg *Func) const override; |
435 static bool classof(const Inst *Inst) { | 434 static bool classof(const Inst *Inst) { |
436 return Inst->getKind() == ExtractElement; | 435 return Inst->getKind() == ExtractElement; |
437 } | 436 } |
438 | 437 |
439 private: | 438 private: |
440 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 439 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
(...skipping 10 matching lines...) Expand all Loading... |
451 public: | 450 public: |
452 enum FCond { | 451 enum FCond { |
453 #define X(tag, str) tag, | 452 #define X(tag, str) tag, |
454 ICEINSTFCMP_TABLE | 453 ICEINSTFCMP_TABLE |
455 #undef X | 454 #undef X |
456 _num | 455 _num |
457 }; | 456 }; |
458 | 457 |
459 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 458 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
460 Operand *Source1, Operand *Source2) { | 459 Operand *Source1, Operand *Source2) { |
461 return new (Func->allocateInst<InstFcmp>()) | 460 return new (Func->allocate<InstFcmp>()) |
462 InstFcmp(Func, Condition, Dest, Source1, Source2); | 461 InstFcmp(Func, Condition, Dest, Source1, Source2); |
463 } | 462 } |
464 FCond getCondition() const { return Condition; } | 463 FCond getCondition() const { return Condition; } |
465 void dump(const Cfg *Func) const override; | 464 void dump(const Cfg *Func) const override; |
466 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } | 465 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } |
467 | 466 |
468 private: | 467 private: |
469 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 468 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
470 Operand *Source2); | 469 Operand *Source2); |
471 ~InstFcmp() override {} | 470 ~InstFcmp() override {} |
472 const FCond Condition; | 471 const FCond Condition; |
473 }; | 472 }; |
474 | 473 |
475 // Integer comparison instruction. The source operands are captured | 474 // Integer comparison instruction. The source operands are captured |
476 // in getSrc(0) and getSrc(1). | 475 // in getSrc(0) and getSrc(1). |
477 class InstIcmp : public InstHighLevel { | 476 class InstIcmp : public InstHighLevel { |
478 InstIcmp(const InstIcmp &) = delete; | 477 InstIcmp(const InstIcmp &) = delete; |
479 InstIcmp &operator=(const InstIcmp &) = delete; | 478 InstIcmp &operator=(const InstIcmp &) = delete; |
480 | 479 |
481 public: | 480 public: |
482 enum ICond { | 481 enum ICond { |
483 #define X(tag, str) tag, | 482 #define X(tag, str) tag, |
484 ICEINSTICMP_TABLE | 483 ICEINSTICMP_TABLE |
485 #undef X | 484 #undef X |
486 _num | 485 _num |
487 }; | 486 }; |
488 | 487 |
489 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 488 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
490 Operand *Source1, Operand *Source2) { | 489 Operand *Source1, Operand *Source2) { |
491 return new (Func->allocateInst<InstIcmp>()) | 490 return new (Func->allocate<InstIcmp>()) |
492 InstIcmp(Func, Condition, Dest, Source1, Source2); | 491 InstIcmp(Func, Condition, Dest, Source1, Source2); |
493 } | 492 } |
494 ICond getCondition() const { return Condition; } | 493 ICond getCondition() const { return Condition; } |
495 void dump(const Cfg *Func) const override; | 494 void dump(const Cfg *Func) const override; |
496 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 495 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } |
497 | 496 |
498 private: | 497 private: |
499 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 498 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
500 Operand *Source2); | 499 Operand *Source2); |
501 ~InstIcmp() override {} | 500 ~InstIcmp() override {} |
502 const ICond Condition; | 501 const ICond Condition; |
503 }; | 502 }; |
504 | 503 |
505 // InsertElement instruction. | 504 // InsertElement instruction. |
506 class InstInsertElement : public InstHighLevel { | 505 class InstInsertElement : public InstHighLevel { |
507 InstInsertElement(const InstInsertElement &) = delete; | 506 InstInsertElement(const InstInsertElement &) = delete; |
508 InstInsertElement &operator=(const InstInsertElement &) = delete; | 507 InstInsertElement &operator=(const InstInsertElement &) = delete; |
509 | 508 |
510 public: | 509 public: |
511 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 510 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
512 Operand *Source2, Operand *Source3) { | 511 Operand *Source2, Operand *Source3) { |
513 return new (Func->allocateInst<InstInsertElement>()) | 512 return new (Func->allocate<InstInsertElement>()) |
514 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 513 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
515 } | 514 } |
516 | 515 |
517 void dump(const Cfg *Func) const override; | 516 void dump(const Cfg *Func) const override; |
518 static bool classof(const Inst *Inst) { | 517 static bool classof(const Inst *Inst) { |
519 return Inst->getKind() == InsertElement; | 518 return Inst->getKind() == InsertElement; |
520 } | 519 } |
521 | 520 |
522 private: | 521 private: |
523 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 522 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
524 Operand *Source2, Operand *Source3); | 523 Operand *Source2, Operand *Source3); |
525 ~InstInsertElement() override {} | 524 ~InstInsertElement() override {} |
526 }; | 525 }; |
527 | 526 |
528 // Call to an intrinsic function. The call target is captured as getSrc(0), | 527 // Call to an intrinsic function. The call target is captured as getSrc(0), |
529 // and arg I is captured as getSrc(I+1). | 528 // and arg I is captured as getSrc(I+1). |
530 class InstIntrinsicCall : public InstCall { | 529 class InstIntrinsicCall : public InstCall { |
531 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | 530 InstIntrinsicCall(const InstIntrinsicCall &) = delete; |
532 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | 531 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; |
533 | 532 |
534 public: | 533 public: |
535 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 534 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
536 Operand *CallTarget, | 535 Operand *CallTarget, |
537 const Intrinsics::IntrinsicInfo &Info) { | 536 const Intrinsics::IntrinsicInfo &Info) { |
538 return new (Func->allocateInst<InstIntrinsicCall>()) | 537 return new (Func->allocate<InstIntrinsicCall>()) |
539 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 538 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
540 } | 539 } |
541 static bool classof(const Inst *Inst) { | 540 static bool classof(const Inst *Inst) { |
542 return Inst->getKind() == IntrinsicCall; | 541 return Inst->getKind() == IntrinsicCall; |
543 } | 542 } |
544 | 543 |
545 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 544 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
546 | 545 |
547 private: | 546 private: |
548 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 547 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
549 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 548 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
550 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, | 549 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, |
551 Inst::IntrinsicCall), | 550 Inst::IntrinsicCall), |
552 Info(Info) {} | 551 Info(Info) {} |
553 ~InstIntrinsicCall() override {} | 552 ~InstIntrinsicCall() override {} |
554 const Intrinsics::IntrinsicInfo Info; | 553 const Intrinsics::IntrinsicInfo Info; |
555 }; | 554 }; |
556 | 555 |
557 // Load instruction. The source address is captured in getSrc(0). | 556 // Load instruction. The source address is captured in getSrc(0). |
558 class InstLoad : public InstHighLevel { | 557 class InstLoad : public InstHighLevel { |
559 InstLoad(const InstLoad &) = delete; | 558 InstLoad(const InstLoad &) = delete; |
560 InstLoad &operator=(const InstLoad &) = delete; | 559 InstLoad &operator=(const InstLoad &) = delete; |
561 | 560 |
562 public: | 561 public: |
563 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 562 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
564 uint32_t Align = 1) { | 563 uint32_t Align = 1) { |
565 // TODO(kschimpf) Stop ignoring alignment specification. | 564 // TODO(kschimpf) Stop ignoring alignment specification. |
566 (void)Align; | 565 (void)Align; |
567 return new (Func->allocateInst<InstLoad>()) | 566 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
568 InstLoad(Func, Dest, SourceAddr); | |
569 } | 567 } |
570 Operand *getSourceAddress() const { return getSrc(0); } | 568 Operand *getSourceAddress() const { return getSrc(0); } |
571 void dump(const Cfg *Func) const override; | 569 void dump(const Cfg *Func) const override; |
572 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } | 570 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } |
573 | 571 |
574 private: | 572 private: |
575 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 573 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
576 ~InstLoad() override {} | 574 ~InstLoad() override {} |
577 }; | 575 }; |
578 | 576 |
579 // Phi instruction. For incoming edge I, the node is Labels[I] and | 577 // Phi instruction. For incoming edge I, the node is Labels[I] and |
580 // the Phi source operand is getSrc(I). | 578 // the Phi source operand is getSrc(I). |
581 class InstPhi : public InstHighLevel { | 579 class InstPhi : public InstHighLevel { |
582 InstPhi(const InstPhi &) = delete; | 580 InstPhi(const InstPhi &) = delete; |
583 InstPhi &operator=(const InstPhi &) = delete; | 581 InstPhi &operator=(const InstPhi &) = delete; |
584 | 582 |
585 public: | 583 public: |
586 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 584 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
587 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 585 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
588 } | 586 } |
589 void addArgument(Operand *Source, CfgNode *Label); | 587 void addArgument(Operand *Source, CfgNode *Label); |
590 Operand *getOperandForTarget(CfgNode *Target) const; | 588 Operand *getOperandForTarget(CfgNode *Target) const; |
591 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } | 589 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } |
592 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 590 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
593 Liveness *Liveness); | 591 Liveness *Liveness); |
594 Inst *lower(Cfg *Func); | 592 Inst *lower(Cfg *Func); |
595 void dump(const Cfg *Func) const override; | 593 void dump(const Cfg *Func) const override; |
596 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } | 594 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } |
597 | 595 |
(...skipping 13 matching lines...) Expand all Loading... |
611 | 609 |
612 // Ret instruction. The return value is captured in getSrc(0), but if | 610 // Ret instruction. The return value is captured in getSrc(0), but if |
613 // there is no return value (void-type function), then | 611 // there is no return value (void-type function), then |
614 // getSrcSize()==0 and hasRetValue()==false. | 612 // getSrcSize()==0 and hasRetValue()==false. |
615 class InstRet : public InstHighLevel { | 613 class InstRet : public InstHighLevel { |
616 InstRet(const InstRet &) = delete; | 614 InstRet(const InstRet &) = delete; |
617 InstRet &operator=(const InstRet &) = delete; | 615 InstRet &operator=(const InstRet &) = delete; |
618 | 616 |
619 public: | 617 public: |
620 static InstRet *create(Cfg *Func, Operand *RetValue = NULL) { | 618 static InstRet *create(Cfg *Func, Operand *RetValue = NULL) { |
621 return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue); | 619 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); |
622 } | 620 } |
623 bool hasRetValue() const { return getSrcSize(); } | 621 bool hasRetValue() const { return getSrcSize(); } |
624 Operand *getRetValue() const { | 622 Operand *getRetValue() const { |
625 assert(hasRetValue()); | 623 assert(hasRetValue()); |
626 return getSrc(0); | 624 return getSrc(0); |
627 } | 625 } |
628 NodeList getTerminatorEdges() const override { return NodeList(); } | 626 NodeList getTerminatorEdges() const override { return NodeList(); } |
629 void dump(const Cfg *Func) const override; | 627 void dump(const Cfg *Func) const override; |
630 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } | 628 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } |
631 | 629 |
632 private: | 630 private: |
633 InstRet(Cfg *Func, Operand *RetValue); | 631 InstRet(Cfg *Func, Operand *RetValue); |
634 ~InstRet() override {} | 632 ~InstRet() override {} |
635 }; | 633 }; |
636 | 634 |
637 // Select instruction. The condition, true, and false operands are captured. | 635 // Select instruction. The condition, true, and false operands are captured. |
638 class InstSelect : public InstHighLevel { | 636 class InstSelect : public InstHighLevel { |
639 InstSelect(const InstSelect &) = delete; | 637 InstSelect(const InstSelect &) = delete; |
640 InstSelect &operator=(const InstSelect &) = delete; | 638 InstSelect &operator=(const InstSelect &) = delete; |
641 | 639 |
642 public: | 640 public: |
643 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 641 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
644 Operand *SourceTrue, Operand *SourceFalse) { | 642 Operand *SourceTrue, Operand *SourceFalse) { |
645 return new (Func->allocateInst<InstSelect>()) | 643 return new (Func->allocate<InstSelect>()) |
646 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 644 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
647 } | 645 } |
648 Operand *getCondition() const { return getSrc(0); } | 646 Operand *getCondition() const { return getSrc(0); } |
649 Operand *getTrueOperand() const { return getSrc(1); } | 647 Operand *getTrueOperand() const { return getSrc(1); } |
650 Operand *getFalseOperand() const { return getSrc(2); } | 648 Operand *getFalseOperand() const { return getSrc(2); } |
651 void dump(const Cfg *Func) const override; | 649 void dump(const Cfg *Func) const override; |
652 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } | 650 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } |
653 | 651 |
654 private: | 652 private: |
655 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 653 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
656 Operand *Source2); | 654 Operand *Source2); |
657 ~InstSelect() override {} | 655 ~InstSelect() override {} |
658 }; | 656 }; |
659 | 657 |
660 // Store instruction. The address operand is captured, along with the | 658 // Store instruction. The address operand is captured, along with the |
661 // data operand to be stored into the address. | 659 // data operand to be stored into the address. |
662 class InstStore : public InstHighLevel { | 660 class InstStore : public InstHighLevel { |
663 InstStore(const InstStore &) = delete; | 661 InstStore(const InstStore &) = delete; |
664 InstStore &operator=(const InstStore &) = delete; | 662 InstStore &operator=(const InstStore &) = delete; |
665 | 663 |
666 public: | 664 public: |
667 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, | 665 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, |
668 uint32_t align = 1) { | 666 uint32_t align = 1) { |
669 // TODO(kschimpf) Stop ignoring alignment specification. | 667 // TODO(kschimpf) Stop ignoring alignment specification. |
670 (void)align; | 668 (void)align; |
671 return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr); | 669 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); |
672 } | 670 } |
673 Operand *getAddr() const { return getSrc(1); } | 671 Operand *getAddr() const { return getSrc(1); } |
674 Operand *getData() const { return getSrc(0); } | 672 Operand *getData() const { return getSrc(0); } |
675 void dump(const Cfg *Func) const override; | 673 void dump(const Cfg *Func) const override; |
676 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } | 674 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } |
677 | 675 |
678 private: | 676 private: |
679 InstStore(Cfg *Func, Operand *Data, Operand *Addr); | 677 InstStore(Cfg *Func, Operand *Data, Operand *Addr); |
680 ~InstStore() override {} | 678 ~InstStore() override {} |
681 }; | 679 }; |
682 | 680 |
683 // Switch instruction. The single source operand is captured as | 681 // Switch instruction. The single source operand is captured as |
684 // getSrc(0). | 682 // getSrc(0). |
685 class InstSwitch : public InstHighLevel { | 683 class InstSwitch : public InstHighLevel { |
686 InstSwitch(const InstSwitch &) = delete; | 684 InstSwitch(const InstSwitch &) = delete; |
687 InstSwitch &operator=(const InstSwitch &) = delete; | 685 InstSwitch &operator=(const InstSwitch &) = delete; |
688 | 686 |
689 public: | 687 public: |
690 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, | 688 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, |
691 CfgNode *LabelDefault) { | 689 CfgNode *LabelDefault) { |
692 return new (Func->allocateInst<InstSwitch>()) | 690 return new (Func->allocate<InstSwitch>()) |
693 InstSwitch(Func, NumCases, Source, LabelDefault); | 691 InstSwitch(Func, NumCases, Source, LabelDefault); |
694 } | 692 } |
695 Operand *getComparison() const { return getSrc(0); } | 693 Operand *getComparison() const { return getSrc(0); } |
696 CfgNode *getLabelDefault() const { return LabelDefault; } | 694 CfgNode *getLabelDefault() const { return LabelDefault; } |
697 SizeT getNumCases() const { return NumCases; } | 695 SizeT getNumCases() const { return NumCases; } |
698 uint64_t getValue(SizeT I) const { | 696 uint64_t getValue(SizeT I) const { |
699 assert(I < NumCases); | 697 assert(I < NumCases); |
700 return Values[I]; | 698 return Values[I]; |
701 } | 699 } |
702 CfgNode *getLabel(SizeT I) const { | 700 CfgNode *getLabel(SizeT I) const { |
(...skipping 22 matching lines...) Expand all Loading... |
725 }; | 723 }; |
726 | 724 |
727 // Unreachable instruction. This is a terminator instruction with no | 725 // Unreachable instruction. This is a terminator instruction with no |
728 // operands. | 726 // operands. |
729 class InstUnreachable : public InstHighLevel { | 727 class InstUnreachable : public InstHighLevel { |
730 InstUnreachable(const InstUnreachable &) = delete; | 728 InstUnreachable(const InstUnreachable &) = delete; |
731 InstUnreachable &operator=(const InstUnreachable &) = delete; | 729 InstUnreachable &operator=(const InstUnreachable &) = delete; |
732 | 730 |
733 public: | 731 public: |
734 static InstUnreachable *create(Cfg *Func) { | 732 static InstUnreachable *create(Cfg *Func) { |
735 return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func); | 733 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
736 } | 734 } |
737 NodeList getTerminatorEdges() const override { return NodeList(); } | 735 NodeList getTerminatorEdges() const override { return NodeList(); } |
738 void dump(const Cfg *Func) const override; | 736 void dump(const Cfg *Func) const override; |
739 static bool classof(const Inst *Inst) { | 737 static bool classof(const Inst *Inst) { |
740 return Inst->getKind() == Unreachable; | 738 return Inst->getKind() == Unreachable; |
741 } | 739 } |
742 | 740 |
743 private: | 741 private: |
744 InstUnreachable(Cfg *Func); | 742 InstUnreachable(Cfg *Func); |
745 ~InstUnreachable() override {} | 743 ~InstUnreachable() override {} |
(...skipping 10 matching lines...) Expand all Loading... |
756 // dest variable of the instruction that actually produces the FakeDef | 754 // dest variable of the instruction that actually produces the FakeDef |
757 // dest. Otherwise, the original instruction could be dead-code | 755 // dest. Otherwise, the original instruction could be dead-code |
758 // eliminated if its dest operand is unused, and therefore the FakeDef | 756 // eliminated if its dest operand is unused, and therefore the FakeDef |
759 // dest wouldn't be properly initialized. | 757 // dest wouldn't be properly initialized. |
760 class InstFakeDef : public InstHighLevel { | 758 class InstFakeDef : public InstHighLevel { |
761 InstFakeDef(const InstFakeDef &) = delete; | 759 InstFakeDef(const InstFakeDef &) = delete; |
762 InstFakeDef &operator=(const InstFakeDef &) = delete; | 760 InstFakeDef &operator=(const InstFakeDef &) = delete; |
763 | 761 |
764 public: | 762 public: |
765 static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { | 763 static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { |
766 return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 764 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
767 } | 765 } |
768 void emit(const Cfg *Func) const override; | 766 void emit(const Cfg *Func) const override; |
769 void emitIAS(const Cfg * /* Func */) const override {} | 767 void emitIAS(const Cfg * /* Func */) const override {} |
770 void dump(const Cfg *Func) const override; | 768 void dump(const Cfg *Func) const override; |
771 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } | 769 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
772 | 770 |
773 private: | 771 private: |
774 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 772 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
775 ~InstFakeDef() override {} | 773 ~InstFakeDef() override {} |
776 }; | 774 }; |
777 | 775 |
778 // FakeUse instruction. This creates a fake use of a variable, to | 776 // FakeUse instruction. This creates a fake use of a variable, to |
779 // keep the instruction that produces that variable from being | 777 // keep the instruction that produces that variable from being |
780 // dead-code eliminated. This is useful in a variety of lowering | 778 // dead-code eliminated. This is useful in a variety of lowering |
781 // situations. The FakeUse instruction has no dest, so it can itself | 779 // situations. The FakeUse instruction has no dest, so it can itself |
782 // never be dead-code eliminated. | 780 // never be dead-code eliminated. |
783 class InstFakeUse : public InstHighLevel { | 781 class InstFakeUse : public InstHighLevel { |
784 InstFakeUse(const InstFakeUse &) = delete; | 782 InstFakeUse(const InstFakeUse &) = delete; |
785 InstFakeUse &operator=(const InstFakeUse &) = delete; | 783 InstFakeUse &operator=(const InstFakeUse &) = delete; |
786 | 784 |
787 public: | 785 public: |
788 static InstFakeUse *create(Cfg *Func, Variable *Src) { | 786 static InstFakeUse *create(Cfg *Func, Variable *Src) { |
789 return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); | 787 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); |
790 } | 788 } |
791 void emit(const Cfg *Func) const override; | 789 void emit(const Cfg *Func) const override; |
792 void emitIAS(const Cfg * /* Func */) const override {} | 790 void emitIAS(const Cfg * /* Func */) const override {} |
793 void dump(const Cfg *Func) const override; | 791 void dump(const Cfg *Func) const override; |
794 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } | 792 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
795 | 793 |
796 private: | 794 private: |
797 InstFakeUse(Cfg *Func, Variable *Src); | 795 InstFakeUse(Cfg *Func, Variable *Src); |
798 ~InstFakeUse() override {} | 796 ~InstFakeUse() override {} |
799 }; | 797 }; |
800 | 798 |
801 // FakeKill instruction. This "kills" a set of variables by modeling | 799 // FakeKill instruction. This "kills" a set of variables by modeling |
802 // a trivial live range at this instruction for each (implicit) | 800 // a trivial live range at this instruction for each (implicit) |
803 // variable. The primary use is to indicate that scratch registers | 801 // variable. The primary use is to indicate that scratch registers |
804 // are killed after a call, so that the register allocator won't | 802 // are killed after a call, so that the register allocator won't |
805 // assign a scratch register to a variable whose live range spans a | 803 // assign a scratch register to a variable whose live range spans a |
806 // call. | 804 // call. |
807 // | 805 // |
808 // The FakeKill instruction also holds a pointer to the instruction | 806 // The FakeKill instruction also holds a pointer to the instruction |
809 // that kills the set of variables, so that if that linked instruction | 807 // that kills the set of variables, so that if that linked instruction |
810 // gets dead-code eliminated, the FakeKill instruction will as well. | 808 // gets dead-code eliminated, the FakeKill instruction will as well. |
811 class InstFakeKill : public InstHighLevel { | 809 class InstFakeKill : public InstHighLevel { |
812 InstFakeKill(const InstFakeKill &) = delete; | 810 InstFakeKill(const InstFakeKill &) = delete; |
813 InstFakeKill &operator=(const InstFakeKill &) = delete; | 811 InstFakeKill &operator=(const InstFakeKill &) = delete; |
814 | 812 |
815 public: | 813 public: |
816 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { | 814 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { |
817 return new (Func->allocateInst<InstFakeKill>()) InstFakeKill(Func, Linked); | 815 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); |
818 } | 816 } |
819 const Inst *getLinked() const { return Linked; } | 817 const Inst *getLinked() const { return Linked; } |
820 void emit(const Cfg *Func) const override; | 818 void emit(const Cfg *Func) const override; |
821 void emitIAS(const Cfg * /* Func */) const override {} | 819 void emitIAS(const Cfg * /* Func */) const override {} |
822 void dump(const Cfg *Func) const override; | 820 void dump(const Cfg *Func) const override; |
823 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } | 821 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
824 | 822 |
825 private: | 823 private: |
826 InstFakeKill(Cfg *Func, const Inst *Linked); | 824 InstFakeKill(Cfg *Func, const Inst *Linked); |
827 ~InstFakeKill() override {} | 825 ~InstFakeKill() override {} |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 864 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
867 void deleteNode(Ice::Inst *) {} | 865 void deleteNode(Ice::Inst *) {} |
868 | 866 |
869 private: | 867 private: |
870 mutable ilist_half_node<Ice::Inst> Sentinel; | 868 mutable ilist_half_node<Ice::Inst> Sentinel; |
871 }; | 869 }; |
872 | 870 |
873 } // end of namespace llvm | 871 } // end of namespace llvm |
874 | 872 |
875 #endif // SUBZERO_SRC_ICEINST_H | 873 #endif // SUBZERO_SRC_ICEINST_H |
OLD | NEW |