| 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 |