|
98 | 98 |
|
99 | 99 | #include "swift/Basic/GraphNodeWorklist.h"
|
100 | 100 | #include "swift/Basic/SmallPtrSetVector.h"
|
| 101 | +#include "swift/Basic/TaggedUnion.h" |
101 | 102 | #include "swift/SIL/PrunedLiveness.h"
|
102 | 103 | #include "swift/SIL/SILInstruction.h"
|
103 | 104 | #include "swift/SILOptimizer/Analysis/DeadEndBlocksAnalysis.h"
|
@@ -279,8 +280,74 @@ class CanonicalizeOSSALifetime final {
|
279 | 280 | /// outside the pruned liveness at the time it is discovered.
|
280 | 281 | llvm::SmallPtrSet<DebugValueInst *, 8> debugValues;
|
281 | 282 |
|
| 283 | + class Def { |
| 284 | + struct Root { |
| 285 | + SILValue value; |
| 286 | + }; |
| 287 | + struct Copy { |
| 288 | + CopyValueInst *cvi; |
| 289 | + }; |
| 290 | + struct BorrowedFrom { |
| 291 | + BorrowedFromInst *bfi; |
| 292 | + }; |
| 293 | + struct Reborrow { |
| 294 | + SILArgument *argument; |
| 295 | + }; |
| 296 | + using Payload = TaggedUnion<Root, Copy, BorrowedFrom, Reborrow>; |
| 297 | + Payload payload; |
| 298 | + Def(Payload payload) : payload(payload) {} |
| 299 | + |
| 300 | + public: |
| 301 | + enum class Kind { |
| 302 | + Root, |
| 303 | + Copy, |
| 304 | + BorrowedFrom, |
| 305 | + Reborrow, |
| 306 | + }; |
| 307 | + Kind getKind() const { |
| 308 | + if (payload.isa<Root>()) { |
| 309 | + return Kind::Root; |
| 310 | + } |
| 311 | + if (payload.isa<Copy>()) { |
| 312 | + return Kind::Copy; |
| 313 | + } |
| 314 | + if (payload.isa<BorrowedFrom>()) { |
| 315 | + return Kind::BorrowedFrom; |
| 316 | + } |
| 317 | + assert(payload.isa<Reborrow>()); |
| 318 | + return Kind::Reborrow; |
| 319 | + } |
| 320 | + operator Kind() const { return getKind(); } |
| 321 | + bool operator==(Def rhs) const { |
| 322 | + return getKind() == rhs.getKind() && getValue() == rhs.getValue(); |
| 323 | + } |
| 324 | + static Def root(SILValue value) { return {Root{value}}; } |
| 325 | + static Def copy(CopyValueInst *cvi) { return {Copy{cvi}}; } |
| 326 | + static Def borrowedFrom(BorrowedFromInst *bfi) { |
| 327 | + return {BorrowedFrom{bfi}}; |
| 328 | + } |
| 329 | + static Def reborrow(SILArgument *argument) { return {Reborrow{argument}}; } |
| 330 | + SILValue getValue() const { |
| 331 | + switch (*this) { |
| 332 | + case Kind::Root: |
| 333 | + return payload.get<Root>().value; |
| 334 | + case Kind::Copy: |
| 335 | + return payload.get<Copy>().cvi; |
| 336 | + case Kind::BorrowedFrom: |
| 337 | + return payload.get<BorrowedFrom>().bfi; |
| 338 | + case Kind::Reborrow: |
| 339 | + return payload.get<Reborrow>().argument; |
| 340 | + } |
| 341 | + llvm_unreachable("covered switch"); |
| 342 | + } |
| 343 | + }; |
| 344 | + friend llvm::DenseMapInfo<Def>; |
| 345 | + friend llvm::PointerLikeTypeTraits<Def>; |
| 346 | + friend llvm::PointerLikeTypeTraits< |
| 347 | + std::optional<swift::CanonicalizeOSSALifetime::Def>>; |
| 348 | + |
282 | 349 | /// Visited set for general def-use traversal that prevents revisiting values.
|
283 |
| - GraphNodeWorklist<SILValue, 8> defUseWorklist; |
| 350 | + GraphNodeWorklist<std::optional<Def>, 8> defUseWorklist; |
284 | 351 |
|
285 | 352 | /// The blocks that were discovered by PrunedLiveness.
|
286 | 353 | SmallVector<SILBasicBlock *, 32> discoveredBlocks;
|
@@ -496,4 +563,94 @@ class CanonicalizeOSSALifetime final {
|
496 | 563 |
|
497 | 564 | } // end namespace swift
|
498 | 565 |
|
| 566 | +namespace llvm { |
| 567 | +template <> |
| 568 | +struct DenseMapInfo<swift::CanonicalizeOSSALifetime::Def> { |
| 569 | + static swift::CanonicalizeOSSALifetime::Def getEmptyKey() { |
| 570 | + return swift::CanonicalizeOSSALifetime::Def::root( |
| 571 | + DenseMapInfo<swift::SILValue>::getEmptyKey()); |
| 572 | + } |
| 573 | + static swift::CanonicalizeOSSALifetime::Def getTombstoneKey() { |
| 574 | + return swift::CanonicalizeOSSALifetime::Def::root( |
| 575 | + DenseMapInfo<swift::SILValue>::getTombstoneKey()); |
| 576 | + } |
| 577 | + static unsigned getHashValue(swift::CanonicalizeOSSALifetime::Def def) { |
| 578 | + return detail::combineHashValue( |
| 579 | + DenseMapInfo<swift::CanonicalizeOSSALifetime::Def::Kind>::getHashValue( |
| 580 | + def.getKind()), |
| 581 | + DenseMapInfo<swift::SILValue>::getHashValue(def.getValue())); |
| 582 | + } |
| 583 | + static bool isEqual(swift::CanonicalizeOSSALifetime::Def LHS, |
| 584 | + swift::CanonicalizeOSSALifetime::Def RHS) { |
| 585 | + return LHS == RHS; |
| 586 | + } |
| 587 | +}; |
| 588 | +template <> |
| 589 | +struct PointerLikeTypeTraits<swift::CanonicalizeOSSALifetime::Def> { |
| 590 | +private: |
| 591 | + using Def = swift::CanonicalizeOSSALifetime::Def; |
| 592 | + |
| 593 | +public: |
| 594 | + static void *getAsVoidPointer(Def def) { |
| 595 | + return reinterpret_cast<void *>( |
| 596 | + reinterpret_cast<uintptr_t>(def.getValue().getOpaqueValue()) | |
| 597 | + ((uintptr_t)def.getKind()) << NumLowBitsAvailable); |
| 598 | + } |
| 599 | + static Def getFromVoidPointer(void *p) { |
| 600 | + auto kind = (Def::Kind)((reinterpret_cast<uintptr_t>(p) & 0b110) >> |
| 601 | + NumLowBitsAvailable); |
| 602 | + auto opaque = |
| 603 | + reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) & ~0b111); |
| 604 | + auto value = swift::SILValue::getFromOpaqueValue(opaque); |
| 605 | + switch (kind) { |
| 606 | + case Def::Kind::Root: |
| 607 | + return Def::root(value); |
| 608 | + case Def::Kind::Copy: |
| 609 | + return Def::copy(cast<swift::CopyValueInst>(value)); |
| 610 | + case Def::Kind::Reborrow: |
| 611 | + return Def::reborrow(cast<swift::SILArgument>(value)); |
| 612 | + case Def::Kind::BorrowedFrom: |
| 613 | + return Def::borrowedFrom(cast<swift::BorrowedFromInst>(value)); |
| 614 | + } |
| 615 | + } |
| 616 | + |
| 617 | + enum { |
| 618 | + NumLowBitsAvailable = |
| 619 | + llvm::PointerLikeTypeTraits<swift::SILValue>::NumLowBitsAvailable - 2 |
| 620 | + }; |
| 621 | +}; |
| 622 | +template <> |
| 623 | +struct PointerLikeTypeTraits< |
| 624 | + std::optional<swift::CanonicalizeOSSALifetime::Def>> { |
| 625 | +private: |
| 626 | + using Def = swift::CanonicalizeOSSALifetime::Def; |
| 627 | + using Payload = std::optional<Def>; |
| 628 | + |
| 629 | +public: |
| 630 | + static void *getAsVoidPointer(Payload payload) { |
| 631 | + if (!payload) |
| 632 | + return 0x0; |
| 633 | + return reinterpret_cast<void *>( |
| 634 | + reinterpret_cast<uintptr_t>( |
| 635 | + PointerLikeTypeTraits<swift::CanonicalizeOSSALifetime::Def>:: |
| 636 | + getAsVoidPointer(*payload)) | |
| 637 | + 0b1); |
| 638 | + } |
| 639 | + static Payload getFromVoidPointer(void *p) { |
| 640 | + auto none = reinterpret_cast<uintptr_t>(p) & 0b1; |
| 641 | + if (none) |
| 642 | + return std::nullopt; |
| 643 | + auto opaque = |
| 644 | + reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(p) & ~0b1); |
| 645 | + return {PointerLikeTypeTraits< |
| 646 | + swift::CanonicalizeOSSALifetime::Def>::getFromVoidPointer(opaque)}; |
| 647 | + } |
| 648 | + |
| 649 | + enum { |
| 650 | + NumLowBitsAvailable = |
| 651 | + llvm::PointerLikeTypeTraits<Def>::NumLowBitsAvailable - 1 |
| 652 | + }; |
| 653 | +}; |
| 654 | +} // end namespace llvm |
| 655 | + |
499 | 656 | #endif
|
0 commit comments