| 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 154 } | 154 } |
| 155 virtual void emitIAS(const Cfg *Func) const { emit(Func); } | 155 virtual void emitIAS(const Cfg *Func) const { emit(Func); } |
| 156 virtual void dump(const Cfg *Func) const; | 156 virtual void dump(const Cfg *Func) const; |
| 157 virtual void dumpExtras(const Cfg *Func) const; | 157 virtual void dumpExtras(const Cfg *Func) const; |
| 158 void dumpDecorated(const Cfg *Func) const; | 158 void dumpDecorated(const Cfg *Func) const; |
| 159 void emitSources(const Cfg *Func) const; | 159 void emitSources(const Cfg *Func) const; |
| 160 void dumpSources(const Cfg *Func) const; | 160 void dumpSources(const Cfg *Func) const; |
| 161 void dumpDest(const Cfg *Func) const; | 161 void dumpDest(const Cfg *Func) const; |
| 162 virtual bool isRedundantAssign() const { return false; } | 162 virtual bool isRedundantAssign() const { return false; } |
| 163 | 163 |
| 164 virtual ~Inst() {} | |
| 165 | |
| 166 protected: | 164 protected: |
| 167 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); | 165 Inst(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest); |
| 168 void addSource(Operand *Src) { | 166 void addSource(Operand *Src) { |
| 169 assert(Src); | 167 assert(Src); |
| 170 assert(NumSrcs < MaxSrcs); | 168 assert(NumSrcs < MaxSrcs); |
| 171 Srcs[NumSrcs++] = Src; | 169 Srcs[NumSrcs++] = Src; |
| 172 } | 170 } |
| 173 void setLastUse(SizeT VarIndex) { | 171 void setLastUse(SizeT VarIndex) { |
| 174 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) | 172 if (VarIndex < CHAR_BIT * sizeof(LiveRangesEnded)) |
| 175 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); | 173 LiveRangesEnded |= (((LREndedBits)1u) << VarIndex); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 222 | 220 |
| 223 protected: | 221 protected: |
| 224 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 222 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 225 : Inst(Func, Kind, MaxSrcs, Dest) {} | 223 : Inst(Func, Kind, MaxSrcs, Dest) {} |
| 226 void emit(const Cfg * /*Func*/) const override { | 224 void emit(const Cfg * /*Func*/) const override { |
| 227 llvm_unreachable("emit() called on a non-lowered instruction"); | 225 llvm_unreachable("emit() called on a non-lowered instruction"); |
| 228 } | 226 } |
| 229 void emitIAS(const Cfg * /*Func*/) const override { | 227 void emitIAS(const Cfg * /*Func*/) const override { |
| 230 llvm_unreachable("emitIAS() called on a non-lowered instruction"); | 228 llvm_unreachable("emitIAS() called on a non-lowered instruction"); |
| 231 } | 229 } |
| 232 ~InstHighLevel() override {} | |
| 233 }; | 230 }; |
| 234 | 231 |
| 235 // Alloca instruction. This captures the size in bytes as getSrc(0), | 232 // Alloca instruction. This captures the size in bytes as getSrc(0), |
| 236 // and the required alignment in bytes. The alignment must be either | 233 // and the required alignment in bytes. The alignment must be either |
| 237 // 0 (no alignment required) or a power of 2. | 234 // 0 (no alignment required) or a power of 2. |
| 238 class InstAlloca : public InstHighLevel { | 235 class InstAlloca : public InstHighLevel { |
| 239 InstAlloca() = delete; | 236 InstAlloca() = delete; |
| 240 InstAlloca(const InstAlloca &) = delete; | 237 InstAlloca(const InstAlloca &) = delete; |
| 241 InstAlloca &operator=(const InstAlloca &) = delete; | 238 InstAlloca &operator=(const InstAlloca &) = delete; |
| 242 | 239 |
| 243 public: | 240 public: |
| 244 static InstAlloca *create(Cfg *Func, Operand *ByteCount, | 241 static InstAlloca *create(Cfg *Func, Operand *ByteCount, |
| 245 uint32_t AlignInBytes, Variable *Dest) { | 242 uint32_t AlignInBytes, Variable *Dest) { |
| 246 return new (Func->allocate<InstAlloca>()) | 243 return new (Func->allocate<InstAlloca>()) |
| 247 InstAlloca(Func, ByteCount, AlignInBytes, Dest); | 244 InstAlloca(Func, ByteCount, AlignInBytes, Dest); |
| 248 } | 245 } |
| 249 uint32_t getAlignInBytes() const { return AlignInBytes; } | 246 uint32_t getAlignInBytes() const { return AlignInBytes; } |
| 250 Operand *getSizeInBytes() const { return getSrc(0); } | 247 Operand *getSizeInBytes() const { return getSrc(0); } |
| 251 void dump(const Cfg *Func) const override; | 248 void dump(const Cfg *Func) const override; |
| 252 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } | 249 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } |
| 253 | 250 |
| 254 private: | 251 private: |
| 255 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 252 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
| 256 Variable *Dest); | 253 Variable *Dest); |
| 257 ~InstAlloca() override {} | 254 |
| 258 const uint32_t AlignInBytes; | 255 const uint32_t AlignInBytes; |
| 259 }; | 256 }; |
| 260 | 257 |
| 261 // Binary arithmetic instruction. The source operands are captured in | 258 // Binary arithmetic instruction. The source operands are captured in |
| 262 // getSrc(0) and getSrc(1). | 259 // getSrc(0) and getSrc(1). |
| 263 class InstArithmetic : public InstHighLevel { | 260 class InstArithmetic : public InstHighLevel { |
| 264 InstArithmetic() = delete; | 261 InstArithmetic() = delete; |
| 265 InstArithmetic(const InstArithmetic &) = delete; | 262 InstArithmetic(const InstArithmetic &) = delete; |
| 266 InstArithmetic &operator=(const InstArithmetic &) = delete; | 263 InstArithmetic &operator=(const InstArithmetic &) = delete; |
| 267 | 264 |
| (...skipping 14 matching lines...) Expand all Loading... |
| 282 static const char *getOpName(OpKind Op); | 279 static const char *getOpName(OpKind Op); |
| 283 bool isCommutative() const; | 280 bool isCommutative() const; |
| 284 void dump(const Cfg *Func) const override; | 281 void dump(const Cfg *Func) const override; |
| 285 static bool classof(const Inst *Inst) { | 282 static bool classof(const Inst *Inst) { |
| 286 return Inst->getKind() == Arithmetic; | 283 return Inst->getKind() == Arithmetic; |
| 287 } | 284 } |
| 288 | 285 |
| 289 private: | 286 private: |
| 290 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, | 287 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, |
| 291 Operand *Source2); | 288 Operand *Source2); |
| 292 ~InstArithmetic() override {} | |
| 293 | 289 |
| 294 const OpKind Op; | 290 const OpKind Op; |
| 295 }; | 291 }; |
| 296 | 292 |
| 297 // Assignment instruction. The source operand is captured in | 293 // Assignment instruction. The source operand is captured in |
| 298 // getSrc(0). This is not part of the LLVM bitcode, but is a useful | 294 // getSrc(0). This is not part of the LLVM bitcode, but is a useful |
| 299 // abstraction for some of the lowering. E.g., if Phi instruction | 295 // abstraction for some of the lowering. E.g., if Phi instruction |
| 300 // lowering happens before target lowering, or for representing an | 296 // lowering happens before target lowering, or for representing an |
| 301 // Inttoptr instruction, or as an intermediate step for lowering a | 297 // Inttoptr instruction, or as an intermediate step for lowering a |
| 302 // Load instruction. | 298 // Load instruction. |
| 303 class InstAssign : public InstHighLevel { | 299 class InstAssign : public InstHighLevel { |
| 304 InstAssign() = delete; | 300 InstAssign() = delete; |
| 305 InstAssign(const InstAssign &) = delete; | 301 InstAssign(const InstAssign &) = delete; |
| 306 InstAssign &operator=(const InstAssign &) = delete; | 302 InstAssign &operator=(const InstAssign &) = delete; |
| 307 | 303 |
| 308 public: | 304 public: |
| 309 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 305 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 310 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); | 306 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
| 311 } | 307 } |
| 312 bool isSimpleAssign() const override { return true; } | 308 bool isSimpleAssign() const override { return true; } |
| 313 void dump(const Cfg *Func) const override; | 309 void dump(const Cfg *Func) const override; |
| 314 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } | 310 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } |
| 315 | 311 |
| 316 private: | 312 private: |
| 317 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 313 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
| 318 ~InstAssign() override {} | |
| 319 }; | 314 }; |
| 320 | 315 |
| 321 // Branch instruction. This represents both conditional and | 316 // Branch instruction. This represents both conditional and |
| 322 // unconditional branches. | 317 // unconditional branches. |
| 323 class InstBr : public InstHighLevel { | 318 class InstBr : public InstHighLevel { |
| 324 InstBr() = delete; | 319 InstBr() = delete; |
| 325 InstBr(const InstBr &) = delete; | 320 InstBr(const InstBr &) = delete; |
| 326 InstBr &operator=(const InstBr &) = delete; | 321 InstBr &operator=(const InstBr &) = delete; |
| 327 | 322 |
| 328 public: | 323 public: |
| (...skipping 23 matching lines...) Expand all Loading... |
| 352 bool isUnconditionalBranch() const override { return isUnconditional(); } | 347 bool isUnconditionalBranch() const override { return isUnconditional(); } |
| 353 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; | 348 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |
| 354 void dump(const Cfg *Func) const override; | 349 void dump(const Cfg *Func) const override; |
| 355 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } | 350 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } |
| 356 | 351 |
| 357 private: | 352 private: |
| 358 // Conditional branch | 353 // Conditional branch |
| 359 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); | 354 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); |
| 360 // Unconditional branch | 355 // Unconditional branch |
| 361 InstBr(Cfg *Func, CfgNode *Target); | 356 InstBr(Cfg *Func, CfgNode *Target); |
| 362 ~InstBr() override {} | |
| 363 | 357 |
| 364 CfgNode *TargetFalse; // Doubles as unconditional branch target | 358 CfgNode *TargetFalse; // Doubles as unconditional branch target |
| 365 CfgNode *TargetTrue; // nullptr if unconditional branch | 359 CfgNode *TargetTrue; // nullptr if unconditional branch |
| 366 }; | 360 }; |
| 367 | 361 |
| 368 // Call instruction. The call target is captured as getSrc(0), and | 362 // Call instruction. The call target is captured as getSrc(0), and |
| 369 // arg I is captured as getSrc(I+1). | 363 // arg I is captured as getSrc(I+1). |
| 370 class InstCall : public InstHighLevel { | 364 class InstCall : public InstHighLevel { |
| 371 InstCall() = delete; | 365 InstCall() = delete; |
| 372 InstCall(const InstCall &) = delete; | 366 InstCall(const InstCall &) = delete; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 392 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } | 386 static bool classof(const Inst *Inst) { return Inst->getKind() == Call; } |
| 393 Type getReturnType() const; | 387 Type getReturnType() const; |
| 394 | 388 |
| 395 protected: | 389 protected: |
| 396 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, | 390 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, |
| 397 bool HasTailCall, bool HasSideEff, InstKind Kind) | 391 bool HasTailCall, bool HasSideEff, InstKind Kind) |
| 398 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { | 392 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { |
| 399 HasSideEffects = HasSideEff; | 393 HasSideEffects = HasSideEff; |
| 400 addSource(CallTarget); | 394 addSource(CallTarget); |
| 401 } | 395 } |
| 402 ~InstCall() override {} | |
| 403 | 396 |
| 404 private: | 397 private: |
| 405 bool HasTailCall; | 398 bool HasTailCall; |
| 406 }; | 399 }; |
| 407 | 400 |
| 408 // Cast instruction (a.k.a. conversion operation). | 401 // Cast instruction (a.k.a. conversion operation). |
| 409 class InstCast : public InstHighLevel { | 402 class InstCast : public InstHighLevel { |
| 410 InstCast() = delete; | 403 InstCast() = delete; |
| 411 InstCast(const InstCast &) = delete; | 404 InstCast(const InstCast &) = delete; |
| 412 InstCast &operator=(const InstCast &) = delete; | 405 InstCast &operator=(const InstCast &) = delete; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 425 Operand *Source) { | 418 Operand *Source) { |
| 426 return new (Func->allocate<InstCast>()) | 419 return new (Func->allocate<InstCast>()) |
| 427 InstCast(Func, CastKind, Dest, Source); | 420 InstCast(Func, CastKind, Dest, Source); |
| 428 } | 421 } |
| 429 OpKind getCastKind() const { return CastKind; } | 422 OpKind getCastKind() const { return CastKind; } |
| 430 void dump(const Cfg *Func) const override; | 423 void dump(const Cfg *Func) const override; |
| 431 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 424 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } |
| 432 | 425 |
| 433 private: | 426 private: |
| 434 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 427 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
| 435 ~InstCast() override {} | 428 |
| 436 const OpKind CastKind; | 429 const OpKind CastKind; |
| 437 }; | 430 }; |
| 438 | 431 |
| 439 // ExtractElement instruction. | 432 // ExtractElement instruction. |
| 440 class InstExtractElement : public InstHighLevel { | 433 class InstExtractElement : public InstHighLevel { |
| 441 InstExtractElement() = delete; | 434 InstExtractElement() = delete; |
| 442 InstExtractElement(const InstExtractElement &) = delete; | 435 InstExtractElement(const InstExtractElement &) = delete; |
| 443 InstExtractElement &operator=(const InstExtractElement &) = delete; | 436 InstExtractElement &operator=(const InstExtractElement &) = delete; |
| 444 | 437 |
| 445 public: | 438 public: |
| 446 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 439 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 447 Operand *Source2) { | 440 Operand *Source2) { |
| 448 return new (Func->allocate<InstExtractElement>()) | 441 return new (Func->allocate<InstExtractElement>()) |
| 449 InstExtractElement(Func, Dest, Source1, Source2); | 442 InstExtractElement(Func, Dest, Source1, Source2); |
| 450 } | 443 } |
| 451 | 444 |
| 452 void dump(const Cfg *Func) const override; | 445 void dump(const Cfg *Func) const override; |
| 453 static bool classof(const Inst *Inst) { | 446 static bool classof(const Inst *Inst) { |
| 454 return Inst->getKind() == ExtractElement; | 447 return Inst->getKind() == ExtractElement; |
| 455 } | 448 } |
| 456 | 449 |
| 457 private: | 450 private: |
| 458 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 451 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 459 Operand *Source2); | 452 Operand *Source2); |
| 460 ~InstExtractElement() override {} | |
| 461 }; | 453 }; |
| 462 | 454 |
| 463 // Floating-point comparison instruction. The source operands are | 455 // Floating-point comparison instruction. The source operands are |
| 464 // captured in getSrc(0) and getSrc(1). | 456 // captured in getSrc(0) and getSrc(1). |
| 465 class InstFcmp : public InstHighLevel { | 457 class InstFcmp : public InstHighLevel { |
| 466 InstFcmp() = delete; | 458 InstFcmp() = delete; |
| 467 InstFcmp(const InstFcmp &) = delete; | 459 InstFcmp(const InstFcmp &) = delete; |
| 468 InstFcmp &operator=(const InstFcmp &) = delete; | 460 InstFcmp &operator=(const InstFcmp &) = delete; |
| 469 | 461 |
| 470 public: | 462 public: |
| 471 enum FCond { | 463 enum FCond { |
| 472 #define X(tag, str) tag, | 464 #define X(tag, str) tag, |
| 473 ICEINSTFCMP_TABLE | 465 ICEINSTFCMP_TABLE |
| 474 #undef X | 466 #undef X |
| 475 _num | 467 _num |
| 476 }; | 468 }; |
| 477 | 469 |
| 478 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 470 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
| 479 Operand *Source1, Operand *Source2) { | 471 Operand *Source1, Operand *Source2) { |
| 480 return new (Func->allocate<InstFcmp>()) | 472 return new (Func->allocate<InstFcmp>()) |
| 481 InstFcmp(Func, Condition, Dest, Source1, Source2); | 473 InstFcmp(Func, Condition, Dest, Source1, Source2); |
| 482 } | 474 } |
| 483 FCond getCondition() const { return Condition; } | 475 FCond getCondition() const { return Condition; } |
| 484 void dump(const Cfg *Func) const override; | 476 void dump(const Cfg *Func) const override; |
| 485 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } | 477 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } |
| 486 | 478 |
| 487 private: | 479 private: |
| 488 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 480 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
| 489 Operand *Source2); | 481 Operand *Source2); |
| 490 ~InstFcmp() override {} | 482 |
| 491 const FCond Condition; | 483 const FCond Condition; |
| 492 }; | 484 }; |
| 493 | 485 |
| 494 // Integer comparison instruction. The source operands are captured | 486 // Integer comparison instruction. The source operands are captured |
| 495 // in getSrc(0) and getSrc(1). | 487 // in getSrc(0) and getSrc(1). |
| 496 class InstIcmp : public InstHighLevel { | 488 class InstIcmp : public InstHighLevel { |
| 497 InstIcmp() = delete; | 489 InstIcmp() = delete; |
| 498 InstIcmp(const InstIcmp &) = delete; | 490 InstIcmp(const InstIcmp &) = delete; |
| 499 InstIcmp &operator=(const InstIcmp &) = delete; | 491 InstIcmp &operator=(const InstIcmp &) = delete; |
| 500 | 492 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 511 return new (Func->allocate<InstIcmp>()) | 503 return new (Func->allocate<InstIcmp>()) |
| 512 InstIcmp(Func, Condition, Dest, Source1, Source2); | 504 InstIcmp(Func, Condition, Dest, Source1, Source2); |
| 513 } | 505 } |
| 514 ICond getCondition() const { return Condition; } | 506 ICond getCondition() const { return Condition; } |
| 515 void dump(const Cfg *Func) const override; | 507 void dump(const Cfg *Func) const override; |
| 516 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 508 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } |
| 517 | 509 |
| 518 private: | 510 private: |
| 519 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 511 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
| 520 Operand *Source2); | 512 Operand *Source2); |
| 521 ~InstIcmp() override {} | 513 |
| 522 const ICond Condition; | 514 const ICond Condition; |
| 523 }; | 515 }; |
| 524 | 516 |
| 525 // InsertElement instruction. | 517 // InsertElement instruction. |
| 526 class InstInsertElement : public InstHighLevel { | 518 class InstInsertElement : public InstHighLevel { |
| 527 InstInsertElement() = delete; | 519 InstInsertElement() = delete; |
| 528 InstInsertElement(const InstInsertElement &) = delete; | 520 InstInsertElement(const InstInsertElement &) = delete; |
| 529 InstInsertElement &operator=(const InstInsertElement &) = delete; | 521 InstInsertElement &operator=(const InstInsertElement &) = delete; |
| 530 | 522 |
| 531 public: | 523 public: |
| 532 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 524 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 533 Operand *Source2, Operand *Source3) { | 525 Operand *Source2, Operand *Source3) { |
| 534 return new (Func->allocate<InstInsertElement>()) | 526 return new (Func->allocate<InstInsertElement>()) |
| 535 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 527 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
| 536 } | 528 } |
| 537 | 529 |
| 538 void dump(const Cfg *Func) const override; | 530 void dump(const Cfg *Func) const override; |
| 539 static bool classof(const Inst *Inst) { | 531 static bool classof(const Inst *Inst) { |
| 540 return Inst->getKind() == InsertElement; | 532 return Inst->getKind() == InsertElement; |
| 541 } | 533 } |
| 542 | 534 |
| 543 private: | 535 private: |
| 544 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 536 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 545 Operand *Source2, Operand *Source3); | 537 Operand *Source2, Operand *Source3); |
| 546 ~InstInsertElement() override {} | |
| 547 }; | 538 }; |
| 548 | 539 |
| 549 // Call to an intrinsic function. The call target is captured as getSrc(0), | 540 // Call to an intrinsic function. The call target is captured as getSrc(0), |
| 550 // and arg I is captured as getSrc(I+1). | 541 // and arg I is captured as getSrc(I+1). |
| 551 class InstIntrinsicCall : public InstCall { | 542 class InstIntrinsicCall : public InstCall { |
| 552 InstIntrinsicCall() = delete; | 543 InstIntrinsicCall() = delete; |
| 553 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | 544 InstIntrinsicCall(const InstIntrinsicCall &) = delete; |
| 554 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | 545 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; |
| 555 | 546 |
| 556 public: | 547 public: |
| 557 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 548 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 558 Operand *CallTarget, | 549 Operand *CallTarget, |
| 559 const Intrinsics::IntrinsicInfo &Info) { | 550 const Intrinsics::IntrinsicInfo &Info) { |
| 560 return new (Func->allocate<InstIntrinsicCall>()) | 551 return new (Func->allocate<InstIntrinsicCall>()) |
| 561 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 552 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
| 562 } | 553 } |
| 563 static bool classof(const Inst *Inst) { | 554 static bool classof(const Inst *Inst) { |
| 564 return Inst->getKind() == IntrinsicCall; | 555 return Inst->getKind() == IntrinsicCall; |
| 565 } | 556 } |
| 566 | 557 |
| 567 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 558 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
| 568 | 559 |
| 569 private: | 560 private: |
| 570 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 561 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 571 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 562 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
| 572 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, | 563 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, |
| 573 Inst::IntrinsicCall), | 564 Inst::IntrinsicCall), |
| 574 Info(Info) {} | 565 Info(Info) {} |
| 575 ~InstIntrinsicCall() override {} | 566 |
| 576 const Intrinsics::IntrinsicInfo Info; | 567 const Intrinsics::IntrinsicInfo Info; |
| 577 }; | 568 }; |
| 578 | 569 |
| 579 // Load instruction. The source address is captured in getSrc(0). | 570 // Load instruction. The source address is captured in getSrc(0). |
| 580 class InstLoad : public InstHighLevel { | 571 class InstLoad : public InstHighLevel { |
| 581 InstLoad() = delete; | 572 InstLoad() = delete; |
| 582 InstLoad(const InstLoad &) = delete; | 573 InstLoad(const InstLoad &) = delete; |
| 583 InstLoad &operator=(const InstLoad &) = delete; | 574 InstLoad &operator=(const InstLoad &) = delete; |
| 584 | 575 |
| 585 public: | 576 public: |
| 586 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 577 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
| 587 uint32_t Align = 1) { | 578 uint32_t Align = 1) { |
| 588 // TODO(kschimpf) Stop ignoring alignment specification. | 579 // TODO(kschimpf) Stop ignoring alignment specification. |
| 589 (void)Align; | 580 (void)Align; |
| 590 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); | 581 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
| 591 } | 582 } |
| 592 Operand *getSourceAddress() const { return getSrc(0); } | 583 Operand *getSourceAddress() const { return getSrc(0); } |
| 593 void dump(const Cfg *Func) const override; | 584 void dump(const Cfg *Func) const override; |
| 594 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } | 585 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } |
| 595 | 586 |
| 596 private: | 587 private: |
| 597 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 588 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
| 598 ~InstLoad() override {} | |
| 599 }; | 589 }; |
| 600 | 590 |
| 601 // Phi instruction. For incoming edge I, the node is Labels[I] and | 591 // Phi instruction. For incoming edge I, the node is Labels[I] and |
| 602 // the Phi source operand is getSrc(I). | 592 // the Phi source operand is getSrc(I). |
| 603 class InstPhi : public InstHighLevel { | 593 class InstPhi : public InstHighLevel { |
| 604 InstPhi() = delete; | 594 InstPhi() = delete; |
| 605 InstPhi(const InstPhi &) = delete; | 595 InstPhi(const InstPhi &) = delete; |
| 606 InstPhi &operator=(const InstPhi &) = delete; | 596 InstPhi &operator=(const InstPhi &) = delete; |
| 607 | 597 |
| 608 public: | 598 public: |
| 609 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 599 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
| 610 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 600 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
| 611 } | 601 } |
| 612 void addArgument(Operand *Source, CfgNode *Label); | 602 void addArgument(Operand *Source, CfgNode *Label); |
| 613 Operand *getOperandForTarget(CfgNode *Target) const; | 603 Operand *getOperandForTarget(CfgNode *Target) const; |
| 614 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } | 604 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } |
| 615 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 605 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
| 616 Liveness *Liveness); | 606 Liveness *Liveness); |
| 617 Inst *lower(Cfg *Func); | 607 Inst *lower(Cfg *Func); |
| 618 void dump(const Cfg *Func) const override; | 608 void dump(const Cfg *Func) const override; |
| 619 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } | 609 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } |
| 620 | 610 |
| 621 private: | 611 private: |
| 622 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 612 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
| 623 void destroy(Cfg *Func) override { | 613 void destroy(Cfg *Func) override { |
| 624 Func->deallocateArrayOf<CfgNode *>(Labels); | 614 Func->deallocateArrayOf<CfgNode *>(Labels); |
| 625 Inst::destroy(Func); | 615 Inst::destroy(Func); |
| 626 } | 616 } |
| 627 ~InstPhi() override {} | |
| 628 | 617 |
| 629 // Labels[] duplicates the InEdges[] information in the enclosing | 618 // Labels[] duplicates the InEdges[] information in the enclosing |
| 630 // CfgNode, but the Phi instruction is created before InEdges[] | 619 // CfgNode, but the Phi instruction is created before InEdges[] |
| 631 // is available, so it's more complicated to share the list. | 620 // is available, so it's more complicated to share the list. |
| 632 CfgNode **Labels; | 621 CfgNode **Labels; |
| 633 }; | 622 }; |
| 634 | 623 |
| 635 // Ret instruction. The return value is captured in getSrc(0), but if | 624 // Ret instruction. The return value is captured in getSrc(0), but if |
| 636 // there is no return value (void-type function), then | 625 // there is no return value (void-type function), then |
| 637 // getSrcSize()==0 and hasRetValue()==false. | 626 // getSrcSize()==0 and hasRetValue()==false. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 648 Operand *getRetValue() const { | 637 Operand *getRetValue() const { |
| 649 assert(hasRetValue()); | 638 assert(hasRetValue()); |
| 650 return getSrc(0); | 639 return getSrc(0); |
| 651 } | 640 } |
| 652 NodeList getTerminatorEdges() const override { return NodeList(); } | 641 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 653 void dump(const Cfg *Func) const override; | 642 void dump(const Cfg *Func) const override; |
| 654 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } | 643 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } |
| 655 | 644 |
| 656 private: | 645 private: |
| 657 InstRet(Cfg *Func, Operand *RetValue); | 646 InstRet(Cfg *Func, Operand *RetValue); |
| 658 ~InstRet() override {} | |
| 659 }; | 647 }; |
| 660 | 648 |
| 661 // Select instruction. The condition, true, and false operands are captured. | 649 // Select instruction. The condition, true, and false operands are captured. |
| 662 class InstSelect : public InstHighLevel { | 650 class InstSelect : public InstHighLevel { |
| 663 InstSelect() = delete; | 651 InstSelect() = delete; |
| 664 InstSelect(const InstSelect &) = delete; | 652 InstSelect(const InstSelect &) = delete; |
| 665 InstSelect &operator=(const InstSelect &) = delete; | 653 InstSelect &operator=(const InstSelect &) = delete; |
| 666 | 654 |
| 667 public: | 655 public: |
| 668 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 656 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
| 669 Operand *SourceTrue, Operand *SourceFalse) { | 657 Operand *SourceTrue, Operand *SourceFalse) { |
| 670 return new (Func->allocate<InstSelect>()) | 658 return new (Func->allocate<InstSelect>()) |
| 671 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 659 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
| 672 } | 660 } |
| 673 Operand *getCondition() const { return getSrc(0); } | 661 Operand *getCondition() const { return getSrc(0); } |
| 674 Operand *getTrueOperand() const { return getSrc(1); } | 662 Operand *getTrueOperand() const { return getSrc(1); } |
| 675 Operand *getFalseOperand() const { return getSrc(2); } | 663 Operand *getFalseOperand() const { return getSrc(2); } |
| 676 void dump(const Cfg *Func) const override; | 664 void dump(const Cfg *Func) const override; |
| 677 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } | 665 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } |
| 678 | 666 |
| 679 private: | 667 private: |
| 680 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 668 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
| 681 Operand *Source2); | 669 Operand *Source2); |
| 682 ~InstSelect() override {} | |
| 683 }; | 670 }; |
| 684 | 671 |
| 685 // Store instruction. The address operand is captured, along with the | 672 // Store instruction. The address operand is captured, along with the |
| 686 // data operand to be stored into the address. | 673 // data operand to be stored into the address. |
| 687 class InstStore : public InstHighLevel { | 674 class InstStore : public InstHighLevel { |
| 688 InstStore() = delete; | 675 InstStore() = delete; |
| 689 InstStore(const InstStore &) = delete; | 676 InstStore(const InstStore &) = delete; |
| 690 InstStore &operator=(const InstStore &) = delete; | 677 InstStore &operator=(const InstStore &) = delete; |
| 691 | 678 |
| 692 public: | 679 public: |
| 693 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, | 680 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, |
| 694 uint32_t Align = 1) { | 681 uint32_t Align = 1) { |
| 695 // TODO(kschimpf) Stop ignoring alignment specification. | 682 // TODO(kschimpf) Stop ignoring alignment specification. |
| 696 (void)Align; | 683 (void)Align; |
| 697 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); | 684 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); |
| 698 } | 685 } |
| 699 Operand *getAddr() const { return getSrc(1); } | 686 Operand *getAddr() const { return getSrc(1); } |
| 700 Operand *getData() const { return getSrc(0); } | 687 Operand *getData() const { return getSrc(0); } |
| 701 Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); } | 688 Variable *getRmwBeacon() const { return llvm::dyn_cast<Variable>(getSrc(2)); } |
| 702 void setRmwBeacon(Variable *Beacon); | 689 void setRmwBeacon(Variable *Beacon); |
| 703 void dump(const Cfg *Func) const override; | 690 void dump(const Cfg *Func) const override; |
| 704 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } | 691 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } |
| 705 | 692 |
| 706 private: | 693 private: |
| 707 InstStore(Cfg *Func, Operand *Data, Operand *Addr); | 694 InstStore(Cfg *Func, Operand *Data, Operand *Addr); |
| 708 ~InstStore() override {} | |
| 709 }; | 695 }; |
| 710 | 696 |
| 711 // Switch instruction. The single source operand is captured as | 697 // Switch instruction. The single source operand is captured as |
| 712 // getSrc(0). | 698 // getSrc(0). |
| 713 class InstSwitch : public InstHighLevel { | 699 class InstSwitch : public InstHighLevel { |
| 714 InstSwitch() = delete; | 700 InstSwitch() = delete; |
| 715 InstSwitch(const InstSwitch &) = delete; | 701 InstSwitch(const InstSwitch &) = delete; |
| 716 InstSwitch &operator=(const InstSwitch &) = delete; | 702 InstSwitch &operator=(const InstSwitch &) = delete; |
| 717 | 703 |
| 718 public: | 704 public: |
| (...skipping 19 matching lines...) Expand all Loading... |
| 738 void dump(const Cfg *Func) const override; | 724 void dump(const Cfg *Func) const override; |
| 739 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } | 725 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } |
| 740 | 726 |
| 741 private: | 727 private: |
| 742 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); | 728 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); |
| 743 void destroy(Cfg *Func) override { | 729 void destroy(Cfg *Func) override { |
| 744 Func->deallocateArrayOf<uint64_t>(Values); | 730 Func->deallocateArrayOf<uint64_t>(Values); |
| 745 Func->deallocateArrayOf<CfgNode *>(Labels); | 731 Func->deallocateArrayOf<CfgNode *>(Labels); |
| 746 Inst::destroy(Func); | 732 Inst::destroy(Func); |
| 747 } | 733 } |
| 748 ~InstSwitch() override {} | |
| 749 | 734 |
| 750 CfgNode *LabelDefault; | 735 CfgNode *LabelDefault; |
| 751 SizeT NumCases; // not including the default case | 736 SizeT NumCases; // not including the default case |
| 752 uint64_t *Values; // size is NumCases | 737 uint64_t *Values; // size is NumCases |
| 753 CfgNode **Labels; // size is NumCases | 738 CfgNode **Labels; // size is NumCases |
| 754 }; | 739 }; |
| 755 | 740 |
| 756 // Unreachable instruction. This is a terminator instruction with no | 741 // Unreachable instruction. This is a terminator instruction with no |
| 757 // operands. | 742 // operands. |
| 758 class InstUnreachable : public InstHighLevel { | 743 class InstUnreachable : public InstHighLevel { |
| 759 InstUnreachable() = delete; | 744 InstUnreachable() = delete; |
| 760 InstUnreachable(const InstUnreachable &) = delete; | 745 InstUnreachable(const InstUnreachable &) = delete; |
| 761 InstUnreachable &operator=(const InstUnreachable &) = delete; | 746 InstUnreachable &operator=(const InstUnreachable &) = delete; |
| 762 | 747 |
| 763 public: | 748 public: |
| 764 static InstUnreachable *create(Cfg *Func) { | 749 static InstUnreachable *create(Cfg *Func) { |
| 765 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); | 750 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
| 766 } | 751 } |
| 767 NodeList getTerminatorEdges() const override { return NodeList(); } | 752 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 768 void dump(const Cfg *Func) const override; | 753 void dump(const Cfg *Func) const override; |
| 769 static bool classof(const Inst *Inst) { | 754 static bool classof(const Inst *Inst) { |
| 770 return Inst->getKind() == Unreachable; | 755 return Inst->getKind() == Unreachable; |
| 771 } | 756 } |
| 772 | 757 |
| 773 private: | 758 private: |
| 774 explicit InstUnreachable(Cfg *Func); | 759 explicit InstUnreachable(Cfg *Func); |
| 775 ~InstUnreachable() override {} | |
| 776 }; | 760 }; |
| 777 | 761 |
| 778 // BundleLock instruction. There are no operands. Contains an option | 762 // BundleLock instruction. There are no operands. Contains an option |
| 779 // indicating whether align_to_end is specified. | 763 // indicating whether align_to_end is specified. |
| 780 class InstBundleLock : public InstHighLevel { | 764 class InstBundleLock : public InstHighLevel { |
| 781 InstBundleLock() = delete; | 765 InstBundleLock() = delete; |
| 782 InstBundleLock(const InstBundleLock &) = delete; | 766 InstBundleLock(const InstBundleLock &) = delete; |
| 783 InstBundleLock &operator=(const InstBundleLock &) = delete; | 767 InstBundleLock &operator=(const InstBundleLock &) = delete; |
| 784 | 768 |
| 785 public: | 769 public: |
| 786 enum Option { Opt_None, Opt_AlignToEnd }; | 770 enum Option { Opt_None, Opt_AlignToEnd }; |
| 787 static InstBundleLock *create(Cfg *Func, Option BundleOption) { | 771 static InstBundleLock *create(Cfg *Func, Option BundleOption) { |
| 788 return new (Func->allocate<InstBundleLock>()) | 772 return new (Func->allocate<InstBundleLock>()) |
| 789 InstBundleLock(Func, BundleOption); | 773 InstBundleLock(Func, BundleOption); |
| 790 } | 774 } |
| 791 void emit(const Cfg *Func) const override; | 775 void emit(const Cfg *Func) const override; |
| 792 void emitIAS(const Cfg * /* Func */) const override {} | 776 void emitIAS(const Cfg * /* Func */) const override {} |
| 793 void dump(const Cfg *Func) const override; | 777 void dump(const Cfg *Func) const override; |
| 794 Option getOption() const { return BundleOption; } | 778 Option getOption() const { return BundleOption; } |
| 795 static bool classof(const Inst *Inst) { | 779 static bool classof(const Inst *Inst) { |
| 796 return Inst->getKind() == BundleLock; | 780 return Inst->getKind() == BundleLock; |
| 797 } | 781 } |
| 798 | 782 |
| 799 private: | 783 private: |
| 800 Option BundleOption; | 784 Option BundleOption; |
| 801 InstBundleLock(Cfg *Func, Option BundleOption); | 785 InstBundleLock(Cfg *Func, Option BundleOption); |
| 802 ~InstBundleLock() override {} | |
| 803 }; | 786 }; |
| 804 | 787 |
| 805 // BundleUnlock instruction. There are no operands. | 788 // BundleUnlock instruction. There are no operands. |
| 806 class InstBundleUnlock : public InstHighLevel { | 789 class InstBundleUnlock : public InstHighLevel { |
| 807 InstBundleUnlock() = delete; | 790 InstBundleUnlock() = delete; |
| 808 InstBundleUnlock(const InstBundleUnlock &) = delete; | 791 InstBundleUnlock(const InstBundleUnlock &) = delete; |
| 809 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; | 792 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; |
| 810 | 793 |
| 811 public: | 794 public: |
| 812 static InstBundleUnlock *create(Cfg *Func) { | 795 static InstBundleUnlock *create(Cfg *Func) { |
| 813 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); | 796 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); |
| 814 } | 797 } |
| 815 void emit(const Cfg *Func) const override; | 798 void emit(const Cfg *Func) const override; |
| 816 void emitIAS(const Cfg * /* Func */) const override {} | 799 void emitIAS(const Cfg * /* Func */) const override {} |
| 817 void dump(const Cfg *Func) const override; | 800 void dump(const Cfg *Func) const override; |
| 818 static bool classof(const Inst *Inst) { | 801 static bool classof(const Inst *Inst) { |
| 819 return Inst->getKind() == BundleUnlock; | 802 return Inst->getKind() == BundleUnlock; |
| 820 } | 803 } |
| 821 | 804 |
| 822 private: | 805 private: |
| 823 explicit InstBundleUnlock(Cfg *Func); | 806 explicit InstBundleUnlock(Cfg *Func); |
| 824 ~InstBundleUnlock() override {} | |
| 825 }; | 807 }; |
| 826 | 808 |
| 827 // FakeDef instruction. This creates a fake definition of a variable, | 809 // FakeDef instruction. This creates a fake definition of a variable, |
| 828 // which is how we represent the case when an instruction produces | 810 // which is how we represent the case when an instruction produces |
| 829 // multiple results. This doesn't happen with high-level ICE | 811 // multiple results. This doesn't happen with high-level ICE |
| 830 // instructions, but might with lowered instructions. For example, | 812 // instructions, but might with lowered instructions. For example, |
| 831 // this would be a way to represent condition flags being modified by | 813 // this would be a way to represent condition flags being modified by |
| 832 // an instruction. | 814 // an instruction. |
| 833 // | 815 // |
| 834 // It's generally useful to set the optional source operand to be the | 816 // It's generally useful to set the optional source operand to be the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 846 Variable *Src = nullptr) { | 828 Variable *Src = nullptr) { |
| 847 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 829 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
| 848 } | 830 } |
| 849 void emit(const Cfg *Func) const override; | 831 void emit(const Cfg *Func) const override; |
| 850 void emitIAS(const Cfg * /* Func */) const override {} | 832 void emitIAS(const Cfg * /* Func */) const override {} |
| 851 void dump(const Cfg *Func) const override; | 833 void dump(const Cfg *Func) const override; |
| 852 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } | 834 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
| 853 | 835 |
| 854 private: | 836 private: |
| 855 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 837 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
| 856 ~InstFakeDef() override {} | |
| 857 }; | 838 }; |
| 858 | 839 |
| 859 // FakeUse instruction. This creates a fake use of a variable, to | 840 // FakeUse instruction. This creates a fake use of a variable, to |
| 860 // keep the instruction that produces that variable from being | 841 // keep the instruction that produces that variable from being |
| 861 // dead-code eliminated. This is useful in a variety of lowering | 842 // dead-code eliminated. This is useful in a variety of lowering |
| 862 // situations. The FakeUse instruction has no dest, so it can itself | 843 // situations. The FakeUse instruction has no dest, so it can itself |
| 863 // never be dead-code eliminated. | 844 // never be dead-code eliminated. |
| 864 class InstFakeUse : public InstHighLevel { | 845 class InstFakeUse : public InstHighLevel { |
| 865 InstFakeUse() = delete; | 846 InstFakeUse() = delete; |
| 866 InstFakeUse(const InstFakeUse &) = delete; | 847 InstFakeUse(const InstFakeUse &) = delete; |
| 867 InstFakeUse &operator=(const InstFakeUse &) = delete; | 848 InstFakeUse &operator=(const InstFakeUse &) = delete; |
| 868 | 849 |
| 869 public: | 850 public: |
| 870 static InstFakeUse *create(Cfg *Func, Variable *Src) { | 851 static InstFakeUse *create(Cfg *Func, Variable *Src) { |
| 871 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); | 852 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); |
| 872 } | 853 } |
| 873 void emit(const Cfg *Func) const override; | 854 void emit(const Cfg *Func) const override; |
| 874 void emitIAS(const Cfg * /* Func */) const override {} | 855 void emitIAS(const Cfg * /* Func */) const override {} |
| 875 void dump(const Cfg *Func) const override; | 856 void dump(const Cfg *Func) const override; |
| 876 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } | 857 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
| 877 | 858 |
| 878 private: | 859 private: |
| 879 InstFakeUse(Cfg *Func, Variable *Src); | 860 InstFakeUse(Cfg *Func, Variable *Src); |
| 880 ~InstFakeUse() override {} | |
| 881 }; | 861 }; |
| 882 | 862 |
| 883 // FakeKill instruction. This "kills" a set of variables by modeling | 863 // FakeKill instruction. This "kills" a set of variables by modeling |
| 884 // a trivial live range at this instruction for each (implicit) | 864 // a trivial live range at this instruction for each (implicit) |
| 885 // variable. The primary use is to indicate that scratch registers | 865 // variable. The primary use is to indicate that scratch registers |
| 886 // are killed after a call, so that the register allocator won't | 866 // are killed after a call, so that the register allocator won't |
| 887 // assign a scratch register to a variable whose live range spans a | 867 // assign a scratch register to a variable whose live range spans a |
| 888 // call. | 868 // call. |
| 889 // | 869 // |
| 890 // The FakeKill instruction also holds a pointer to the instruction | 870 // The FakeKill instruction also holds a pointer to the instruction |
| 891 // that kills the set of variables, so that if that linked instruction | 871 // that kills the set of variables, so that if that linked instruction |
| 892 // gets dead-code eliminated, the FakeKill instruction will as well. | 872 // gets dead-code eliminated, the FakeKill instruction will as well. |
| 893 class InstFakeKill : public InstHighLevel { | 873 class InstFakeKill : public InstHighLevel { |
| 894 InstFakeKill() = delete; | 874 InstFakeKill() = delete; |
| 895 InstFakeKill(const InstFakeKill &) = delete; | 875 InstFakeKill(const InstFakeKill &) = delete; |
| 896 InstFakeKill &operator=(const InstFakeKill &) = delete; | 876 InstFakeKill &operator=(const InstFakeKill &) = delete; |
| 897 | 877 |
| 898 public: | 878 public: |
| 899 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { | 879 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { |
| 900 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); | 880 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); |
| 901 } | 881 } |
| 902 const Inst *getLinked() const { return Linked; } | 882 const Inst *getLinked() const { return Linked; } |
| 903 void emit(const Cfg *Func) const override; | 883 void emit(const Cfg *Func) const override; |
| 904 void emitIAS(const Cfg * /* Func */) const override {} | 884 void emitIAS(const Cfg * /* Func */) const override {} |
| 905 void dump(const Cfg *Func) const override; | 885 void dump(const Cfg *Func) const override; |
| 906 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } | 886 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
| 907 | 887 |
| 908 private: | 888 private: |
| 909 InstFakeKill(Cfg *Func, const Inst *Linked); | 889 InstFakeKill(Cfg *Func, const Inst *Linked); |
| 910 ~InstFakeKill() override {} | |
| 911 | 890 |
| 912 // This instruction is ignored if Linked->isDeleted() is true. | 891 // This instruction is ignored if Linked->isDeleted() is true. |
| 913 const Inst *Linked; | 892 const Inst *Linked; |
| 914 }; | 893 }; |
| 915 | 894 |
| 916 // The Target instruction is the base class for all target-specific | 895 // The Target instruction is the base class for all target-specific |
| 917 // instructions. | 896 // instructions. |
| 918 class InstTarget : public Inst { | 897 class InstTarget : public Inst { |
| 919 InstTarget() = delete; | 898 InstTarget() = delete; |
| 920 InstTarget(const InstTarget &) = delete; | 899 InstTarget(const InstTarget &) = delete; |
| 921 InstTarget &operator=(const InstTarget &) = delete; | 900 InstTarget &operator=(const InstTarget &) = delete; |
| 922 | 901 |
| 923 public: | 902 public: |
| 924 uint32_t getEmitInstCount() const override { return 1; } | 903 uint32_t getEmitInstCount() const override { return 1; } |
| 925 void dump(const Cfg *Func) const override; | 904 void dump(const Cfg *Func) const override; |
| 926 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 905 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
| 927 | 906 |
| 928 protected: | 907 protected: |
| 929 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 908 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 930 : Inst(Func, Kind, MaxSrcs, Dest) { | 909 : Inst(Func, Kind, MaxSrcs, Dest) { |
| 931 assert(Kind >= Target); | 910 assert(Kind >= Target); |
| 932 } | 911 } |
| 933 ~InstTarget() override {} | |
| 934 }; | 912 }; |
| 935 | 913 |
| 936 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); | 914 bool checkForRedundantAssign(const Variable *Dest, const Operand *Source); |
| 937 | 915 |
| 938 } // end of namespace Ice | 916 } // end of namespace Ice |
| 939 | 917 |
| 940 namespace llvm { | 918 namespace llvm { |
| 941 | 919 |
| 942 // Override the default ilist traits so that Inst's private ctor and | 920 // Override the default ilist traits so that Inst's private ctor and |
| 943 // deleted dtor aren't invoked. | 921 // deleted dtor aren't invoked. |
| 944 template <> | 922 template <> |
| 945 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { | 923 struct ilist_traits<Ice::Inst> : public ilist_default_traits<Ice::Inst> { |
| 946 Ice::Inst *createSentinel() const { | 924 Ice::Inst *createSentinel() const { |
| 947 return static_cast<Ice::Inst *>(&Sentinel); | 925 return static_cast<Ice::Inst *>(&Sentinel); |
| 948 } | 926 } |
| 949 static void destroySentinel(Ice::Inst *) {} | 927 static void destroySentinel(Ice::Inst *) {} |
| 950 Ice::Inst *provideInitialHead() const { return createSentinel(); } | 928 Ice::Inst *provideInitialHead() const { return createSentinel(); } |
| 951 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } | 929 Ice::Inst *ensureHead(Ice::Inst *) const { return createSentinel(); } |
| 952 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 930 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
| 953 void deleteNode(Ice::Inst *) {} | 931 void deleteNode(Ice::Inst *) {} |
| 954 | 932 |
| 955 private: | 933 private: |
| 956 mutable ilist_half_node<Ice::Inst> Sentinel; | 934 mutable ilist_half_node<Ice::Inst> Sentinel; |
| 957 }; | 935 }; |
| 958 | 936 |
| 959 } // end of namespace llvm | 937 } // end of namespace llvm |
| 960 | 938 |
| 961 #endif // SUBZERO_SRC_ICEINST_H | 939 #endif // SUBZERO_SRC_ICEINST_H |
| OLD | NEW |