| //===- PMOMemoryUseCollector.h - Memory use information for PMO -*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See https://swift.org/LICENSE.txt for license information |
| // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// \file |
| /// |
| /// High Level Overview |
| /// ------------------- |
| /// |
| /// This file declares logic that is used by the predictable memory optimization |
| /// pass. Like definite initialization, it is tuple element sensitive instead of |
| /// relying on an SROA optimization or the like to chop up structs. |
| /// |
| /// NOTE: PMO is an abbreviation for "Predictable Memory Optimizations". |
| /// |
| /// Historical Note |
| /// --------------- |
| /// |
| /// This file looks very similar to DIMemoryUseCollector.* and has many |
| /// connections to Definite Initialization. This is because early in the |
| /// development of Swift, Predictable Memory Optimizations and Definite |
| /// Initialization were actually the same pass. The pass grew really big and the |
| /// two passes were split, but still used similra utility code. This became the |
| /// original DIMemoryUseCollector.*. This code was full of conditional logic for |
| /// all of the various cases that made it difficult to understand which code was |
| /// needed for Predictable Mem Opts and what was needed for DI. The introduction |
| /// of the SIL ownership model to SIL was used as an opportunity to split the |
| /// two, flatten the sphagetti conditional code so the logic was clear, and |
| /// allow the two passes to diverge and hew their form closer to their function. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_SILOPTIMIZER_MANDATORY_PMOMEMORYUSECOLLECTOR_H |
| #define SWIFT_SILOPTIMIZER_MANDATORY_PMOMEMORYUSECOLLECTOR_H |
| |
| #include "swift/Basic/LLVM.h" |
| #include "swift/SIL/SILInstruction.h" |
| #include "swift/SIL/SILType.h" |
| #include "llvm/ADT/APInt.h" |
| #include "llvm/Support/Compiler.h" |
| |
| namespace swift { |
| |
| class SILBuilder; |
| |
| /// PMOMemoryObjectInfo - This struct holds information about the memory object |
| /// being analyzed that is required to correctly break it down into elements. |
| /// |
| /// This includes a collection of utilities for reasoning about (potentially |
| /// recursively) exploded aggregate elements, and computing access paths and |
| /// indexes into the flattened namespace. |
| /// |
| /// The flattened namespace is assigned lexicographically. For example, in: |
| /// (Int, ((Float, (), Double))) |
| /// the Int member is numbered 0, the Float is numbered 1, and the Double is |
| /// numbered 2. Empty tuples don't get numbered since they contain no state. |
| /// |
| /// Structs and classes have their elements exploded when we are analyzing the |
| /// 'self' member in an initializer for the aggregate. |
| /// |
| /// Derived classes have an additional field at the end that models whether or |
| /// not super.init() has been called or not. |
| class PMOMemoryObjectInfo { |
| public: |
| /// This is the instruction that represents the memory. It is either an |
| /// alloc_box or alloc_stack. |
| AllocationInst *MemoryInst; |
| |
| /// This is the base type of the memory allocation. |
| SILType MemorySILType; |
| |
| public: |
| PMOMemoryObjectInfo(AllocationInst *MemoryInst); |
| |
| SILLocation getLoc() const { return MemoryInst->getLoc(); } |
| SILFunction &getFunction() const { return *MemoryInst->getFunction(); } |
| |
| /// Return the first instruction of the function containing the memory object. |
| SILInstruction *getFunctionEntryPoint() const; |
| |
| CanType getType() const { return MemorySILType.getASTType(); } |
| |
| SingleValueInstruction *getAddress() const { |
| if (isa<AllocStackInst>(MemoryInst)) |
| return MemoryInst; |
| assert(false); |
| return nullptr; |
| } |
| |
| AllocBoxInst *getContainer() const { |
| return dyn_cast<AllocBoxInst>(MemoryInst); |
| } |
| }; |
| |
| enum PMOUseKind { |
| /// The instruction is a Load. |
| Load, |
| |
| /// The instruction is either an initialization or an assignment, we don't |
| /// know which. This classification only happens with values of trivial type |
| /// where the different isn't significant. |
| InitOrAssign, |
| |
| /// The instruction is an initialization of the tuple element. |
| Initialization, |
| |
| /// The instruction is an assignment, overwriting an already initialized |
| /// value. |
| Assign, |
| |
| /// The instruction is a store to a member of a larger struct value. |
| PartialStore, |
| |
| /// An indirect 'inout' parameter of an Apply instruction. |
| InOutUse, |
| |
| /// An indirect 'in' parameter of an Apply instruction. |
| IndirectIn, |
| |
| /// This instruction is a general escape of the value, e.g. a call to a |
| /// closure that captures it. |
| Escape, |
| }; |
| |
| /// This struct represents a single classified access to the memory object |
| /// being analyzed, along with classification information about the access. |
| struct PMOMemoryUse { |
| /// This is the instruction accessing the memory. |
| SILInstruction *Inst; |
| |
| /// This is what kind of access it is, load, store, escape, etc. |
| PMOUseKind Kind; |
| |
| PMOMemoryUse(SILInstruction *Inst, PMOUseKind Kind) |
| : Inst(Inst), Kind(Kind) {} |
| |
| PMOMemoryUse() : Inst(nullptr) {} |
| |
| bool isInvalid() const { return Inst == nullptr; } |
| bool isValid() const { return Inst != nullptr; } |
| }; |
| |
| /// collectPMOElementUsesFrom - Analyze all uses of the specified allocation |
| /// instruction (alloc_box, alloc_stack or mark_uninitialized), classifying them |
| /// and storing the information found into the Uses and Releases lists. |
| LLVM_NODISCARD bool |
| collectPMOElementUsesFrom(const PMOMemoryObjectInfo &MemoryInfo, |
| SmallVectorImpl<PMOMemoryUse> &Uses, |
| SmallVectorImpl<SILInstruction *> &Releases); |
| |
| } // end namespace swift |
| |
| #endif |