| 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 17 matching lines...) Expand all Loading... |
| 28 // We need a list of everything that should be validated, and tests | 28 // We need a list of everything that should be validated, and tests |
| 29 // for each. | 29 // for each. |
| 30 | 30 |
| 31 namespace Ice { | 31 namespace Ice { |
| 32 | 32 |
| 33 // Base instruction class for ICE. Inst has two subclasses: | 33 // Base instruction class for ICE. Inst has two subclasses: |
| 34 // InstHighLevel and InstTarget. High-level ICE instructions inherit | 34 // InstHighLevel and InstTarget. High-level ICE instructions inherit |
| 35 // from InstHighLevel, and low-level (target-specific) ICE | 35 // from InstHighLevel, and low-level (target-specific) ICE |
| 36 // instructions inherit from InstTarget. | 36 // instructions inherit from InstTarget. |
| 37 class Inst : public llvm::ilist_node<Inst> { | 37 class Inst : public llvm::ilist_node<Inst> { |
| 38 Inst() = delete; |
| 38 Inst(const Inst &) = delete; | 39 Inst(const Inst &) = delete; |
| 39 Inst &operator=(const Inst &) = delete; | 40 Inst &operator=(const Inst &) = delete; |
| 40 | 41 |
| 41 public: | 42 public: |
| 42 enum InstKind { | 43 enum InstKind { |
| 43 // Arbitrary (alphabetical) order, except put Unreachable first. | 44 // Arbitrary (alphabetical) order, except put Unreachable first. |
| 44 Unreachable, | 45 Unreachable, |
| 45 Alloca, | 46 Alloca, |
| 46 Arithmetic, | 47 Arithmetic, |
| 47 Assign, // not part of LLVM/PNaCl bitcode | |
| 48 Br, | 48 Br, |
| 49 Call, | 49 Call, |
| 50 Cast, | 50 Cast, |
| 51 ExtractElement, | 51 ExtractElement, |
| 52 Fcmp, | 52 Fcmp, |
| 53 Icmp, | 53 Icmp, |
| 54 IntrinsicCall, | 54 IntrinsicCall, |
| 55 InsertElement, | 55 InsertElement, |
| 56 Load, | 56 Load, |
| 57 Phi, | 57 Phi, |
| 58 Ret, | 58 Ret, |
| 59 Select, | 59 Select, |
| 60 Store, | 60 Store, |
| 61 Switch, | 61 Switch, |
| 62 Assign, // not part of LLVM/PNaCl bitcode |
| 62 BundleLock, // not part of LLVM/PNaCl bitcode | 63 BundleLock, // not part of LLVM/PNaCl bitcode |
| 63 BundleUnlock, // not part of LLVM/PNaCl bitcode | 64 BundleUnlock, // not part of LLVM/PNaCl bitcode |
| 64 FakeDef, // not part of LLVM/PNaCl bitcode | 65 FakeDef, // not part of LLVM/PNaCl bitcode |
| 65 FakeUse, // not part of LLVM/PNaCl bitcode | 66 FakeUse, // not part of LLVM/PNaCl bitcode |
| 66 FakeKill, // not part of LLVM/PNaCl bitcode | 67 FakeKill, // not part of LLVM/PNaCl bitcode |
| 67 Target // target-specific low-level ICE | 68 Target // target-specific low-level ICE |
| 68 // Anything >= Target is an InstTarget subclass. | 69 // Anything >= Target is an InstTarget subclass. |
| 69 }; | 70 }; |
| 70 InstKind getKind() const { return Kind; } | 71 InstKind getKind() const { return Kind; } |
| 71 | 72 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 // could contain more than 1 Variable). All the variables in an | 201 // could contain more than 1 Variable). All the variables in an |
| 201 // instruction are conceptually flattened and each variable is | 202 // instruction are conceptually flattened and each variable is |
| 202 // mapped to one bit position of the LiveRangesEnded bit vector. | 203 // mapped to one bit position of the LiveRangesEnded bit vector. |
| 203 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are | 204 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are |
| 204 // tracked this way. | 205 // tracked this way. |
| 205 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry | 206 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry |
| 206 LREndedBits LiveRangesEnded; | 207 LREndedBits LiveRangesEnded; |
| 207 }; | 208 }; |
| 208 | 209 |
| 209 class InstHighLevel : public Inst { | 210 class InstHighLevel : public Inst { |
| 211 InstHighLevel() = delete; |
| 210 InstHighLevel(const InstHighLevel &) = delete; | 212 InstHighLevel(const InstHighLevel &) = delete; |
| 211 InstHighLevel &operator=(const InstHighLevel &) = delete; | 213 InstHighLevel &operator=(const InstHighLevel &) = delete; |
| 212 | 214 |
| 213 protected: | 215 protected: |
| 214 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 216 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| 215 : Inst(Func, Kind, MaxSrcs, Dest) {} | 217 : Inst(Func, Kind, MaxSrcs, Dest) {} |
| 216 void emit(const Cfg * /*Func*/) const override { | 218 void emit(const Cfg * /*Func*/) const override { |
| 217 llvm_unreachable("emit() called on a non-lowered instruction"); | 219 llvm_unreachable("emit() called on a non-lowered instruction"); |
| 218 } | 220 } |
| 219 void emitIAS(const Cfg * /*Func*/) const override { | 221 void emitIAS(const Cfg * /*Func*/) const override { |
| 220 llvm_unreachable("emitIAS() called on a non-lowered instruction"); | 222 llvm_unreachable("emitIAS() called on a non-lowered instruction"); |
| 221 } | 223 } |
| 222 ~InstHighLevel() override {} | 224 ~InstHighLevel() override {} |
| 223 }; | 225 }; |
| 224 | 226 |
| 225 // Alloca instruction. This captures the size in bytes as getSrc(0), | 227 // Alloca instruction. This captures the size in bytes as getSrc(0), |
| 226 // and the required alignment in bytes. The alignment must be either | 228 // and the required alignment in bytes. The alignment must be either |
| 227 // 0 (no alignment required) or a power of 2. | 229 // 0 (no alignment required) or a power of 2. |
| 228 class InstAlloca : public InstHighLevel { | 230 class InstAlloca : public InstHighLevel { |
| 231 InstAlloca() = delete; |
| 229 InstAlloca(const InstAlloca &) = delete; | 232 InstAlloca(const InstAlloca &) = delete; |
| 230 InstAlloca &operator=(const InstAlloca &) = delete; | 233 InstAlloca &operator=(const InstAlloca &) = delete; |
| 231 | 234 |
| 232 public: | 235 public: |
| 233 static InstAlloca *create(Cfg *Func, Operand *ByteCount, | 236 static InstAlloca *create(Cfg *Func, Operand *ByteCount, |
| 234 uint32_t AlignInBytes, Variable *Dest) { | 237 uint32_t AlignInBytes, Variable *Dest) { |
| 235 return new (Func->allocate<InstAlloca>()) | 238 return new (Func->allocate<InstAlloca>()) |
| 236 InstAlloca(Func, ByteCount, AlignInBytes, Dest); | 239 InstAlloca(Func, ByteCount, AlignInBytes, Dest); |
| 237 } | 240 } |
| 238 uint32_t getAlignInBytes() const { return AlignInBytes; } | 241 uint32_t getAlignInBytes() const { return AlignInBytes; } |
| 239 Operand *getSizeInBytes() const { return getSrc(0); } | 242 Operand *getSizeInBytes() const { return getSrc(0); } |
| 240 void dump(const Cfg *Func) const override; | 243 void dump(const Cfg *Func) const override; |
| 241 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } | 244 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } |
| 242 | 245 |
| 243 private: | 246 private: |
| 244 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 247 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
| 245 Variable *Dest); | 248 Variable *Dest); |
| 246 ~InstAlloca() override {} | 249 ~InstAlloca() override {} |
| 247 const uint32_t AlignInBytes; | 250 const uint32_t AlignInBytes; |
| 248 }; | 251 }; |
| 249 | 252 |
| 250 // Binary arithmetic instruction. The source operands are captured in | 253 // Binary arithmetic instruction. The source operands are captured in |
| 251 // getSrc(0) and getSrc(1). | 254 // getSrc(0) and getSrc(1). |
| 252 class InstArithmetic : public InstHighLevel { | 255 class InstArithmetic : public InstHighLevel { |
| 256 InstArithmetic() = delete; |
| 253 InstArithmetic(const InstArithmetic &) = delete; | 257 InstArithmetic(const InstArithmetic &) = delete; |
| 254 InstArithmetic &operator=(const InstArithmetic &) = delete; | 258 InstArithmetic &operator=(const InstArithmetic &) = delete; |
| 255 | 259 |
| 256 public: | 260 public: |
| 257 enum OpKind { | 261 enum OpKind { |
| 258 #define X(tag, str, commutative) tag, | 262 #define X(tag, str, commutative) tag, |
| 259 ICEINSTARITHMETIC_TABLE | 263 ICEINSTARITHMETIC_TABLE |
| 260 #undef X | 264 #undef X |
| 261 _num | 265 _num |
| 262 }; | 266 }; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 282 const OpKind Op; | 286 const OpKind Op; |
| 283 }; | 287 }; |
| 284 | 288 |
| 285 // Assignment instruction. The source operand is captured in | 289 // Assignment instruction. The source operand is captured in |
| 286 // getSrc(0). This is not part of the LLVM bitcode, but is a useful | 290 // getSrc(0). This is not part of the LLVM bitcode, but is a useful |
| 287 // abstraction for some of the lowering. E.g., if Phi instruction | 291 // abstraction for some of the lowering. E.g., if Phi instruction |
| 288 // lowering happens before target lowering, or for representing an | 292 // lowering happens before target lowering, or for representing an |
| 289 // Inttoptr instruction, or as an intermediate step for lowering a | 293 // Inttoptr instruction, or as an intermediate step for lowering a |
| 290 // Load instruction. | 294 // Load instruction. |
| 291 class InstAssign : public InstHighLevel { | 295 class InstAssign : public InstHighLevel { |
| 296 InstAssign() = delete; |
| 292 InstAssign(const InstAssign &) = delete; | 297 InstAssign(const InstAssign &) = delete; |
| 293 InstAssign &operator=(const InstAssign &) = delete; | 298 InstAssign &operator=(const InstAssign &) = delete; |
| 294 | 299 |
| 295 public: | 300 public: |
| 296 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 301 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
| 297 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); | 302 return new (Func->allocate<InstAssign>()) InstAssign(Func, Dest, Source); |
| 298 } | 303 } |
| 299 bool isSimpleAssign() const override { return true; } | 304 bool isSimpleAssign() const override { return true; } |
| 300 void dump(const Cfg *Func) const override; | 305 void dump(const Cfg *Func) const override; |
| 301 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } | 306 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } |
| 302 | 307 |
| 303 private: | 308 private: |
| 304 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 309 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
| 305 ~InstAssign() override {} | 310 ~InstAssign() override {} |
| 306 }; | 311 }; |
| 307 | 312 |
| 308 // Branch instruction. This represents both conditional and | 313 // Branch instruction. This represents both conditional and |
| 309 // unconditional branches. | 314 // unconditional branches. |
| 310 class InstBr : public InstHighLevel { | 315 class InstBr : public InstHighLevel { |
| 316 InstBr() = delete; |
| 311 InstBr(const InstBr &) = delete; | 317 InstBr(const InstBr &) = delete; |
| 312 InstBr &operator=(const InstBr &) = delete; | 318 InstBr &operator=(const InstBr &) = delete; |
| 313 | 319 |
| 314 public: | 320 public: |
| 315 // Create a conditional branch. If TargetTrue==TargetFalse, it is | 321 // Create a conditional branch. If TargetTrue==TargetFalse, it is |
| 316 // optimized to an unconditional branch. | 322 // optimized to an unconditional branch. |
| 317 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 323 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |
| 318 CfgNode *TargetFalse) { | 324 CfgNode *TargetFalse) { |
| 319 return new (Func->allocate<InstBr>()) | 325 return new (Func->allocate<InstBr>()) |
| 320 InstBr(Func, Source, TargetTrue, TargetFalse); | 326 InstBr(Func, Source, TargetTrue, TargetFalse); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 347 InstBr(Cfg *Func, CfgNode *Target); | 353 InstBr(Cfg *Func, CfgNode *Target); |
| 348 ~InstBr() override {} | 354 ~InstBr() override {} |
| 349 | 355 |
| 350 CfgNode *TargetFalse; // Doubles as unconditional branch target | 356 CfgNode *TargetFalse; // Doubles as unconditional branch target |
| 351 CfgNode *TargetTrue; // nullptr if unconditional branch | 357 CfgNode *TargetTrue; // nullptr if unconditional branch |
| 352 }; | 358 }; |
| 353 | 359 |
| 354 // Call instruction. The call target is captured as getSrc(0), and | 360 // Call instruction. The call target is captured as getSrc(0), and |
| 355 // arg I is captured as getSrc(I+1). | 361 // arg I is captured as getSrc(I+1). |
| 356 class InstCall : public InstHighLevel { | 362 class InstCall : public InstHighLevel { |
| 363 InstCall() = delete; |
| 357 InstCall(const InstCall &) = delete; | 364 InstCall(const InstCall &) = delete; |
| 358 InstCall &operator=(const InstCall &) = delete; | 365 InstCall &operator=(const InstCall &) = delete; |
| 359 | 366 |
| 360 public: | 367 public: |
| 361 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 368 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 362 Operand *CallTarget, bool HasTailCall) { | 369 Operand *CallTarget, bool HasTailCall) { |
| 363 // Set HasSideEffects to true so that the call instruction can't be | 370 // Set HasSideEffects to true so that the call instruction can't be |
| 364 // dead-code eliminated. IntrinsicCalls can override this if the | 371 // dead-code eliminated. IntrinsicCalls can override this if the |
| 365 // particular intrinsic is deletable and has no side-effects. | 372 // particular intrinsic is deletable and has no side-effects. |
| 366 const bool HasSideEffects = true; | 373 const bool HasSideEffects = true; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 385 addSource(CallTarget); | 392 addSource(CallTarget); |
| 386 } | 393 } |
| 387 ~InstCall() override {} | 394 ~InstCall() override {} |
| 388 | 395 |
| 389 private: | 396 private: |
| 390 bool HasTailCall; | 397 bool HasTailCall; |
| 391 }; | 398 }; |
| 392 | 399 |
| 393 // Cast instruction (a.k.a. conversion operation). | 400 // Cast instruction (a.k.a. conversion operation). |
| 394 class InstCast : public InstHighLevel { | 401 class InstCast : public InstHighLevel { |
| 402 InstCast() = delete; |
| 395 InstCast(const InstCast &) = delete; | 403 InstCast(const InstCast &) = delete; |
| 396 InstCast &operator=(const InstCast &) = delete; | 404 InstCast &operator=(const InstCast &) = delete; |
| 397 | 405 |
| 398 public: | 406 public: |
| 399 enum OpKind { | 407 enum OpKind { |
| 400 #define X(tag, str) tag, | 408 #define X(tag, str) tag, |
| 401 ICEINSTCAST_TABLE | 409 ICEINSTCAST_TABLE |
| 402 #undef X | 410 #undef X |
| 403 _num | 411 _num |
| 404 }; | 412 }; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 415 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 423 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } |
| 416 | 424 |
| 417 private: | 425 private: |
| 418 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 426 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
| 419 ~InstCast() override {} | 427 ~InstCast() override {} |
| 420 const OpKind CastKind; | 428 const OpKind CastKind; |
| 421 }; | 429 }; |
| 422 | 430 |
| 423 // ExtractElement instruction. | 431 // ExtractElement instruction. |
| 424 class InstExtractElement : public InstHighLevel { | 432 class InstExtractElement : public InstHighLevel { |
| 433 InstExtractElement() = delete; |
| 425 InstExtractElement(const InstExtractElement &) = delete; | 434 InstExtractElement(const InstExtractElement &) = delete; |
| 426 InstExtractElement &operator=(const InstExtractElement &) = delete; | 435 InstExtractElement &operator=(const InstExtractElement &) = delete; |
| 427 | 436 |
| 428 public: | 437 public: |
| 429 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 438 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 430 Operand *Source2) { | 439 Operand *Source2) { |
| 431 return new (Func->allocate<InstExtractElement>()) | 440 return new (Func->allocate<InstExtractElement>()) |
| 432 InstExtractElement(Func, Dest, Source1, Source2); | 441 InstExtractElement(Func, Dest, Source1, Source2); |
| 433 } | 442 } |
| 434 | 443 |
| 435 void dump(const Cfg *Func) const override; | 444 void dump(const Cfg *Func) const override; |
| 436 static bool classof(const Inst *Inst) { | 445 static bool classof(const Inst *Inst) { |
| 437 return Inst->getKind() == ExtractElement; | 446 return Inst->getKind() == ExtractElement; |
| 438 } | 447 } |
| 439 | 448 |
| 440 private: | 449 private: |
| 441 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 450 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 442 Operand *Source2); | 451 Operand *Source2); |
| 443 ~InstExtractElement() override {} | 452 ~InstExtractElement() override {} |
| 444 }; | 453 }; |
| 445 | 454 |
| 446 // Floating-point comparison instruction. The source operands are | 455 // Floating-point comparison instruction. The source operands are |
| 447 // captured in getSrc(0) and getSrc(1). | 456 // captured in getSrc(0) and getSrc(1). |
| 448 class InstFcmp : public InstHighLevel { | 457 class InstFcmp : public InstHighLevel { |
| 458 InstFcmp() = delete; |
| 449 InstFcmp(const InstFcmp &) = delete; | 459 InstFcmp(const InstFcmp &) = delete; |
| 450 InstFcmp &operator=(const InstFcmp &) = delete; | 460 InstFcmp &operator=(const InstFcmp &) = delete; |
| 451 | 461 |
| 452 public: | 462 public: |
| 453 enum FCond { | 463 enum FCond { |
| 454 #define X(tag, str) tag, | 464 #define X(tag, str) tag, |
| 455 ICEINSTFCMP_TABLE | 465 ICEINSTFCMP_TABLE |
| 456 #undef X | 466 #undef X |
| 457 _num | 467 _num |
| 458 }; | 468 }; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 469 private: | 479 private: |
| 470 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 480 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
| 471 Operand *Source2); | 481 Operand *Source2); |
| 472 ~InstFcmp() override {} | 482 ~InstFcmp() override {} |
| 473 const FCond Condition; | 483 const FCond Condition; |
| 474 }; | 484 }; |
| 475 | 485 |
| 476 // Integer comparison instruction. The source operands are captured | 486 // Integer comparison instruction. The source operands are captured |
| 477 // in getSrc(0) and getSrc(1). | 487 // in getSrc(0) and getSrc(1). |
| 478 class InstIcmp : public InstHighLevel { | 488 class InstIcmp : public InstHighLevel { |
| 489 InstIcmp() = delete; |
| 479 InstIcmp(const InstIcmp &) = delete; | 490 InstIcmp(const InstIcmp &) = delete; |
| 480 InstIcmp &operator=(const InstIcmp &) = delete; | 491 InstIcmp &operator=(const InstIcmp &) = delete; |
| 481 | 492 |
| 482 public: | 493 public: |
| 483 enum ICond { | 494 enum ICond { |
| 484 #define X(tag, str) tag, | 495 #define X(tag, str) tag, |
| 485 ICEINSTICMP_TABLE | 496 ICEINSTICMP_TABLE |
| 486 #undef X | 497 #undef X |
| 487 _num | 498 _num |
| 488 }; | 499 }; |
| 489 | 500 |
| 490 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 501 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
| 491 Operand *Source1, Operand *Source2) { | 502 Operand *Source1, Operand *Source2) { |
| 492 return new (Func->allocate<InstIcmp>()) | 503 return new (Func->allocate<InstIcmp>()) |
| 493 InstIcmp(Func, Condition, Dest, Source1, Source2); | 504 InstIcmp(Func, Condition, Dest, Source1, Source2); |
| 494 } | 505 } |
| 495 ICond getCondition() const { return Condition; } | 506 ICond getCondition() const { return Condition; } |
| 496 void dump(const Cfg *Func) const override; | 507 void dump(const Cfg *Func) const override; |
| 497 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 508 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } |
| 498 | 509 |
| 499 private: | 510 private: |
| 500 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 511 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
| 501 Operand *Source2); | 512 Operand *Source2); |
| 502 ~InstIcmp() override {} | 513 ~InstIcmp() override {} |
| 503 const ICond Condition; | 514 const ICond Condition; |
| 504 }; | 515 }; |
| 505 | 516 |
| 506 // InsertElement instruction. | 517 // InsertElement instruction. |
| 507 class InstInsertElement : public InstHighLevel { | 518 class InstInsertElement : public InstHighLevel { |
| 519 InstInsertElement() = delete; |
| 508 InstInsertElement(const InstInsertElement &) = delete; | 520 InstInsertElement(const InstInsertElement &) = delete; |
| 509 InstInsertElement &operator=(const InstInsertElement &) = delete; | 521 InstInsertElement &operator=(const InstInsertElement &) = delete; |
| 510 | 522 |
| 511 public: | 523 public: |
| 512 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 524 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
| 513 Operand *Source2, Operand *Source3) { | 525 Operand *Source2, Operand *Source3) { |
| 514 return new (Func->allocate<InstInsertElement>()) | 526 return new (Func->allocate<InstInsertElement>()) |
| 515 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 527 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
| 516 } | 528 } |
| 517 | 529 |
| 518 void dump(const Cfg *Func) const override; | 530 void dump(const Cfg *Func) const override; |
| 519 static bool classof(const Inst *Inst) { | 531 static bool classof(const Inst *Inst) { |
| 520 return Inst->getKind() == InsertElement; | 532 return Inst->getKind() == InsertElement; |
| 521 } | 533 } |
| 522 | 534 |
| 523 private: | 535 private: |
| 524 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 536 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
| 525 Operand *Source2, Operand *Source3); | 537 Operand *Source2, Operand *Source3); |
| 526 ~InstInsertElement() override {} | 538 ~InstInsertElement() override {} |
| 527 }; | 539 }; |
| 528 | 540 |
| 529 // Call to an intrinsic function. The call target is captured as getSrc(0), | 541 // Call to an intrinsic function. The call target is captured as getSrc(0), |
| 530 // and arg I is captured as getSrc(I+1). | 542 // and arg I is captured as getSrc(I+1). |
| 531 class InstIntrinsicCall : public InstCall { | 543 class InstIntrinsicCall : public InstCall { |
| 544 InstIntrinsicCall() = delete; |
| 532 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | 545 InstIntrinsicCall(const InstIntrinsicCall &) = delete; |
| 533 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | 546 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; |
| 534 | 547 |
| 535 public: | 548 public: |
| 536 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 549 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 537 Operand *CallTarget, | 550 Operand *CallTarget, |
| 538 const Intrinsics::IntrinsicInfo &Info) { | 551 const Intrinsics::IntrinsicInfo &Info) { |
| 539 return new (Func->allocate<InstIntrinsicCall>()) | 552 return new (Func->allocate<InstIntrinsicCall>()) |
| 540 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 553 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
| 541 } | 554 } |
| 542 static bool classof(const Inst *Inst) { | 555 static bool classof(const Inst *Inst) { |
| 543 return Inst->getKind() == IntrinsicCall; | 556 return Inst->getKind() == IntrinsicCall; |
| 544 } | 557 } |
| 545 | 558 |
| 546 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 559 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
| 547 | 560 |
| 548 private: | 561 private: |
| 549 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 562 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
| 550 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 563 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
| 551 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, | 564 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, |
| 552 Inst::IntrinsicCall), | 565 Inst::IntrinsicCall), |
| 553 Info(Info) {} | 566 Info(Info) {} |
| 554 ~InstIntrinsicCall() override {} | 567 ~InstIntrinsicCall() override {} |
| 555 const Intrinsics::IntrinsicInfo Info; | 568 const Intrinsics::IntrinsicInfo Info; |
| 556 }; | 569 }; |
| 557 | 570 |
| 558 // Load instruction. The source address is captured in getSrc(0). | 571 // Load instruction. The source address is captured in getSrc(0). |
| 559 class InstLoad : public InstHighLevel { | 572 class InstLoad : public InstHighLevel { |
| 573 InstLoad() = delete; |
| 560 InstLoad(const InstLoad &) = delete; | 574 InstLoad(const InstLoad &) = delete; |
| 561 InstLoad &operator=(const InstLoad &) = delete; | 575 InstLoad &operator=(const InstLoad &) = delete; |
| 562 | 576 |
| 563 public: | 577 public: |
| 564 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 578 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
| 565 uint32_t Align = 1) { | 579 uint32_t Align = 1) { |
| 566 // TODO(kschimpf) Stop ignoring alignment specification. | 580 // TODO(kschimpf) Stop ignoring alignment specification. |
| 567 (void)Align; | 581 (void)Align; |
| 568 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); | 582 return new (Func->allocate<InstLoad>()) InstLoad(Func, Dest, SourceAddr); |
| 569 } | 583 } |
| 570 Operand *getSourceAddress() const { return getSrc(0); } | 584 Operand *getSourceAddress() const { return getSrc(0); } |
| 571 void dump(const Cfg *Func) const override; | 585 void dump(const Cfg *Func) const override; |
| 572 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } | 586 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } |
| 573 | 587 |
| 574 private: | 588 private: |
| 575 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 589 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
| 576 ~InstLoad() override {} | 590 ~InstLoad() override {} |
| 577 }; | 591 }; |
| 578 | 592 |
| 579 // Phi instruction. For incoming edge I, the node is Labels[I] and | 593 // Phi instruction. For incoming edge I, the node is Labels[I] and |
| 580 // the Phi source operand is getSrc(I). | 594 // the Phi source operand is getSrc(I). |
| 581 class InstPhi : public InstHighLevel { | 595 class InstPhi : public InstHighLevel { |
| 596 InstPhi() = delete; |
| 582 InstPhi(const InstPhi &) = delete; | 597 InstPhi(const InstPhi &) = delete; |
| 583 InstPhi &operator=(const InstPhi &) = delete; | 598 InstPhi &operator=(const InstPhi &) = delete; |
| 584 | 599 |
| 585 public: | 600 public: |
| 586 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 601 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
| 587 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 602 return new (Func->allocate<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
| 588 } | 603 } |
| 589 void addArgument(Operand *Source, CfgNode *Label); | 604 void addArgument(Operand *Source, CfgNode *Label); |
| 590 Operand *getOperandForTarget(CfgNode *Target) const; | 605 Operand *getOperandForTarget(CfgNode *Target) const; |
| 591 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } | 606 CfgNode *getLabel(SizeT Index) const { return Labels[Index]; } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 606 // Labels[] duplicates the InEdges[] information in the enclosing | 621 // Labels[] duplicates the InEdges[] information in the enclosing |
| 607 // CfgNode, but the Phi instruction is created before InEdges[] | 622 // CfgNode, but the Phi instruction is created before InEdges[] |
| 608 // is available, so it's more complicated to share the list. | 623 // is available, so it's more complicated to share the list. |
| 609 CfgNode **Labels; | 624 CfgNode **Labels; |
| 610 }; | 625 }; |
| 611 | 626 |
| 612 // Ret instruction. The return value is captured in getSrc(0), but if | 627 // Ret instruction. The return value is captured in getSrc(0), but if |
| 613 // there is no return value (void-type function), then | 628 // there is no return value (void-type function), then |
| 614 // getSrcSize()==0 and hasRetValue()==false. | 629 // getSrcSize()==0 and hasRetValue()==false. |
| 615 class InstRet : public InstHighLevel { | 630 class InstRet : public InstHighLevel { |
| 631 InstRet() = delete; |
| 616 InstRet(const InstRet &) = delete; | 632 InstRet(const InstRet &) = delete; |
| 617 InstRet &operator=(const InstRet &) = delete; | 633 InstRet &operator=(const InstRet &) = delete; |
| 618 | 634 |
| 619 public: | 635 public: |
| 620 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { | 636 static InstRet *create(Cfg *Func, Operand *RetValue = nullptr) { |
| 621 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); | 637 return new (Func->allocate<InstRet>()) InstRet(Func, RetValue); |
| 622 } | 638 } |
| 623 bool hasRetValue() const { return getSrcSize(); } | 639 bool hasRetValue() const { return getSrcSize(); } |
| 624 Operand *getRetValue() const { | 640 Operand *getRetValue() const { |
| 625 assert(hasRetValue()); | 641 assert(hasRetValue()); |
| 626 return getSrc(0); | 642 return getSrc(0); |
| 627 } | 643 } |
| 628 NodeList getTerminatorEdges() const override { return NodeList(); } | 644 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 629 void dump(const Cfg *Func) const override; | 645 void dump(const Cfg *Func) const override; |
| 630 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } | 646 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } |
| 631 | 647 |
| 632 private: | 648 private: |
| 633 InstRet(Cfg *Func, Operand *RetValue); | 649 InstRet(Cfg *Func, Operand *RetValue); |
| 634 ~InstRet() override {} | 650 ~InstRet() override {} |
| 635 }; | 651 }; |
| 636 | 652 |
| 637 // Select instruction. The condition, true, and false operands are captured. | 653 // Select instruction. The condition, true, and false operands are captured. |
| 638 class InstSelect : public InstHighLevel { | 654 class InstSelect : public InstHighLevel { |
| 655 InstSelect() = delete; |
| 639 InstSelect(const InstSelect &) = delete; | 656 InstSelect(const InstSelect &) = delete; |
| 640 InstSelect &operator=(const InstSelect &) = delete; | 657 InstSelect &operator=(const InstSelect &) = delete; |
| 641 | 658 |
| 642 public: | 659 public: |
| 643 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 660 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
| 644 Operand *SourceTrue, Operand *SourceFalse) { | 661 Operand *SourceTrue, Operand *SourceFalse) { |
| 645 return new (Func->allocate<InstSelect>()) | 662 return new (Func->allocate<InstSelect>()) |
| 646 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 663 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
| 647 } | 664 } |
| 648 Operand *getCondition() const { return getSrc(0); } | 665 Operand *getCondition() const { return getSrc(0); } |
| 649 Operand *getTrueOperand() const { return getSrc(1); } | 666 Operand *getTrueOperand() const { return getSrc(1); } |
| 650 Operand *getFalseOperand() const { return getSrc(2); } | 667 Operand *getFalseOperand() const { return getSrc(2); } |
| 651 void dump(const Cfg *Func) const override; | 668 void dump(const Cfg *Func) const override; |
| 652 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } | 669 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } |
| 653 | 670 |
| 654 private: | 671 private: |
| 655 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 672 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
| 656 Operand *Source2); | 673 Operand *Source2); |
| 657 ~InstSelect() override {} | 674 ~InstSelect() override {} |
| 658 }; | 675 }; |
| 659 | 676 |
| 660 // Store instruction. The address operand is captured, along with the | 677 // Store instruction. The address operand is captured, along with the |
| 661 // data operand to be stored into the address. | 678 // data operand to be stored into the address. |
| 662 class InstStore : public InstHighLevel { | 679 class InstStore : public InstHighLevel { |
| 680 InstStore() = delete; |
| 663 InstStore(const InstStore &) = delete; | 681 InstStore(const InstStore &) = delete; |
| 664 InstStore &operator=(const InstStore &) = delete; | 682 InstStore &operator=(const InstStore &) = delete; |
| 665 | 683 |
| 666 public: | 684 public: |
| 667 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, | 685 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, |
| 668 uint32_t align = 1) { | 686 uint32_t align = 1) { |
| 669 // TODO(kschimpf) Stop ignoring alignment specification. | 687 // TODO(kschimpf) Stop ignoring alignment specification. |
| 670 (void)align; | 688 (void)align; |
| 671 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); | 689 return new (Func->allocate<InstStore>()) InstStore(Func, Data, Addr); |
| 672 } | 690 } |
| 673 Operand *getAddr() const { return getSrc(1); } | 691 Operand *getAddr() const { return getSrc(1); } |
| 674 Operand *getData() const { return getSrc(0); } | 692 Operand *getData() const { return getSrc(0); } |
| 675 void dump(const Cfg *Func) const override; | 693 void dump(const Cfg *Func) const override; |
| 676 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } | 694 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } |
| 677 | 695 |
| 678 private: | 696 private: |
| 679 InstStore(Cfg *Func, Operand *Data, Operand *Addr); | 697 InstStore(Cfg *Func, Operand *Data, Operand *Addr); |
| 680 ~InstStore() override {} | 698 ~InstStore() override {} |
| 681 }; | 699 }; |
| 682 | 700 |
| 683 // Switch instruction. The single source operand is captured as | 701 // Switch instruction. The single source operand is captured as |
| 684 // getSrc(0). | 702 // getSrc(0). |
| 685 class InstSwitch : public InstHighLevel { | 703 class InstSwitch : public InstHighLevel { |
| 704 InstSwitch() = delete; |
| 686 InstSwitch(const InstSwitch &) = delete; | 705 InstSwitch(const InstSwitch &) = delete; |
| 687 InstSwitch &operator=(const InstSwitch &) = delete; | 706 InstSwitch &operator=(const InstSwitch &) = delete; |
| 688 | 707 |
| 689 public: | 708 public: |
| 690 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, | 709 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, |
| 691 CfgNode *LabelDefault) { | 710 CfgNode *LabelDefault) { |
| 692 return new (Func->allocate<InstSwitch>()) | 711 return new (Func->allocate<InstSwitch>()) |
| 693 InstSwitch(Func, NumCases, Source, LabelDefault); | 712 InstSwitch(Func, NumCases, Source, LabelDefault); |
| 694 } | 713 } |
| 695 Operand *getComparison() const { return getSrc(0); } | 714 Operand *getComparison() const { return getSrc(0); } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 720 | 739 |
| 721 CfgNode *LabelDefault; | 740 CfgNode *LabelDefault; |
| 722 SizeT NumCases; // not including the default case | 741 SizeT NumCases; // not including the default case |
| 723 uint64_t *Values; // size is NumCases | 742 uint64_t *Values; // size is NumCases |
| 724 CfgNode **Labels; // size is NumCases | 743 CfgNode **Labels; // size is NumCases |
| 725 }; | 744 }; |
| 726 | 745 |
| 727 // Unreachable instruction. This is a terminator instruction with no | 746 // Unreachable instruction. This is a terminator instruction with no |
| 728 // operands. | 747 // operands. |
| 729 class InstUnreachable : public InstHighLevel { | 748 class InstUnreachable : public InstHighLevel { |
| 749 InstUnreachable() = delete; |
| 730 InstUnreachable(const InstUnreachable &) = delete; | 750 InstUnreachable(const InstUnreachable &) = delete; |
| 731 InstUnreachable &operator=(const InstUnreachable &) = delete; | 751 InstUnreachable &operator=(const InstUnreachable &) = delete; |
| 732 | 752 |
| 733 public: | 753 public: |
| 734 static InstUnreachable *create(Cfg *Func) { | 754 static InstUnreachable *create(Cfg *Func) { |
| 735 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); | 755 return new (Func->allocate<InstUnreachable>()) InstUnreachable(Func); |
| 736 } | 756 } |
| 737 NodeList getTerminatorEdges() const override { return NodeList(); } | 757 NodeList getTerminatorEdges() const override { return NodeList(); } |
| 738 void dump(const Cfg *Func) const override; | 758 void dump(const Cfg *Func) const override; |
| 739 static bool classof(const Inst *Inst) { | 759 static bool classof(const Inst *Inst) { |
| 740 return Inst->getKind() == Unreachable; | 760 return Inst->getKind() == Unreachable; |
| 741 } | 761 } |
| 742 | 762 |
| 743 private: | 763 private: |
| 744 InstUnreachable(Cfg *Func); | 764 explicit InstUnreachable(Cfg *Func); |
| 745 ~InstUnreachable() override {} | 765 ~InstUnreachable() override {} |
| 746 }; | 766 }; |
| 747 | 767 |
| 748 // BundleLock instruction. There are no operands. Contains an option | 768 // BundleLock instruction. There are no operands. Contains an option |
| 749 // indicating whether align_to_end is specified. | 769 // indicating whether align_to_end is specified. |
| 750 class InstBundleLock : public InstHighLevel { | 770 class InstBundleLock : public InstHighLevel { |
| 771 InstBundleLock() = delete; |
| 751 InstBundleLock(const InstBundleLock &) = delete; | 772 InstBundleLock(const InstBundleLock &) = delete; |
| 752 InstBundleLock &operator=(const InstBundleLock &) = delete; | 773 InstBundleLock &operator=(const InstBundleLock &) = delete; |
| 753 | 774 |
| 754 public: | 775 public: |
| 755 enum Option { Opt_None, Opt_AlignToEnd }; | 776 enum Option { Opt_None, Opt_AlignToEnd }; |
| 756 static InstBundleLock *create(Cfg *Func, Option BundleOption) { | 777 static InstBundleLock *create(Cfg *Func, Option BundleOption) { |
| 757 return new (Func->allocate<InstBundleLock>()) | 778 return new (Func->allocate<InstBundleLock>()) |
| 758 InstBundleLock(Func, BundleOption); | 779 InstBundleLock(Func, BundleOption); |
| 759 } | 780 } |
| 760 void emit(const Cfg *Func) const override; | 781 void emit(const Cfg *Func) const override; |
| 761 void emitIAS(const Cfg * /* Func */) const override {} | 782 void emitIAS(const Cfg * /* Func */) const override {} |
| 762 void dump(const Cfg *Func) const override; | 783 void dump(const Cfg *Func) const override; |
| 763 Option getOption() const { return BundleOption; } | 784 Option getOption() const { return BundleOption; } |
| 764 static bool classof(const Inst *Inst) { | 785 static bool classof(const Inst *Inst) { |
| 765 return Inst->getKind() == BundleLock; | 786 return Inst->getKind() == BundleLock; |
| 766 } | 787 } |
| 767 | 788 |
| 768 private: | 789 private: |
| 769 Option BundleOption; | 790 Option BundleOption; |
| 770 InstBundleLock(Cfg *Func, Option BundleOption); | 791 InstBundleLock(Cfg *Func, Option BundleOption); |
| 771 ~InstBundleLock() override {} | 792 ~InstBundleLock() override {} |
| 772 }; | 793 }; |
| 773 | 794 |
| 774 // BundleUnlock instruction. There are no operands. | 795 // BundleUnlock instruction. There are no operands. |
| 775 class InstBundleUnlock : public InstHighLevel { | 796 class InstBundleUnlock : public InstHighLevel { |
| 797 InstBundleUnlock() = delete; |
| 776 InstBundleUnlock(const InstBundleUnlock &) = delete; | 798 InstBundleUnlock(const InstBundleUnlock &) = delete; |
| 777 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; | 799 InstBundleUnlock &operator=(const InstBundleUnlock &) = delete; |
| 778 | 800 |
| 779 public: | 801 public: |
| 780 static InstBundleUnlock *create(Cfg *Func) { | 802 static InstBundleUnlock *create(Cfg *Func) { |
| 781 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); | 803 return new (Func->allocate<InstBundleUnlock>()) InstBundleUnlock(Func); |
| 782 } | 804 } |
| 783 void emit(const Cfg *Func) const override; | 805 void emit(const Cfg *Func) const override; |
| 784 void emitIAS(const Cfg * /* Func */) const override {} | 806 void emitIAS(const Cfg * /* Func */) const override {} |
| 785 void dump(const Cfg *Func) const override; | 807 void dump(const Cfg *Func) const override; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 798 // instructions, but might with lowered instructions. For example, | 820 // instructions, but might with lowered instructions. For example, |
| 799 // this would be a way to represent condition flags being modified by | 821 // this would be a way to represent condition flags being modified by |
| 800 // an instruction. | 822 // an instruction. |
| 801 // | 823 // |
| 802 // It's generally useful to set the optional source operand to be the | 824 // It's generally useful to set the optional source operand to be the |
| 803 // dest variable of the instruction that actually produces the FakeDef | 825 // dest variable of the instruction that actually produces the FakeDef |
| 804 // dest. Otherwise, the original instruction could be dead-code | 826 // dest. Otherwise, the original instruction could be dead-code |
| 805 // eliminated if its dest operand is unused, and therefore the FakeDef | 827 // eliminated if its dest operand is unused, and therefore the FakeDef |
| 806 // dest wouldn't be properly initialized. | 828 // dest wouldn't be properly initialized. |
| 807 class InstFakeDef : public InstHighLevel { | 829 class InstFakeDef : public InstHighLevel { |
| 830 InstFakeDef() = delete; |
| 808 InstFakeDef(const InstFakeDef &) = delete; | 831 InstFakeDef(const InstFakeDef &) = delete; |
| 809 InstFakeDef &operator=(const InstFakeDef &) = delete; | 832 InstFakeDef &operator=(const InstFakeDef &) = delete; |
| 810 | 833 |
| 811 public: | 834 public: |
| 812 static InstFakeDef *create(Cfg *Func, Variable *Dest, | 835 static InstFakeDef *create(Cfg *Func, Variable *Dest, |
| 813 Variable *Src = nullptr) { | 836 Variable *Src = nullptr) { |
| 814 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 837 return new (Func->allocate<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
| 815 } | 838 } |
| 816 void emit(const Cfg *Func) const override; | 839 void emit(const Cfg *Func) const override; |
| 817 void emitIAS(const Cfg * /* Func */) const override {} | 840 void emitIAS(const Cfg * /* Func */) const override {} |
| 818 void dump(const Cfg *Func) const override; | 841 void dump(const Cfg *Func) const override; |
| 819 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } | 842 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
| 820 | 843 |
| 821 private: | 844 private: |
| 822 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 845 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
| 823 ~InstFakeDef() override {} | 846 ~InstFakeDef() override {} |
| 824 }; | 847 }; |
| 825 | 848 |
| 826 // FakeUse instruction. This creates a fake use of a variable, to | 849 // FakeUse instruction. This creates a fake use of a variable, to |
| 827 // keep the instruction that produces that variable from being | 850 // keep the instruction that produces that variable from being |
| 828 // dead-code eliminated. This is useful in a variety of lowering | 851 // dead-code eliminated. This is useful in a variety of lowering |
| 829 // situations. The FakeUse instruction has no dest, so it can itself | 852 // situations. The FakeUse instruction has no dest, so it can itself |
| 830 // never be dead-code eliminated. | 853 // never be dead-code eliminated. |
| 831 class InstFakeUse : public InstHighLevel { | 854 class InstFakeUse : public InstHighLevel { |
| 855 InstFakeUse() = delete; |
| 832 InstFakeUse(const InstFakeUse &) = delete; | 856 InstFakeUse(const InstFakeUse &) = delete; |
| 833 InstFakeUse &operator=(const InstFakeUse &) = delete; | 857 InstFakeUse &operator=(const InstFakeUse &) = delete; |
| 834 | 858 |
| 835 public: | 859 public: |
| 836 static InstFakeUse *create(Cfg *Func, Variable *Src) { | 860 static InstFakeUse *create(Cfg *Func, Variable *Src) { |
| 837 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); | 861 return new (Func->allocate<InstFakeUse>()) InstFakeUse(Func, Src); |
| 838 } | 862 } |
| 839 void emit(const Cfg *Func) const override; | 863 void emit(const Cfg *Func) const override; |
| 840 void emitIAS(const Cfg * /* Func */) const override {} | 864 void emitIAS(const Cfg * /* Func */) const override {} |
| 841 void dump(const Cfg *Func) const override; | 865 void dump(const Cfg *Func) const override; |
| 842 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } | 866 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
| 843 | 867 |
| 844 private: | 868 private: |
| 845 InstFakeUse(Cfg *Func, Variable *Src); | 869 InstFakeUse(Cfg *Func, Variable *Src); |
| 846 ~InstFakeUse() override {} | 870 ~InstFakeUse() override {} |
| 847 }; | 871 }; |
| 848 | 872 |
| 849 // FakeKill instruction. This "kills" a set of variables by modeling | 873 // FakeKill instruction. This "kills" a set of variables by modeling |
| 850 // a trivial live range at this instruction for each (implicit) | 874 // a trivial live range at this instruction for each (implicit) |
| 851 // variable. The primary use is to indicate that scratch registers | 875 // variable. The primary use is to indicate that scratch registers |
| 852 // are killed after a call, so that the register allocator won't | 876 // are killed after a call, so that the register allocator won't |
| 853 // assign a scratch register to a variable whose live range spans a | 877 // assign a scratch register to a variable whose live range spans a |
| 854 // call. | 878 // call. |
| 855 // | 879 // |
| 856 // The FakeKill instruction also holds a pointer to the instruction | 880 // The FakeKill instruction also holds a pointer to the instruction |
| 857 // that kills the set of variables, so that if that linked instruction | 881 // that kills the set of variables, so that if that linked instruction |
| 858 // gets dead-code eliminated, the FakeKill instruction will as well. | 882 // gets dead-code eliminated, the FakeKill instruction will as well. |
| 859 class InstFakeKill : public InstHighLevel { | 883 class InstFakeKill : public InstHighLevel { |
| 884 InstFakeKill() = delete; |
| 860 InstFakeKill(const InstFakeKill &) = delete; | 885 InstFakeKill(const InstFakeKill &) = delete; |
| 861 InstFakeKill &operator=(const InstFakeKill &) = delete; | 886 InstFakeKill &operator=(const InstFakeKill &) = delete; |
| 862 | 887 |
| 863 public: | 888 public: |
| 864 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { | 889 static InstFakeKill *create(Cfg *Func, const Inst *Linked) { |
| 865 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); | 890 return new (Func->allocate<InstFakeKill>()) InstFakeKill(Func, Linked); |
| 866 } | 891 } |
| 867 const Inst *getLinked() const { return Linked; } | 892 const Inst *getLinked() const { return Linked; } |
| 868 void emit(const Cfg *Func) const override; | 893 void emit(const Cfg *Func) const override; |
| 869 void emitIAS(const Cfg * /* Func */) const override {} | 894 void emitIAS(const Cfg * /* Func */) const override {} |
| 870 void dump(const Cfg *Func) const override; | 895 void dump(const Cfg *Func) const override; |
| 871 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } | 896 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
| 872 | 897 |
| 873 private: | 898 private: |
| 874 InstFakeKill(Cfg *Func, const Inst *Linked); | 899 InstFakeKill(Cfg *Func, const Inst *Linked); |
| 875 ~InstFakeKill() override {} | 900 ~InstFakeKill() override {} |
| 876 | 901 |
| 877 // This instruction is ignored if Linked->isDeleted() is true. | 902 // This instruction is ignored if Linked->isDeleted() is true. |
| 878 const Inst *Linked; | 903 const Inst *Linked; |
| 879 }; | 904 }; |
| 880 | 905 |
| 881 // The Target instruction is the base class for all target-specific | 906 // The Target instruction is the base class for all target-specific |
| 882 // instructions. | 907 // instructions. |
| 883 class InstTarget : public Inst { | 908 class InstTarget : public Inst { |
| 909 InstTarget() = delete; |
| 884 InstTarget(const InstTarget &) = delete; | 910 InstTarget(const InstTarget &) = delete; |
| 885 InstTarget &operator=(const InstTarget &) = delete; | 911 InstTarget &operator=(const InstTarget &) = delete; |
| 886 | 912 |
| 887 public: | 913 public: |
| 888 uint32_t getEmitInstCount() const override { return 1; } | 914 uint32_t getEmitInstCount() const override { return 1; } |
| 889 void dump(const Cfg *Func) const override; | 915 void dump(const Cfg *Func) const override; |
| 890 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 916 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
| 891 | 917 |
| 892 protected: | 918 protected: |
| 893 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 919 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 914 static void noteHead(Ice::Inst *, Ice::Inst *) {} | 940 static void noteHead(Ice::Inst *, Ice::Inst *) {} |
| 915 void deleteNode(Ice::Inst *) {} | 941 void deleteNode(Ice::Inst *) {} |
| 916 | 942 |
| 917 private: | 943 private: |
| 918 mutable ilist_half_node<Ice::Inst> Sentinel; | 944 mutable ilist_half_node<Ice::Inst> Sentinel; |
| 919 }; | 945 }; |
| 920 | 946 |
| 921 } // end of namespace llvm | 947 } // end of namespace llvm |
| 922 | 948 |
| 923 #endif // SUBZERO_SRC_ICEINST_H | 949 #endif // SUBZERO_SRC_ICEINST_H |
| OLD | NEW |