From bddc69c8a69ce8d8c73df478dba80d8e8a5e6760 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Sat, 28 Sep 2019 00:35:14 -0700 Subject: [PATCH 1/4] Organize SILOptimizer/Utils headers. Remove Local.h. The XXOptUtils.h convention is already established and parallels the SIL/XXUtils convention. New: - InstOptUtils.h - CFGOptUtils.h - BasicBlockOptUtils.h - ValueLifetime.h Removed: - Local.h - Two conflicting CFG.h files This reorganization is helpful before I introduce more utilities for block cloning similar to SinkAddressProjections. Move the control flow utilies out of Local.h, which was an unreadable, unprincipled mess. Rename it to InstOptUtils.h, and confine it to small APIs for working with individual instructions. These are the optimizer's additions to /SIL/InstUtils.h. Rename CFG.h to CFGOptUtils.h and remove the one in /Analysis. Now there is only SIL/CFG.h, resolving the naming conflict within the swift project (this has always been a problem for source tools). Limit this header to low-level APIs for working with branches and CFG edges. Add BasicBlockOptUtils.h for block level transforms (it makes me sad that I can't use BBOptUtils.h, but SIL already has BasicBlockUtils.h). These are larger APIs for cloning or removing whole blocks. --- include/swift/SIL/SILInstructionWorklist.h | 2 +- include/swift/SIL/TypeSubstCloner.h | 4 +- include/swift/SILOptimizer/Analysis/CFG.h | 50 -- .../SILOptimizer/Analysis/CallerAnalysis.h | 2 +- .../SILOptimizer/Utils/BasicBlockOptUtils.h | 260 ++++++++ .../Utils/{CFG.h => CFGOptUtils.h} | 56 +- .../swift/SILOptimizer/Utils/Devirtualize.h | 2 +- .../swift/SILOptimizer/Utils/GenericCloner.h | 2 +- include/swift/SILOptimizer/Utils/Generics.h | 2 +- .../Utils/{Local.h => InstOptUtils.h} | 386 ++---------- .../SILOptimizer/Utils/LoadStoreOptUtils.h | 2 +- .../swift/SILOptimizer/Utils/ValueLifetime.h | 123 ++++ lib/IRGen/LoadableByAddress.cpp | 2 +- lib/SILOptimizer/ARC/ARCMatchingSet.cpp | 12 +- lib/SILOptimizer/ARC/ARCSequenceOpts.cpp | 22 +- lib/SILOptimizer/Analysis/ARCAnalysis.cpp | 6 +- lib/SILOptimizer/Analysis/AliasAnalysis.cpp | 16 +- lib/SILOptimizer/Analysis/Analysis.cpp | 12 +- lib/SILOptimizer/Analysis/ArraySemantic.cpp | 6 +- .../Analysis/BasicCalleeAnalysis.cpp | 3 +- lib/SILOptimizer/Analysis/CFG.cpp | 107 ---- lib/SILOptimizer/Analysis/CMakeLists.txt | 1 - lib/SILOptimizer/Analysis/CallerAnalysis.cpp | 3 +- lib/SILOptimizer/Analysis/EscapeAnalysis.cpp | 8 +- .../Analysis/SimplifyInstruction.cpp | 2 +- .../Analysis/TypeExpansionAnalysis.cpp | 2 +- lib/SILOptimizer/Analysis/ValueTracking.cpp | 8 +- .../ExistentialSpecializer.cpp | 2 +- .../ExistentialTransform.cpp | 3 +- .../ExistentialTransform.h | 2 +- .../FunctionSignatureOpts.cpp | 4 +- .../FunctionSignatureOpts.h | 2 +- lib/SILOptimizer/IPO/CapturePropagation.cpp | 4 +- lib/SILOptimizer/IPO/ClosureSpecializer.cpp | 7 +- .../IPO/DeadFunctionElimination.cpp | 8 +- lib/SILOptimizer/IPO/GlobalOpt.cpp | 6 +- lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp | 12 +- lib/SILOptimizer/IPO/LetPropertiesOpts.cpp | 3 +- lib/SILOptimizer/IPO/UsePrespecialized.cpp | 14 +- .../LoopTransforms/ArrayBoundsCheckOpts.cpp | 20 +- .../LoopTransforms/COWArrayOpt.cpp | 14 +- lib/SILOptimizer/LoopTransforms/LICM.cpp | 4 +- .../LoopTransforms/LoopRotate.cpp | 11 +- .../Mandatory/AddressLowering.cpp | 2 +- .../Mandatory/ClosureLifetimeFixup.cpp | 4 +- .../Mandatory/DefiniteInitialization.cpp | 4 +- .../Mandatory/DiagnoseUnreachable.cpp | 4 +- lib/SILOptimizer/Mandatory/IRGenPrepare.cpp | 2 +- .../Mandatory/MandatoryCombine.cpp | 2 +- .../Mandatory/MandatoryInlining.cpp | 4 +- .../Mandatory/OSLogOptimization.cpp | 2 +- .../Mandatory/PredictableMemOpt.cpp | 2 +- lib/SILOptimizer/Mandatory/SILGenCleanup.cpp | 2 +- .../Mandatory/SemanticARCOpts.cpp | 2 +- lib/SILOptimizer/PassManager/PassPipeline.cpp | 2 +- lib/SILOptimizer/PassManager/Passes.cpp | 4 +- lib/SILOptimizer/SILCombiner/SILCombine.cpp | 2 +- lib/SILOptimizer/SILCombiner/SILCombiner.h | 2 +- .../SILCombiner/SILCombinerApplyVisitors.cpp | 3 +- .../SILCombinerBuiltinVisitors.cpp | 10 +- .../SILCombiner/SILCombinerCastVisitors.cpp | 10 +- .../SILCombiner/SILCombinerMiscVisitors.cpp | 4 +- lib/SILOptimizer/Transforms/ARCCodeMotion.cpp | 4 +- .../Transforms/AccessEnforcementDom.cpp | 2 +- .../Transforms/AccessEnforcementOpts.cpp | 2 +- .../Transforms/AccessEnforcementWMO.cpp | 2 +- .../Transforms/AllocBoxToStack.cpp | 5 +- .../Transforms/AssumeSingleThreaded.cpp | 4 +- lib/SILOptimizer/Transforms/CSE.cpp | 13 +- .../Transforms/CopyForwarding.cpp | 2 +- .../Transforms/CopyPropagation.cpp | 4 +- .../Transforms/DeadCodeElimination.cpp | 6 +- .../Transforms/DeadObjectElimination.cpp | 15 +- .../Transforms/DeadStoreElimination.cpp | 8 +- .../Transforms/DestroyHoisting.cpp | 4 +- .../Transforms/GenericSpecializer.cpp | 4 +- lib/SILOptimizer/Transforms/MergeCondFail.cpp | 6 +- .../Transforms/ObjectOutliner.cpp | 4 +- .../Transforms/OwnershipModelEliminator.cpp | 2 +- .../Transforms/PerformanceInliner.cpp | 2 +- .../Transforms/RedundantLoadElimination.cpp | 6 +- .../RedundantOverflowCheckRemoval.cpp | 6 +- lib/SILOptimizer/Transforms/SILCodeMotion.cpp | 6 +- .../Transforms/SILLowerAggregateInstrs.cpp | 2 +- lib/SILOptimizer/Transforms/SILMem2Reg.cpp | 14 +- lib/SILOptimizer/Transforms/SILSROA.cpp | 2 +- lib/SILOptimizer/Transforms/SimplifyCFG.cpp | 128 +--- lib/SILOptimizer/Transforms/Sink.cpp | 20 +- .../Transforms/SpecializeOpaqueArchetypes.cpp | 4 +- .../Transforms/StackPromotion.cpp | 15 +- .../Transforms/UnsafeGuaranteedPeephole.cpp | 4 +- lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp | 243 ++++++++ .../Utils/{CFG.cpp => CFGOptUtils.cpp} | 248 +++++--- lib/SILOptimizer/Utils/CMakeLists.txt | 6 +- lib/SILOptimizer/Utils/CastOptimizer.cpp | 10 +- .../Utils/CheckedCastBrJumpThreading.cpp | 13 +- lib/SILOptimizer/Utils/ConstantFolding.cpp | 3 +- lib/SILOptimizer/Utils/Devirtualize.cpp | 6 +- lib/SILOptimizer/Utils/Existential.cpp | 4 +- lib/SILOptimizer/Utils/GenericCloner.cpp | 4 +- .../Utils/{Local.cpp => InstOptUtils.cpp} | 553 ++++-------------- lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp | 2 +- lib/SILOptimizer/Utils/LoopUtils.cpp | 2 +- .../Utils/PerformanceInlinerUtils.cpp | 2 +- lib/SILOptimizer/Utils/SILInliner.cpp | 2 +- lib/SILOptimizer/Utils/SILSSAUpdater.cpp | 13 +- lib/SILOptimizer/Utils/ValueLifetime.cpp | 251 ++++++++ 107 files changed, 1514 insertions(+), 1428 deletions(-) delete mode 100644 include/swift/SILOptimizer/Analysis/CFG.h create mode 100644 include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h rename include/swift/SILOptimizer/Utils/{CFG.h => CFGOptUtils.h} (83%) rename include/swift/SILOptimizer/Utils/{Local.h => InstOptUtils.h} (52%) create mode 100644 include/swift/SILOptimizer/Utils/ValueLifetime.h delete mode 100644 lib/SILOptimizer/Analysis/CFG.cpp create mode 100644 lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp rename lib/SILOptimizer/Utils/{CFG.cpp => CFGOptUtils.cpp} (78%) rename lib/SILOptimizer/Utils/{Local.cpp => InstOptUtils.cpp} (74%) create mode 100644 lib/SILOptimizer/Utils/ValueLifetime.cpp diff --git a/include/swift/SIL/SILInstructionWorklist.h b/include/swift/SIL/SILInstructionWorklist.h index af43d47bf4a..36af8225211 100644 --- a/include/swift/SIL/SILInstructionWorklist.h +++ b/include/swift/SIL/SILInstructionWorklist.h @@ -33,7 +33,7 @@ #include "swift/Basic/BlotSetVector.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILValue.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/swift/SIL/TypeSubstCloner.h b/include/swift/SIL/TypeSubstCloner.h index 5bca456a3f4..3bbb363945a 100644 --- a/include/swift/SIL/TypeSubstCloner.h +++ b/include/swift/SIL/TypeSubstCloner.h @@ -21,10 +21,10 @@ #include "swift/AST/GenericEnvironment.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/Type.h" -#include "swift/SIL/SILCloner.h" #include "swift/SIL/DynamicCasts.h" +#include "swift/SIL/SILCloner.h" #include "swift/SIL/SILFunctionBuilder.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/Support/Debug.h" diff --git a/include/swift/SILOptimizer/Analysis/CFG.h b/include/swift/SILOptimizer/Analysis/CFG.h deleted file mode 100644 index 2f8b195b1e0..00000000000 --- a/include/swift/SILOptimizer/Analysis/CFG.h +++ /dev/null @@ -1,50 +0,0 @@ -//===--- CFG.h - Routines which analyze the CFG of a function ---*- 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 -// -//===----------------------------------------------------------------------===// - -#ifndef SWIFT_SILOPTIMIZER_ANALYSIS_CFG_H -#define SWIFT_SILOPTIMIZER_ANALYSIS_CFG_H - -namespace llvm { - -template class TinyPtrVector; - -} // end namespace llvm - -namespace swift { - -class SILFunction; -class SILBasicBlock; - -/// Return true if we conservatively find all BB's that are non-failure exit -/// basic blocks and place them in \p BBs. If we find something we don't -/// understand, bail. -/// -/// A non-failure exit BB is defined as a BB that: -/// -/// 1. Has a return terminator. -/// 2. unreachable + noreturn terminator sequence. -/// 3. has a throw terminator. -/// -/// If we just have an unreachable without a noreturn call before it, we must -/// have a failure BB. -/// -/// We use a TinyPtrVector since in most cases this will only return one -/// SILBasicBlock since non-failure noreturn functions should not occur often -/// implying in most cases this will be one element. -/// -/// TODO: -bool findAllNonFailureExitBBs(SILFunction *F, - llvm::TinyPtrVector &BBs); - -} // end namespace swift - -#endif diff --git a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h index b23570c2e49..b2a722f3ed6 100644 --- a/include/swift/SILOptimizer/Analysis/CallerAnalysis.h +++ b/include/swift/SILOptimizer/Analysis/CallerAnalysis.h @@ -17,7 +17,7 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/Analysis/Analysis.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallSet.h" diff --git a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h new file mode 100644 index 00000000000..8b6e07bcc42 --- /dev/null +++ b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h @@ -0,0 +1,260 @@ +//===--- BasicBlockOptUtils.h - SIL basic block utilities -------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// +/// +/// Utilities used by the SILOptimizer for analyzing and operating on whole +/// basic blocks, including as removal, cloning, and SSA update. +/// +/// CFGOptUtils.h provides lower-level CFG branch and edge utilities. +/// +/// SIL/BasicBlockUtils.h provides essential SILBasicBlock utilities. +/// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H +#define SWIFT_SILOPTIMIZER_UTILS_BASICBLOCKOPTUTILS_H + +#include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILBasicBlock.h" +#include "swift/SIL/SILCloner.h" + +namespace swift { + +class BasicBlockCloner; +class SILLoop; +class SILLoopInfo; + +/// Remove all instructions in the body of \p BB in safe manner by using +/// undef. +void clearBlockBody(SILBasicBlock *BB); + +/// Handle the mechanical aspects of removing an unreachable block. +void removeDeadBlock(SILBasicBlock *BB); + +/// Remove all unreachable blocks in a function. +bool removeUnreachableBlocks(SILFunction &Fn); + +/// Return true if there are any users of V outside the specified block. +inline bool isUsedOutsideOfBlock(SILValue V) { + auto *BB = V->getParentBlock(); + for (auto UI : V->getUses()) + if (UI->getUser()->getParent() != BB) + return true; + return false; +} + +/// Rotate a loop's header as long as it is exiting and not equal to the +/// passed basic block. +/// If \p RotateSingleBlockLoops is true a single basic block loop will be +/// rotated once. ShouldVerify specifies whether to perform verification after +/// the transformation. +/// Returns true if the loop could be rotated. +bool rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, + bool RotateSingleBlockLoops, SILBasicBlock *UpTo, + bool ShouldVerify); + +/// Helper function to perform SSA updates in case of jump threading. +void updateSSAAfterCloning(BasicBlockCloner &Cloner, SILBasicBlock *SrcBB, + SILBasicBlock *DestBB); + +/// Clone a single basic block and any required successor edges within the same +/// function. +class BasicBlockCloner : public SILCloner { + using SuperTy = SILCloner; + friend class SILCloner; + +protected: + /// The original block to be cloned. + SILBasicBlock *origBB; + +public: + /// An ordered list of old to new available value pairs. + /// + /// updateSSAAfterCloning() expects this public field to hold values that may + /// be remapped in the cloned block and live out. + SmallVector, 16> AvailVals; + + // Clone blocks starting at `origBB`, within the same function. + BasicBlockCloner(SILBasicBlock *origBB) + : SILCloner(*origBB->getParent()), origBB(origBB) {} + + void cloneBlock(SILBasicBlock *insertAfterBB = nullptr) { + SmallVector successorBBs; + successorBBs.reserve(origBB->getSuccessors().size()); + llvm::copy(origBB->getSuccessors(), std::back_inserter(successorBBs)); + cloneReachableBlocks(origBB, successorBBs, insertAfterBB); + } + + /// Clone the given branch instruction's destination block, splitting + /// its successors, and rewrite the branch instruction. + void cloneBranchTarget(BranchInst *BI) { + assert(origBB == BI->getDestBB()); + + cloneBlock(/*insertAfter*/BI->getParent()); + + SILBuilderWithScope(BI).createBranch(BI->getLoc(), getNewBB(), + BI->getArgs()); + BI->eraseFromParent(); + } + + /// Get the newly cloned block corresponding to `origBB`. + SILBasicBlock *getNewBB() { + return remapBasicBlock(origBB); + } + + /// Call this after processing all instructions to fix the control flow + /// graph. The branch cloner may have left critical edges. + bool splitCriticalEdges(DominanceInfo *DT, SILLoopInfo *LI); + +protected: + // MARK: CRTP overrides. + + /// Override getMappedValue to allow values defined outside the block to be + /// cloned to be reused in the newly cloned block. + SILValue getMappedValue(SILValue Value) { + if (auto SI = Value->getDefiningInstruction()) { + if (!isBlockCloned(SI->getParent())) + return Value; + } else if (auto BBArg = dyn_cast(Value)) { + if (!isBlockCloned(BBArg->getParent())) + return Value; + } else { + assert(isa(Value) && "Unexpected Value kind"); + return Value; + } + // `value` is not defined outside the cloned block, so consult the cloner's + // map of cloned values. + return SuperTy::getMappedValue(Value); + } + + void mapValue(SILValue origValue, SILValue mappedValue) { + SuperTy::mapValue(origValue, mappedValue); + AvailVals.emplace_back(origValue, mappedValue); + } +}; + +// Helper class that provides a callback that can be used in +// inliners/cloners for collecting new call sites. +class CloneCollector { +public: + typedef std::pair value_type; + typedef std::function CallbackType; + typedef std::function FilterType; + +private: + FilterType Filter; + + // Pairs of collected instructions; (new, old) + llvm::SmallVector InstructionPairs; + + void collect(SILInstruction *Old, SILInstruction *New) { + if (Filter(New)) + InstructionPairs.push_back(std::make_pair(New, Old)); + } + +public: + CloneCollector(FilterType Filter) : Filter(Filter) {} + + CallbackType getCallback() { + return std::bind(&CloneCollector::collect, this, std::placeholders::_1, + std::placeholders::_2); + } + + llvm::SmallVectorImpl &getInstructionPairs() { + return InstructionPairs; + } +}; + +/// Sink address projections to their out-of-block uses. This is +/// required after cloning a block and before calling +/// updateSSAAfterCloning to avoid address-type phis. +/// +/// This clones address projections at their use points, but does not +/// mutate the block containing the projections. +class SinkAddressProjections { + // Projections ordered from last to first in the chain. + SmallVector projections; + SmallSetVector inBlockDefs; + +public: + /// Check for an address projection chain ending at \p inst. Return true if + /// the given instruction is successfully analyzed. + /// + /// If \p inst does not produce an address, then return + /// true. getInBlockDefs() will contain \p inst if any of its + /// (non-address) values are used outside its block. + /// + /// If \p inst does produce an address, return true only of the + /// chain of address projections within this block is clonable at + /// their use sites. getInBlockDefs will return all non-address + /// operands in the chain that are also defined in this block. These + /// may require phis after cloning the projections. + bool analyzeAddressProjections(SILInstruction *inst); + + /// After analyzing projections, returns the list of (non-address) values + /// defined in the same block as the projections which will have uses outside + /// the block after cloning. + ArrayRef getInBlockDefs() const { + return inBlockDefs.getArrayRef(); + } + /// Clone the chain of projections at their use sites. + /// + /// Return true if anything was done. + /// + /// getInBlockProjectionOperandValues() can be called before or after cloning. + bool cloneProjections(); +}; + +/// Utility class for cloning init values into the static initializer of a +/// SILGlobalVariable. +class StaticInitCloner : public SILCloner { + friend class SILInstructionVisitor; + friend class SILCloner; + + /// The number of not yet cloned operands for each instruction. + llvm::DenseMap NumOpsToClone; + + /// List of instructions for which all operands are already cloned (or which + /// don't have any operands). + llvm::SmallVector ReadyToClone; + +public: + StaticInitCloner(SILGlobalVariable *GVar) + : SILCloner(GVar) { } + + /// Add \p InitVal and all its operands (transitively) for cloning. + /// + /// Note: all init values must are added, before calling clone(). + void add(SILInstruction *InitVal); + + /// Clone \p InitVal and all its operands into the initializer of the + /// SILGlobalVariable. + /// + /// \return Returns the cloned instruction in the SILGlobalVariable. + SingleValueInstruction *clone(SingleValueInstruction *InitVal); + + /// Convenience function to clone a single \p InitVal. + static void appendToInitializer(SILGlobalVariable *GVar, + SingleValueInstruction *InitVal) { + StaticInitCloner Cloner(GVar); + Cloner.add(InitVal); + Cloner.clone(InitVal); + } + +protected: + SILLocation remapLocation(SILLocation Loc) { + return ArtificialUnreachableLocation(); + } +}; + +} // namespace swift + +#endif diff --git a/include/swift/SILOptimizer/Utils/CFG.h b/include/swift/SILOptimizer/Utils/CFGOptUtils.h similarity index 83% rename from include/swift/SILOptimizer/Utils/CFG.h rename to include/swift/SILOptimizer/Utils/CFGOptUtils.h index ceaea27b91f..d67ba9267a7 100644 --- a/include/swift/SILOptimizer/Utils/CFG.h +++ b/include/swift/SILOptimizer/Utils/CFGOptUtils.h @@ -1,20 +1,34 @@ -//===--- CFG.h - Utilities for SIL CFG transformations ----------*- C++ -*-===// +//===--- CFGOptUtils.h - SIL CFG edge utilities -----------------*- C++ -*-===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2019 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 // //===----------------------------------------------------------------------===// +/// +/// APIs used by the SILOptimizer for low-level branch and CFG edge analysis +/// and operations. These may merge blocks, split blocks, or create empty +/// blocks, but don't duplicate whole blocks. +/// +/// Essential CFG utilities are in SIL/CFG.h. +/// +/// Whole block-level transformations are in BasicBlockOptUtils.h. +/// +//===----------------------------------------------------------------------===// -#ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H -#define SWIFT_SILOPTIMIZER_UTILS_CFG_H +#ifndef SWIFT_SILOPTIMIZER_UTILS_CFGOPTUTILS_H +#define SWIFT_SILOPTIMIZER_UTILS_CFGOPTUTILS_H -#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILInstruction.h" + +namespace llvm { +template class TinyPtrVector; +} namespace swift { @@ -98,16 +112,6 @@ bool splitCriticalEdgesFrom(SILBasicBlock *fromBB, DominanceInfo *DT = nullptr, void splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To, DominanceInfo *DT = nullptr, SILLoopInfo *LI = nullptr); -/// Rotate a loop's header as long as it is exiting and not equal to the -/// passed basic block. -/// If \p RotateSingleBlockLoops is true a single basic block loop will be -/// rotated once. ShouldVerify specifies whether to perform verification after -/// the transformation. -/// Returns true if the loop could be rotated. -bool rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, - bool RotateSingleBlockLoops, SILBasicBlock *UpTo, - bool ShouldVerify); - /// Splits the basic block before the instruction with an unconditional branch /// and updates the dominator tree and loop info. Returns the new, branched to /// block that contains the end of \p SplitBeforeInst's block. @@ -180,8 +184,26 @@ void completeJointPostDominanceSet( ArrayRef UserBlocks, ArrayRef DefBlocks, llvm::SmallVectorImpl &Completion); -/// Remove all unreachable blocks in a function. -bool removeUnreachableBlocks(SILFunction &Fn); +/// Return true if we conservatively find all BB's that are non-failure exit +/// basic blocks and place them in \p BBs. If we find something we don't +/// understand, bail. +/// +/// A non-failure exit BB is defined as a BB that: +/// +/// 1. Has a return terminator. +/// 2. unreachable + noreturn terminator sequence. +/// 3. has a throw terminator. +/// +/// If we just have an unreachable without a noreturn call before it, we must +/// have a failure BB. +/// +/// We use a TinyPtrVector since in most cases this will only return one +/// SILBasicBlock since non-failure noreturn functions should not occur often +/// implying in most cases this will be one element. +/// +/// TODO: +bool findAllNonFailureExitBBs(SILFunction *F, + llvm::TinyPtrVector &BBs); } // end namespace swift diff --git a/include/swift/SILOptimizer/Utils/Devirtualize.h b/include/swift/SILOptimizer/Utils/Devirtualize.h index d99810f951c..6301c64725e 100644 --- a/include/swift/SILOptimizer/Utils/Devirtualize.h +++ b/include/swift/SILOptimizer/Utils/Devirtualize.h @@ -27,7 +27,7 @@ #include "swift/SIL/SILType.h" #include "swift/SIL/SILValue.h" #include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/ArrayRef.h" namespace swift { diff --git a/include/swift/SILOptimizer/Utils/GenericCloner.h b/include/swift/SILOptimizer/Utils/GenericCloner.h index 1c54bdecf16..ea0d3aa617d 100644 --- a/include/swift/SILOptimizer/Utils/GenericCloner.h +++ b/include/swift/SILOptimizer/Utils/GenericCloner.h @@ -22,7 +22,7 @@ #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/TypeSubstCloner.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" #include "swift/SILOptimizer/Utils/Generics.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" diff --git a/include/swift/SILOptimizer/Utils/Generics.h b/include/swift/SILOptimizer/Utils/Generics.h index 3c78e3c6a1a..50c80b51578 100644 --- a/include/swift/SILOptimizer/Utils/Generics.h +++ b/include/swift/SILOptimizer/Utils/Generics.h @@ -20,7 +20,7 @@ #include "swift/AST/SubstitutionMap.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/include/swift/SILOptimizer/Utils/Local.h b/include/swift/SILOptimizer/Utils/InstOptUtils.h similarity index 52% rename from include/swift/SILOptimizer/Utils/Local.h rename to include/swift/SILOptimizer/Utils/InstOptUtils.h index c7a33d8afa0..de2521a9a9a 100644 --- a/include/swift/SILOptimizer/Utils/Local.h +++ b/include/swift/SILOptimizer/Utils/InstOptUtils.h @@ -1,27 +1,32 @@ -//===--- Local.h - Local SIL transformations. -------------------*- C++ -*-===// +//===--- InstOptUtils.h - SILOptimizer instruction utilities ----*- C++ -*-===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2019 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 // //===----------------------------------------------------------------------===// +/// +/// Utilities used by the SILOptimizer for analyzing and transforming +/// SILInstructions. +/// +/// SIL/InstUtils.h provides essential SILInstruction utilities. +/// +//===----------------------------------------------------------------------===// -#ifndef SWIFT_SILOPTIMIZER_UTILS_LOCAL_H -#define SWIFT_SILOPTIMIZER_UTILS_LOCAL_H +#ifndef SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H +#define SWIFT_SILOPTIMIZER_UTILS_INSTOPTUTILS_H -#include "swift/SILOptimizer/Analysis/ARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" -#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" -#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILBuilder.h" -#include "swift/SIL/SILCloner.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Analysis/ARCAnalysis.h" +#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" +#include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h" +#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/Support/Allocator.h" #include #include @@ -33,10 +38,10 @@ template class NullablePtr; /// Transform a Use Range (Operand*) into a User Range (SILInstruction*) using UserTransform = std::function; using ValueBaseUserRange = - TransformRange, UserTransform>; + TransformRange, UserTransform>; -inline ValueBaseUserRange makeUserRange( - iterator_range R) { +inline ValueBaseUserRange +makeUserRange(iterator_range R) { auto toUser = [](Operand *O) { return O->getUser(); }; return makeTransformRange(makeIteratorRange(R.begin(), R.end()), UserTransform(toUser)); @@ -59,10 +64,9 @@ NullablePtr createDecrementBefore(SILValue Ptr, /// \param Force If Force is set, don't check if the top level instructions /// are considered dead - delete them regardless. /// \param C a callback called whenever an instruction is deleted. -void -recursivelyDeleteTriviallyDeadInstructions( - ArrayRef I, bool Force = false, - llvm::function_ref C = [](SILInstruction *){}); +void recursivelyDeleteTriviallyDeadInstructions( + ArrayRef I, bool Force = false, + llvm::function_ref C = [](SILInstruction *) {}); /// If the given instruction is dead, delete it along with its dead /// operands. @@ -86,14 +90,14 @@ bool isIntermediateRelease(SILInstruction *I, EpilogueARCFunctionInfo *ERFI); /// Recursively collect all the uses and transitive uses of the /// instruction. -void -collectUsesOfValue(SILValue V, llvm::SmallPtrSetImpl &Insts); +void collectUsesOfValue(SILValue V, + llvm::SmallPtrSetImpl &Insts); /// Recursively erase all of the uses of the instruction (but not the /// instruction itself) void eraseUsesOfInstruction( SILInstruction *Inst, - llvm::function_ref C = [](SILInstruction *){}); + llvm::function_ref C = [](SILInstruction *) {}); /// Recursively erase all of the uses of the value (but not the /// value itself) @@ -107,8 +111,7 @@ FullApplySite findApplyFromDevirtualizedResult(SILValue value); /// - actual return type and expected return type differ in optionality. /// - both types are tuple-types and some of the elements need to be casted. SILValue castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, - SILValue Value, - SILType SrcTy, + SILValue Value, SILType SrcTy, SILType DestTy); /// Peek through trivial Enum initialization, typically for pointless /// Optionals. @@ -139,13 +142,6 @@ void placeFuncRef(ApplyInst *AI, DominanceInfo *DT); TermInst *addArgumentToBranch(SILValue Val, SILBasicBlock *Dest, TermInst *Branch); -/// Handle the mechanical aspects of removing an unreachable block. -void removeDeadBlock(SILBasicBlock *BB); - -/// Remove all instructions in the body of \p BB in safe manner by using -/// undef. -void clearBlockBody(SILBasicBlock *BB); - /// Get the linkage to be used for specializations of a function with /// the given linkage. SILLinkage getSpecializedLinkage(SILFunction *F, SILLinkage L); @@ -156,20 +152,19 @@ SingleValueInstruction *tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B); /// Tries to perform jump-threading on all checked_cast_br instruction in /// function \p Fn. -bool tryCheckedCastBrJumpThreading(SILFunction *Fn, DominanceInfo *DT, - SmallVectorImpl &BlocksForWorklist); +bool tryCheckedCastBrJumpThreading( + SILFunction *Fn, DominanceInfo *DT, + SmallVectorImpl &BlocksForWorklist); /// A structure containing callbacks that are called when an instruction is /// removed or added. struct InstModCallbacks { - using CallbackTy = std::function; - CallbackTy DeleteInst = [](SILInstruction *I) { - I->eraseFromParent(); - }; - CallbackTy CreatedNewInst = [](SILInstruction *){}; + using CallbackTy = std::function; + CallbackTy DeleteInst = [](SILInstruction *I) { I->eraseFromParent(); }; + CallbackTy CreatedNewInst = [](SILInstruction *) {}; InstModCallbacks(CallbackTy DeleteInst, CallbackTy CreatedNewInst) - : DeleteInst(DeleteInst), CreatedNewInst(CreatedNewInst) {} + : DeleteInst(DeleteInst), CreatedNewInst(CreatedNewInst) {} InstModCallbacks() = default; ~InstModCallbacks() = default; InstModCallbacks(const InstModCallbacks &) = default; @@ -184,9 +179,8 @@ struct InstModCallbacks { /// captured args if we have a partial_apply. /// /// In the future this should be extended to be less conservative with users. -bool -tryDeleteDeadClosure(SingleValueInstruction *Closure, - InstModCallbacks Callbacks = InstModCallbacks()); +bool tryDeleteDeadClosure(SingleValueInstruction *Closure, + InstModCallbacks Callbacks = InstModCallbacks()); /// Given a SILValue argument to a partial apply \p Arg and the associated /// parameter info for that argument, perform the necessary cleanups to Arg when @@ -201,253 +195,6 @@ void insertDestroyOfCapturedArguments( llvm::function_ref shouldInsertDestroy = [](SILValue arg) -> bool { return true; }); -/// This computes the lifetime of a single SILValue. -/// -/// This does not compute a set of jointly postdominating use points. Instead it -/// assumes that the value's existing uses already jointly postdominate the -/// definition. This makes sense for values that are returned +1 from an -/// instruction, like partial_apply, and therefore must be released on all paths -/// via strong_release or apply. -class ValueLifetimeAnalysis { -public: - - /// The lifetime frontier for the value. It is the list of instructions - /// following the last uses of the value. All the frontier instructions - /// end the value's lifetime. - typedef llvm::SmallVector Frontier; - - /// Constructor for the value \p Def with a specific set of users of Def's - /// users. - ValueLifetimeAnalysis(SILInstruction *Def, ArrayRef UserList) : - DefValue(Def), UserSet(UserList.begin(), UserList.end()) { - propagateLiveness(); - } - - /// Constructor for the value \p Def considering all the value's uses. - ValueLifetimeAnalysis(SILInstruction *Def) : DefValue(Def) { - for (auto result : Def->getResults()) { - for (Operand *op : result->getUses()) { - UserSet.insert(op->getUser()); - } - } - propagateLiveness(); - } - - enum Mode { - /// Don't split critical edges if the frontier instructions are located on - /// a critical edges. Instead fail. - DontModifyCFG, - - /// Split critical edges if the frontier instructions are located on - /// a critical edges. - AllowToModifyCFG, - - /// Require that all users must commonly post-dominate the definition. In - /// other words: All paths from the definition to the function exit must - /// contain at least one use. Fail if this is not the case. - UsersMustPostDomDef - }; - - /// Computes and returns the lifetime frontier for the value in \p Fr. - /// - /// Returns true if all instructions in the frontier could be found in - /// non-critical edges. - /// Returns false if some frontier instructions are located on critical edges. - /// In this case, if \p mode is AllowToModifyCFG, those critical edges are - /// split, otherwise nothing is done and the returned \p Fr is not valid. - /// - /// If \p deadEndBlocks is provided, all dead-end blocks are ignored. This - /// prevents unreachable-blocks to be included in the frontier. - bool computeFrontier(Frontier &Fr, Mode mode, - DeadEndBlocks *DEBlocks = nullptr); - - /// Returns true if the instruction \p Inst is located within the value's - /// lifetime. - /// It is assumed that \p Inst is located after the value's definition. - bool isWithinLifetime(SILInstruction *Inst); - - /// Returns true if the value is alive at the begin of block \p BB. - bool isAliveAtBeginOfBlock(SILBasicBlock *BB) { - return LiveBlocks.count(BB) && BB != DefValue->getParent(); - } - - /// Checks if there is a dealloc_ref inside the value's live range. - bool containsDeallocRef(const Frontier &Frontier); - - /// For debug dumping. - void dump() const; - -private: - - /// The value. - SILInstruction *DefValue; - - /// The set of blocks where the value is live. - llvm::SmallSetVector LiveBlocks; - - /// The set of instructions where the value is used, or the users-list - /// provided with the constructor. - llvm::SmallPtrSet UserSet; - - /// Propagates the liveness information up the control flow graph. - void propagateLiveness(); - - /// Returns the last use of the value in the live block \p BB. - SILInstruction *findLastUserInBlock(SILBasicBlock *BB); -}; - -/// Clone a single basic block and any required successor edges within the same -/// function. -class BasicBlockCloner : public SILCloner { - using SuperTy = SILCloner; - friend class SILCloner; - -protected: - /// The original block to be cloned. - SILBasicBlock *origBB; - -public: - /// An ordered list of old to new available value pairs. - /// - /// updateSSAAfterCloning() expects this public field to hold values that may - /// be remapped in the cloned block and live out. - SmallVector, 16> AvailVals; - - // Clone blocks starting at `origBB`, within the same function. - BasicBlockCloner(SILBasicBlock *origBB) - : SILCloner(*origBB->getParent()), origBB(origBB) {} - - void cloneBlock(SILBasicBlock *insertAfterBB = nullptr) { - SmallVector successorBBs; - successorBBs.reserve(origBB->getSuccessors().size()); - llvm::copy(origBB->getSuccessors(), std::back_inserter(successorBBs)); - cloneReachableBlocks(origBB, successorBBs, insertAfterBB); - } - - /// Clone the given branch instruction's destination block, splitting - /// its successors, and rewrite the branch instruction. - void cloneBranchTarget(BranchInst *BI) { - assert(origBB == BI->getDestBB()); - - cloneBlock(/*insertAfter*/BI->getParent()); - - SILBuilderWithScope(BI).createBranch(BI->getLoc(), getNewBB(), - BI->getArgs()); - BI->eraseFromParent(); - } - - /// Get the newly cloned block corresponding to `origBB`. - SILBasicBlock *getNewBB() { - return remapBasicBlock(origBB); - } - - /// Call this after processing all instructions to fix the control flow - /// graph. The branch cloner may have left critical edges. - bool splitCriticalEdges(DominanceInfo *DT, SILLoopInfo *LI); - -protected: - // MARK: CRTP overrides. - - /// Override getMappedValue to allow values defined outside the block to be - /// cloned to be reused in the newly cloned block. - SILValue getMappedValue(SILValue Value) { - if (auto SI = Value->getDefiningInstruction()) { - if (!isBlockCloned(SI->getParent())) - return Value; - } else if (auto BBArg = dyn_cast(Value)) { - if (!isBlockCloned(BBArg->getParent())) - return Value; - } else { - assert(isa(Value) && "Unexpected Value kind"); - return Value; - } - // `value` is not defined outside the cloned block, so consult the cloner's - // map of cloned values. - return SuperTy::getMappedValue(Value); - } - - void mapValue(SILValue origValue, SILValue mappedValue) { - SuperTy::mapValue(origValue, mappedValue); - AvailVals.emplace_back(origValue, mappedValue); - } -}; - -/// Sink address projections to their out-of-block uses. This is -/// required after cloning a block and before calling -/// updateSSAAfterCloning to avoid address-type phis. -/// -/// This clones address projections at their use points, but does not -/// mutate the block containing the projections. -class SinkAddressProjections { - // Projections ordered from last to first in the chain. - SmallVector projections; - SmallSetVector inBlockDefs; - -public: - /// Check for an address projection chain ending at \p inst. Return true if - /// the given instruction is successfully analyzed. - /// - /// If \p inst does not produce an address, then return - /// true. getInBlockDefs() will contain \p inst if any of its - /// (non-address) values are used outside its block. - /// - /// If \p inst does produce an address, return true only of the - /// chain of address projections within this block is clonable at - /// their use sites. getInBlockDefs will return all non-address - /// operands in the chain that are also defined in this block. These - /// may require phis after cloning the projections. - bool analyzeAddressProjections(SILInstruction *inst); - - /// After analyzing projections, returns the list of (non-address) values - /// defined in the same block as the projections which will have uses outside - /// the block after cloning. - ArrayRef getInBlockDefs() const { - return inBlockDefs.getArrayRef(); - } - /// Clone the chain of projections at their use sites. - /// - /// Return true if anything was done. - /// - /// getInBlockProjectionOperandValues() can be called before or after cloning. - bool cloneProjections(); -}; - -/// Helper function to perform SSA updates in case of jump threading. -void updateSSAAfterCloning(BasicBlockCloner &Cloner, SILBasicBlock *SrcBB, - SILBasicBlock *DestBB); - -// Helper class that provides a callback that can be used in -// inliners/cloners for collecting new call sites. -class CloneCollector { -public: - typedef std::pair value_type; - typedef std::function CallbackType; - typedef std::function FilterType; - -private: - FilterType Filter; - - // Pairs of collected instructions; (new, old) - llvm::SmallVector InstructionPairs; - - void collect(SILInstruction *Old, SILInstruction *New) { - if (Filter(New)) - InstructionPairs.push_back(std::make_pair(New, Old)); - } - -public: - CloneCollector(FilterType Filter) : Filter(Filter) {} - - CallbackType getCallback() { - return std::bind(&CloneCollector::collect, this, std::placeholders::_1, - std::placeholders::_2); - } - - llvm::SmallVectorImpl &getInstructionPairs() { - return InstructionPairs; - } -}; - /// This iterator 'looks through' one level of builtin expect users exposing all /// users of the looked through builtin expect instruction i.e it presents a /// view that shows all users as if there were no builtin expect instructions @@ -467,10 +214,11 @@ class IgnoreExpectUseIterator // Advance through expect users to their users until we encounter a user that // is not an expect. void advanceThroughExpects() { - while (CurrentIter == OrigUseChain && - CurrentIter != ValueBaseUseIterator(nullptr)) { + while (CurrentIter == OrigUseChain + && CurrentIter != ValueBaseUseIterator(nullptr)) { auto *Expect = isExpect(*CurrentIter); - if (!Expect) return; + if (!Expect) + return; CurrentIter = Expect->use_begin(); // Expect with no users advance to next item in original use chain. if (CurrentIter == Expect->use_end()) @@ -498,7 +246,7 @@ public: ++CurrentIter; // Ignore expects. advanceThroughExpects(); - } else { + } else { // Use chain of an expect. ++CurrentIter; if (CurrentIter == ValueBaseUseIterator(nullptr)) { @@ -527,8 +275,7 @@ public: inline iterator_range ignore_expect_uses(ValueBase *V) { - return make_range(IgnoreExpectUseIterator(V), - IgnoreExpectUseIterator()); + return make_range(IgnoreExpectUseIterator(V), IgnoreExpectUseIterator()); } /// Run simplifyInstruction() on all of the instruction I's users if they only @@ -560,9 +307,7 @@ bool canReplaceLoadSequence(SILInstruction *I); /// a chain of struct_element_addr followed by a load. /// The sequence is traversed inside out, i.e. /// starting with the innermost struct_element_addr -void replaceLoadSequence(SILInstruction *I, - SILValue Value); - +void replaceLoadSequence(SILInstruction *I, SILValue Value); /// Do we have enough information to determine all callees that could /// be reached by calling the function represented by Decl? @@ -580,8 +325,7 @@ SILValue getInstanceWithExactDynamicType(SILValue S, /// Try to determine the exact dynamic type of an object. /// returns the exact dynamic type of the object, or an empty type if the exact /// type could not be determined. -SILType getExactDynamicType(SILValue S, - ClassHierarchyAnalysis *CHA, +SILType getExactDynamicType(SILValue S, ClassHierarchyAnalysis *CHA, bool ForUnderlyingObject = false); /// Try to statically determine the exact dynamic type of the underlying object. @@ -590,49 +334,7 @@ SILType getExactDynamicType(SILValue S, SILType getExactDynamicTypeOfUnderlyingObject(SILValue S, ClassHierarchyAnalysis *CHA); -/// Utility class for cloning init values into the static initializer of a -/// SILGlobalVariable. -class StaticInitCloner : public SILCloner { - friend class SILInstructionVisitor; - friend class SILCloner; - - /// The number of not yet cloned operands for each instruction. - llvm::DenseMap NumOpsToClone; - - /// List of instructions for which all operands are already cloned (or which - /// don't have any operands). - llvm::SmallVector ReadyToClone; - -public: - StaticInitCloner(SILGlobalVariable *GVar) - : SILCloner(GVar) { } - - /// Add \p InitVal and all its operands (transitively) for cloning. - /// - /// Note: all init values must are added, before calling clone(). - void add(SILInstruction *InitVal); - - /// Clone \p InitVal and all its operands into the initializer of the - /// SILGlobalVariable. - /// - /// \return Returns the cloned instruction in the SILGlobalVariable. - SingleValueInstruction *clone(SingleValueInstruction *InitVal); - - /// Convenience function to clone a single \p InitVal. - static void appendToInitializer(SILGlobalVariable *GVar, - SingleValueInstruction *InitVal) { - StaticInitCloner Cloner(GVar); - Cloner.add(InitVal); - Cloner.clone(InitVal); - } - -protected: - SILLocation remapLocation(SILLocation Loc) { - return ArtificialUnreachableLocation(); - } -}; - -/// Move only data structure that is the result of findLocalApplySite. +// Move only data structure that is the result of findLocalApplySite. /// /// NOTE: Generally it is not suggested to have move only types that contain /// small vectors. Since our small vectors contain one element or a std::vector diff --git a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h index 5613af10681..f11fbcd3042 100644 --- a/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h +++ b/include/swift/SILOptimizer/Utils/LoadStoreOptUtils.h @@ -33,7 +33,7 @@ #include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" #include "swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Hashing.h" diff --git a/include/swift/SILOptimizer/Utils/ValueLifetime.h b/include/swift/SILOptimizer/Utils/ValueLifetime.h new file mode 100644 index 00000000000..b0215ce7d82 --- /dev/null +++ b/include/swift/SILOptimizer/Utils/ValueLifetime.h @@ -0,0 +1,123 @@ +//===--- ValueLifetime.h - ValueLifetimeAnalysis ----------------*- C++ -*-===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// +/// +/// Utilities used by the SILOptimizer for SSA analysis and update. +/// +//===----------------------------------------------------------------------===// + +#ifndef SWIFT_SILOPTIMIZER_UTILS_CFG_H +#define SWIFT_SILOPTIMIZER_UTILS_CFG_H + +#include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILBuilder.h" + +namespace swift { + +/// This computes the lifetime of a single SILValue. +/// +/// This does not compute a set of jointly postdominating use points. Instead it +/// assumes that the value's existing uses already jointly postdominate the +/// definition. This makes sense for values that are returned +1 from an +/// instruction, like partial_apply, and therefore must be released on all paths +/// via strong_release or apply. +class ValueLifetimeAnalysis { +public: + + /// The lifetime frontier for the value. It is the list of instructions + /// following the last uses of the value. All the frontier instructions + /// end the value's lifetime. + typedef llvm::SmallVector Frontier; + + /// Constructor for the value \p Def with a specific set of users of Def's + /// users. + ValueLifetimeAnalysis(SILInstruction *Def, ArrayRef UserList) : + DefValue(Def), UserSet(UserList.begin(), UserList.end()) { + propagateLiveness(); + } + + /// Constructor for the value \p Def considering all the value's uses. + ValueLifetimeAnalysis(SILInstruction *Def) : DefValue(Def) { + for (auto result : Def->getResults()) { + for (Operand *op : result->getUses()) { + UserSet.insert(op->getUser()); + } + } + propagateLiveness(); + } + + enum Mode { + /// Don't split critical edges if the frontier instructions are located on + /// a critical edges. Instead fail. + DontModifyCFG, + + /// Split critical edges if the frontier instructions are located on + /// a critical edges. + AllowToModifyCFG, + + /// Require that all users must commonly post-dominate the definition. In + /// other words: All paths from the definition to the function exit must + /// contain at least one use. Fail if this is not the case. + UsersMustPostDomDef + }; + + /// Computes and returns the lifetime frontier for the value in \p Fr. + /// + /// Returns true if all instructions in the frontier could be found in + /// non-critical edges. + /// Returns false if some frontier instructions are located on critical edges. + /// In this case, if \p mode is AllowToModifyCFG, those critical edges are + /// split, otherwise nothing is done and the returned \p Fr is not valid. + /// + /// If \p deadEndBlocks is provided, all dead-end blocks are ignored. This + /// prevents unreachable-blocks to be included in the frontier. + bool computeFrontier(Frontier &Fr, Mode mode, + DeadEndBlocks *DEBlocks = nullptr); + + /// Returns true if the instruction \p Inst is located within the value's + /// lifetime. + /// It is assumed that \p Inst is located after the value's definition. + bool isWithinLifetime(SILInstruction *Inst); + + /// Returns true if the value is alive at the begin of block \p BB. + bool isAliveAtBeginOfBlock(SILBasicBlock *BB) { + return LiveBlocks.count(BB) && BB != DefValue->getParent(); + } + + /// Checks if there is a dealloc_ref inside the value's live range. + bool containsDeallocRef(const Frontier &Frontier); + + /// For debug dumping. + void dump() const; + +private: + + /// The value. + SILInstruction *DefValue; + + /// The set of blocks where the value is live. + llvm::SmallSetVector LiveBlocks; + + /// The set of instructions where the value is used, or the users-list + /// provided with the constructor. + llvm::SmallPtrSet UserSet; + + /// Propagates the liveness information up the control flow graph. + void propagateLiveness(); + + /// Returns the last use of the value in the live block \p BB. + SILInstruction *findLastUserInBlock(SILBasicBlock *BB); +}; + + +} // end namespace swift + +#endif diff --git a/lib/IRGen/LoadableByAddress.cpp b/lib/IRGen/LoadableByAddress.cpp index 2e01eaa55e7..4a3b79b25f3 100644 --- a/lib/IRGen/LoadableByAddress.cpp +++ b/lib/IRGen/LoadableByAddress.cpp @@ -27,7 +27,7 @@ #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/ARC/ARCMatchingSet.cpp b/lib/SILOptimizer/ARC/ARCMatchingSet.cpp index dff2579427d..442a4c9011b 100644 --- a/lib/SILOptimizer/ARC/ARCMatchingSet.cpp +++ b/lib/SILOptimizer/ARC/ARCMatchingSet.cpp @@ -12,24 +12,24 @@ #define DEBUG_TYPE "arc-sequence-opts" -#include "RefCountState.h" #include "ARCMatchingSet.h" +#include "RefCountState.h" #include "swift/Basic/BlotMapVector.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Debug.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp b/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp index f4e0cdc07c4..00d284761f6 100644 --- a/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp +++ b/lib/SILOptimizer/ARC/ARCSequenceOpts.cpp @@ -12,28 +12,28 @@ #define DEBUG_TYPE "arc-sequence-opts" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "ARCSequenceOpts.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/LoopUtils.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/EpilogueARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/ProgramTerminationAnalysis.h" -#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" -#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" -#include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h" #include "swift/SILOptimizer/Analysis/LoopAnalysis.h" +#include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h" +#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" +#include "swift/SILOptimizer/Analysis/ProgramTerminationAnalysis.h" +#include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/LoopUtils.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Debug.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp index 74d1ceb5ffd..f600f0d0523 100644 --- a/lib/SILOptimizer/Analysis/ARCAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/ARCAnalysis.cpp @@ -15,16 +15,16 @@ #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/InstructionUtils.h" +#include "swift/SIL/Projection.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" -#include "swift/SIL/Projection.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "llvm/ADT/StringSwitch.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp index acbd467d374..b70518c0b81 100644 --- a/lib/SILOptimizer/Analysis/AliasAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/AliasAnalysis.cpp @@ -12,18 +12,18 @@ #define DEBUG_TYPE "sil-aa" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" -#include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Analysis/SideEffectAnalysis.h" -#include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/PassManager/PassManager.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/Projection.h" -#include "swift/SIL/SILValue.h" -#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILFunction.h" +#include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" -#include "swift/SIL/InstructionUtils.h" +#include "swift/SIL/SILValue.h" +#include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" +#include "swift/SILOptimizer/Analysis/SideEffectAnalysis.h" +#include "swift/SILOptimizer/Analysis/ValueTracking.h" +#include "swift/SILOptimizer/PassManager/PassManager.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/SILOptimizer/Analysis/Analysis.cpp b/lib/SILOptimizer/Analysis/Analysis.cpp index 2fc7354f9ec..ac1b76de4bb 100644 --- a/lib/SILOptimizer/Analysis/Analysis.cpp +++ b/lib/SILOptimizer/Analysis/Analysis.cpp @@ -12,19 +12,19 @@ #define DEBUG_TYPE "sil-analysis" #include "swift/SILOptimizer/Analysis/Analysis.h" +#include "swift/AST/Module.h" +#include "swift/AST/SILOptions.h" +#include "swift/SIL/SILFunction.h" +#include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" +#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/IVAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" -#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" #include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h" -#include "swift/AST/Module.h" -#include "swift/AST/SILOptions.h" -#include "swift/SIL/SILModule.h" -#include "swift/SIL/SILFunction.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" -#include "swift/SILOptimizer/Utils/Local.h" using namespace swift; diff --git a/lib/SILOptimizer/Analysis/ArraySemantic.cpp b/lib/SILOptimizer/Analysis/ArraySemantic.cpp index e01864c3089..52282d2a7cf 100644 --- a/lib/SILOptimizer/Analysis/ArraySemantic.cpp +++ b/lib/SILOptimizer/Analysis/ArraySemantic.cpp @@ -10,14 +10,14 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/StringSwitch.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" -#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILFunction.h" +#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "llvm/ADT/StringSwitch.h" using namespace swift; diff --git a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp index 5aae7d49271..904518a21b8 100644 --- a/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/BasicCalleeAnalysis.cpp @@ -13,9 +13,10 @@ #include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" #include "swift/AST/Decl.h" +#include "swift/AST/ProtocolConformance.h" #include "swift/Basic/Statistic.h" #include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/Compiler.h" #include diff --git a/lib/SILOptimizer/Analysis/CFG.cpp b/lib/SILOptimizer/Analysis/CFG.cpp deleted file mode 100644 index a079be8ce56..00000000000 --- a/lib/SILOptimizer/Analysis/CFG.cpp +++ /dev/null @@ -1,107 +0,0 @@ -//===--- CFG.cpp ----------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "swift/SILOptimizer/Analysis/CFG.h" -#include "swift/SIL/SILFunction.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/SILValue.h" -#include "swift/Demangling/ManglingMacros.h" -#include "llvm/ADT/TinyPtrVector.h" - -using namespace swift; - -static bool isSafeNonExitTerminator(TermInst *TI) { - switch (TI->getTermKind()) { - case TermKind::BranchInst: - case TermKind::CondBranchInst: - case TermKind::SwitchValueInst: - case TermKind::SwitchEnumInst: - case TermKind::SwitchEnumAddrInst: - case TermKind::DynamicMethodBranchInst: - case TermKind::CheckedCastBranchInst: - case TermKind::CheckedCastValueBranchInst: - case TermKind::CheckedCastAddrBranchInst: - return true; - case TermKind::UnreachableInst: - case TermKind::ReturnInst: - case TermKind::ThrowInst: - case TermKind::UnwindInst: - return false; - // yield is special because it can do arbitrary, - // potentially-process-terminating things. - case TermKind::YieldInst: - return false; - case TermKind::TryApplyInst: - return true; - } - - llvm_unreachable("Unhandled TermKind in switch."); -} - -static bool isTrapNoReturnFunction(ApplyInst *AI) { - const char *fatalName = - MANGLE_AS_STRING(MANGLE_SYM(s18_fatalErrorMessageyys12StaticStringV_AcCSutF)); - auto *Fn = AI->getReferencedFunctionOrNull(); - - // We use endswith here since if we specialize fatal error we will always - // prepend the specialization records to fatalName. - if (!Fn || !Fn->getName().endswith(fatalName)) - return false; - - return true; -} - -bool -swift:: -findAllNonFailureExitBBs(SILFunction *F, - llvm::TinyPtrVector &BBs) { - for (SILBasicBlock &BB : *F) { - TermInst *TI = BB.getTerminator(); - - // If we know that this terminator is not an exit terminator, continue. - if (isSafeNonExitTerminator(TI)) - continue; - - // A return inst is always a non-failure exit bb. - if (TI->isFunctionExiting()) { - BBs.push_back(&BB); - continue; - } - - // If we don't have an unreachable inst at this point, this is a terminator - // we don't understand. Be conservative and return false. - if (!isa(TI)) - return false; - - // Ok, at this point we know we have a terminator. If it is the only - // instruction in our BB, it is a failure BB. continue... - if (TI == &*BB.begin()) - continue; - - // If the unreachable is preceded by a no-return apply inst, then it is a - // non-failure exit BB. Add it to our list and continue. - auto PrevIter = std::prev(SILBasicBlock::iterator(TI)); - if (auto *AI = dyn_cast(&*PrevIter)) { - if (AI->isCalleeNoReturn() && - !isTrapNoReturnFunction(AI)) { - BBs.push_back(&BB); - continue; - } - } - - // Otherwise, it must be a failure BB where we leak, continue. - continue; - } - - // We understood all terminators, return true. - return true; -} diff --git a/lib/SILOptimizer/Analysis/CMakeLists.txt b/lib/SILOptimizer/Analysis/CMakeLists.txt index 009fea5b7e3..58be25ffa01 100644 --- a/lib/SILOptimizer/Analysis/CMakeLists.txt +++ b/lib/SILOptimizer/Analysis/CMakeLists.txt @@ -7,7 +7,6 @@ silopt_register_sources( ArraySemantic.cpp BasicCalleeAnalysis.cpp CallerAnalysis.cpp - CFG.cpp ClassHierarchyAnalysis.cpp ClosureScope.cpp ColdBlockInfo.cpp diff --git a/lib/SILOptimizer/Analysis/CallerAnalysis.cpp b/lib/SILOptimizer/Analysis/CallerAnalysis.cpp index c2894f10725..f27316bd95e 100644 --- a/lib/SILOptimizer/Analysis/CallerAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/CallerAnalysis.cpp @@ -14,7 +14,8 @@ #include "swift/SILOptimizer/Analysis/CallerAnalysis.h" #include "swift/SIL/InstructionUtils.h" #include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SIL/SILVisitor.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/YAMLTraits.h" diff --git a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp index 8924baa8f90..0b6316d9b80 100644 --- a/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/EscapeAnalysis.cpp @@ -12,13 +12,13 @@ #define DEBUG_TYPE "sil-escape" #include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" -#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" +#include "swift/SIL/DebugUtils.h" +#include "swift/SIL/SILArgument.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" +#include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" #include "swift/SILOptimizer/PassManager/PassManager.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SIL/SILArgument.h" -#include "swift/SIL/DebugUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/GraphWriter.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp index 914650a6bda..1ffe2bb525b 100644 --- a/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp +++ b/lib/SILOptimizer/Analysis/SimplifyInstruction.cpp @@ -25,7 +25,7 @@ #include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" using namespace swift; using namespace swift::PatternMatch; diff --git a/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp b/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp index 9758746fb8a..203e7cca659 100644 --- a/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp +++ b/lib/SILOptimizer/Analysis/TypeExpansionAnalysis.cpp @@ -14,7 +14,7 @@ #include "swift/SILOptimizer/Analysis/TypeExpansionAnalysis.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Analysis/ValueTracking.cpp b/lib/SILOptimizer/Analysis/ValueTracking.cpp index 58d0e3aac98..43a067b3224 100644 --- a/lib/SILOptimizer/Analysis/ValueTracking.cpp +++ b/lib/SILOptimizer/Analysis/ValueTracking.cpp @@ -12,13 +12,13 @@ #define DEBUG_TYPE "sil-value-tracking" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" +#include "swift/SIL/InstructionUtils.h" +#include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILValue.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SIL/PatternMatch.h" +#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/Debug.h" using namespace swift; using namespace swift::PatternMatch; diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp index 0d93ef676ec..6a10833dc58 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialSpecializer.cpp @@ -22,7 +22,7 @@ #include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/Existential.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp index 85006473260..37f1fbaf2c6 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.cpp @@ -23,10 +23,9 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/TypeSubstCloner.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" #include "swift/SILOptimizer/Utils/Existential.h" #include "swift/SILOptimizer/Utils/Generics.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.h b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.h index 424595c8d4e..79ad59ec7eb 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.h +++ b/lib/SILOptimizer/FunctionSignatureTransforms/ExistentialTransform.h @@ -20,7 +20,7 @@ #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/Utils/Existential.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/ADT/SmallBitVector.h" diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp index b683e260647..106503643ae 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.cpp @@ -34,7 +34,6 @@ #include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILCloner.h" #include "swift/SIL/SILFunction.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SIL/SILValue.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/CallerAnalysis.h" @@ -42,8 +41,9 @@ #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILInliner.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.h b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.h index 84c1f62847a..764510db9bd 100644 --- a/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.h +++ b/lib/SILOptimizer/FunctionSignatureTransforms/FunctionSignatureOpts.h @@ -26,7 +26,7 @@ #include "swift/SILOptimizer/Analysis/CallerAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/PassManager.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/ADT/DenseMap.h" diff --git a/lib/SILOptimizer/IPO/CapturePropagation.cpp b/lib/SILOptimizer/IPO/CapturePropagation.cpp index 43aec92f08d..614f8781b8b 100644 --- a/lib/SILOptimizer/IPO/CapturePropagation.cpp +++ b/lib/SILOptimizer/IPO/CapturePropagation.cpp @@ -14,7 +14,6 @@ #include "swift/AST/GenericEnvironment.h" #include "swift/Demangling/Demangle.h" #include "swift/SIL/SILCloner.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/TypeSubstCloner.h" #include "swift/SILOptimizer/Analysis/ColdBlockInfo.h" @@ -22,7 +21,8 @@ #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/Generics.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp index 38184d982ae..335961d249e 100644 --- a/lib/SILOptimizer/IPO/ClosureSpecializer.cpp +++ b/lib/SILOptimizer/IPO/ClosureSpecializer.cpp @@ -63,18 +63,19 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/Analysis/BasicCalleeAnalysis.h" -#include "swift/SILOptimizer/Analysis/CFG.h" #include "swift/SILOptimizer/Analysis/FunctionOrder.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILInliner.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "swift/SILOptimizer/Utils/StackNesting.h" -#include "llvm/ADT/SmallString.h" +#include "swift/SILOptimizer/Utils/ValueLifetime.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp index a533cc5f764..48bba4ae285 100644 --- a/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp +++ b/lib/SILOptimizer/IPO/DeadFunctionElimination.cpp @@ -12,13 +12,13 @@ #define DEBUG_TYPE "sil-dead-function-elimination" #include "swift/AST/ProtocolConformance.h" -#include "swift/SILOptimizer/PassManager/Passes.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/IPO/GlobalOpt.cpp b/lib/SILOptimizer/IPO/GlobalOpt.cpp index f2e18428c6b..0fcd0d7f390 100644 --- a/lib/SILOptimizer/IPO/GlobalOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalOpt.cpp @@ -17,14 +17,16 @@ #include "swift/Demangling/ManglingMacros.h" #include "swift/SIL/CFG.h" #include "swift/SIL/DebugUtils.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" +#include "swift/SIL/SILCloner.h" #include "swift/SIL/SILGlobalVariable.h" #include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/Analysis/ColdBlockInfo.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp index 86500322f54..b0b6dc0ecd1 100644 --- a/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp +++ b/lib/SILOptimizer/IPO/GlobalPropertyOpt.cpp @@ -11,20 +11,20 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "globalpropertyopt" -#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" -#include "swift/SIL/SILArgument.h" #include "swift/SIL/SILModule.h" -#include "swift/SIL/SILBuilder.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Support/Debug.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp index ed90ade92b1..6fc43adc5fe 100644 --- a/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp +++ b/lib/SILOptimizer/IPO/LetPropertiesOpts.cpp @@ -26,7 +26,8 @@ #include "swift/SIL/SILLinkage.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/MapVector.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/IPO/UsePrespecialized.cpp b/lib/SILOptimizer/IPO/UsePrespecialized.cpp index 42f39f5c203..2b1e8f58aa4 100644 --- a/lib/SILOptimizer/IPO/UsePrespecialized.cpp +++ b/lib/SILOptimizer/IPO/UsePrespecialized.cpp @@ -11,16 +11,16 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "use-prespecialized" +#include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILFunction.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/SpecializationMangler.h" -#include "swift/SIL/SILBuilder.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/SILFunction.h" -#include "swift/SIL/SILModule.h" -#include "llvm/Support/Debug.h" #include "swift/SILOptimizer/Utils/Generics.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SpecializationMangler.h" +#include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp index c9c07299331..3af89ed40f5 100644 --- a/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp +++ b/lib/SILOptimizer/LoopTransforms/ArrayBoundsCheckOpts.cpp @@ -12,8 +12,15 @@ #define DEBUG_TYPE "sil-abcopts" -#include "swift/Basic/STLExtras.h" #include "swift/AST/Builtins.h" +#include "swift/Basic/STLExtras.h" +#include "swift/SIL/Dominance.h" +#include "swift/SIL/InstructionUtils.h" +#include "swift/SIL/PatternMatch.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILFunction.h" +#include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" @@ -24,16 +31,9 @@ #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" -#include "swift/SIL/Dominance.h" -#include "swift/SIL/PatternMatch.h" -#include "swift/SIL/SILArgument.h" -#include "swift/SIL/SILBuilder.h" -#include "swift/SIL/SILFunction.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/InstructionUtils.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/PointerIntPair.h" diff --git a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp index 4afd42b8640..b7838207e27 100644 --- a/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp +++ b/lib/SILOptimizer/LoopTransforms/COWArrayOpt.cpp @@ -11,26 +11,26 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "cowarray-opts" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SIL/CFG.h" +#include "swift/SIL/DebugUtils.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/Projection.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILCloner.h" #include "swift/SIL/SILInstruction.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Analysis/ArraySemantic.h" -#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" +#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" +#include "swift/SILOptimizer/Analysis/ArraySemantic.h" #include "swift/SILOptimizer/Analysis/ColdBlockInfo.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/LoopAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringExtras.h" diff --git a/lib/SILOptimizer/LoopTransforms/LICM.cpp b/lib/SILOptimizer/LoopTransforms/LICM.cpp index a3921290eec..10e4d6b7012 100644 --- a/lib/SILOptimizer/LoopTransforms/LICM.cpp +++ b/lib/SILOptimizer/LoopTransforms/LICM.cpp @@ -27,8 +27,8 @@ #include "swift/SILOptimizer/Analysis/SideEffectAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/DepthFirstIterator.h" diff --git a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp index 52c622c4821..abc97756f24 100644 --- a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp +++ b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp @@ -13,17 +13,18 @@ #define DEBUG_TYPE "sil-looprotate" #include "swift/SIL/Dominance.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/LoopAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/LoopUtils.h" -#include "swift/SIL/SILArgument.h" -#include "swift/SIL/SILBuilder.h" -#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/Support/Debug.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/Mandatory/AddressLowering.cpp b/lib/SILOptimizer/Mandatory/AddressLowering.cpp index 864f1464ab0..061bdab9cb2 100644 --- a/lib/SILOptimizer/Mandatory/AddressLowering.cpp +++ b/lib/SILOptimizer/Mandatory/AddressLowering.cpp @@ -96,7 +96,7 @@ #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SetVector.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp index 2a54afb4835..d0c9c67e5c4 100644 --- a/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp +++ b/lib/SILOptimizer/Mandatory/ClosureLifetimeFixup.cpp @@ -19,8 +19,8 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "swift/SILOptimizer/Utils/StackNesting.h" diff --git a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp index dbab75c357f..531d68083f6 100644 --- a/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp +++ b/lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp @@ -22,8 +22,8 @@ #include "swift/SIL/SILBuilder.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp index d7af3f17fc2..3a60405702a 100644 --- a/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp +++ b/lib/SILOptimizer/Mandatory/DiagnoseUnreachable.cpp @@ -22,8 +22,8 @@ #include "swift/SIL/SILUndef.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp index 811b212bdd6..6da647c6944 100644 --- a/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp +++ b/lib/SILOptimizer/Mandatory/IRGenPrepare.cpp @@ -27,7 +27,7 @@ #include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/Strings.h" using namespace swift; diff --git a/lib/SILOptimizer/Mandatory/MandatoryCombine.cpp b/lib/SILOptimizer/Mandatory/MandatoryCombine.cpp index ea6126fa0f1..3e0d256aaeb 100644 --- a/lib/SILOptimizer/Mandatory/MandatoryCombine.cpp +++ b/lib/SILOptimizer/Mandatory/MandatoryCombine.cpp @@ -31,7 +31,7 @@ #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp index 76341b3f622..6504b6f338f 100644 --- a/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp +++ b/lib/SILOptimizer/Mandatory/MandatoryInlining.cpp @@ -20,9 +20,9 @@ #include "swift/SIL/OwnershipUtils.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/Devirtualize.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILInliner.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/StackNesting.h" diff --git a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp index 09551d05779..e0e9026a256 100644 --- a/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp +++ b/lib/SILOptimizer/Mandatory/OSLogOptimization.cpp @@ -87,7 +87,7 @@ #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/ConstExpr.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILInliner.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/MapVector.h" diff --git a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp index df5a0c71421..2e814332b30 100644 --- a/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp +++ b/lib/SILOptimizer/Mandatory/PredictableMemOpt.cpp @@ -19,7 +19,7 @@ #include "swift/SIL/SILBuilder.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp index 5b51c722ec2..eb4c12f4d99 100644 --- a/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp +++ b/lib/SILOptimizer/Mandatory/SILGenCleanup.cpp @@ -19,7 +19,7 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" using namespace swift; diff --git a/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp b/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp index 3894db77610..72fa8368a7f 100644 --- a/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp +++ b/lib/SILOptimizer/Mandatory/SemanticARCOpts.cpp @@ -24,7 +24,7 @@ #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/PassManager/PassPipeline.cpp b/lib/SILOptimizer/PassManager/PassPipeline.cpp index 997efa8264c..79974aaa9db 100644 --- a/lib/SILOptimizer/PassManager/PassPipeline.cpp +++ b/lib/SILOptimizer/PassManager/PassPipeline.cpp @@ -27,7 +27,7 @@ #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/PassManager/Passes.cpp b/lib/SILOptimizer/PassManager/Passes.cpp index 4317e83ffad..ce715dbd658 100644 --- a/lib/SILOptimizer/PassManager/Passes.cpp +++ b/lib/SILOptimizer/PassManager/Passes.cpp @@ -21,14 +21,14 @@ #define DEBUG_TYPE "sil-optimizer" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/AST/ASTContext.h" #include "swift/AST/Module.h" #include "swift/SIL/SILModule.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/PassManager/PassManager.h" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/SILCombiner/SILCombine.cpp b/lib/SILOptimizer/SILCombiner/SILCombine.cpp index 7f0893d0b8f..e0b9dae9019 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombine.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombine.cpp @@ -28,7 +28,7 @@ #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Utils/CanonicalizeInstruction.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/SILCombiner/SILCombiner.h b/lib/SILOptimizer/SILCombiner/SILCombiner.h index 1a76e0d8425..609bfe79df3 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombiner.h +++ b/lib/SILOptimizer/SILCombiner/SILCombiner.h @@ -30,7 +30,7 @@ #include "swift/SILOptimizer/Analysis/ProtocolConformanceAnalysis.h" #include "swift/SILOptimizer/Utils/CastOptimizer.h" #include "swift/SILOptimizer/Utils/Existential.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp index aefddbd51de..6f9af158319 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerApplyVisitors.cpp @@ -24,9 +24,10 @@ #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" -#include "swift/SILOptimizer/Analysis/CFG.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/Existential.h" +#include "swift/SILOptimizer/Utils/ValueLifetime.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp index 9227db10cf1..7c37686e464 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerBuiltinVisitors.cpp @@ -12,19 +12,19 @@ #define DEBUG_TYPE "sil-combine" #include "SILCombiner.h" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/DynamicCasts.h" #include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/CFG.h" +#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseMap.h" using namespace swift; using namespace swift::PatternMatch; diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp index 9d020bbb4ff..eee7bf3a22f 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerCastVisitors.cpp @@ -12,19 +12,19 @@ #define DEBUG_TYPE "sil-combine" #include "SILCombiner.h" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/DynamicCasts.h" #include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/CFG.h" +#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/DenseMap.h" using namespace swift; using namespace swift::PatternMatch; diff --git a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp index 0cf87916044..aa41f2c8d55 100644 --- a/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp +++ b/lib/SILOptimizer/SILCombiner/SILCombinerMiscVisitors.cpp @@ -22,10 +22,10 @@ #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" -#include "swift/SILOptimizer/Analysis/CFG.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/Devirtualize.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp b/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp index 8815b5be162..22af78be9fc 100644 --- a/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp +++ b/lib/SILOptimizer/Transforms/ARCCodeMotion.cpp @@ -80,8 +80,8 @@ #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/Strings.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallPtrSet.h" diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementDom.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementDom.cpp index a9a6a88512b..d454493053f 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementDom.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementDom.cpp @@ -56,7 +56,7 @@ #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/LoopAnalysis.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DepthFirstIterator.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp index 9ea227ae398..8aadfb4ce1f 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementOpts.cpp @@ -84,7 +84,7 @@ #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SCCIterator.h" diff --git a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp index 3dd7fd1bfc2..65df81551ad 100644 --- a/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp +++ b/lib/SILOptimizer/Transforms/AccessEnforcementWMO.cpp @@ -59,7 +59,7 @@ #include "swift/SIL/MemAccessUtils.h" #include "swift/SIL/SILFunction.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp index 5168f730e1b..3f52bb1c059 100644 --- a/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp +++ b/lib/SILOptimizer/Transforms/AllocBoxToStack.cpp @@ -11,16 +11,17 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "allocbox-to-stack" +#include "swift/SIL/ApplySite.h" #include "swift/SIL/Dominance.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILCloner.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SpecializationMangler.h" #include "swift/SILOptimizer/Utils/StackNesting.h" +#include "swift/SILOptimizer/Utils/ValueLifetime.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" diff --git a/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp b/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp index 558752006ea..8668a6971fc 100644 --- a/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp +++ b/lib/SILOptimizer/Transforms/AssumeSingleThreaded.cpp @@ -25,12 +25,12 @@ // //===----------------------------------------------------------------------===// -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/CommandLine.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/CSE.cpp b/lib/SILOptimizer/Transforms/CSE.cpp index 79d57506eba..8021602717f 100644 --- a/lib/SILOptimizer/Transforms/CSE.cpp +++ b/lib/SILOptimizer/Transforms/CSE.cpp @@ -16,24 +16,25 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-cse" -#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/Dominance.h" +#include "swift/SIL/SILCloner.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILOpenedArchetypesTracker.h" #include "swift/SIL/SILType.h" #include "swift/SIL/SILValue.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" #include "swift/SILOptimizer/Analysis/SideEffectAnalysis.h" +#include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Hashing.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopedHashTable.h" #include "llvm/ADT/Statistic.h" -#include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" #include "llvm/Support/RecyclingAllocator.h" diff --git a/lib/SILOptimizer/Transforms/CopyForwarding.cpp b/lib/SILOptimizer/Transforms/CopyForwarding.cpp index ae4d669aa85..c33bf4bddbf 100644 --- a/lib/SILOptimizer/Transforms/CopyForwarding.cpp +++ b/lib/SILOptimizer/Transforms/CopyForwarding.cpp @@ -68,7 +68,7 @@ #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/Transforms/CopyPropagation.cpp b/lib/SILOptimizer/Transforms/CopyPropagation.cpp index 72fd3d8c259..185e900052f 100644 --- a/lib/SILOptimizer/Transforms/CopyPropagation.cpp +++ b/lib/SILOptimizer/Transforms/CopyPropagation.cpp @@ -127,9 +127,9 @@ #include "swift/SIL/Projection.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/IndexTrie.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp index c8e2bee00b9..bc9dc78059b 100644 --- a/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadCodeElimination.cpp @@ -11,19 +11,19 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-dce" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILUndef.h" -#include "swift/SIL/DebugUtils.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp index 442978d1383..6056b412224 100644 --- a/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadObjectElimination.cpp @@ -24,8 +24,10 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "dead-object-elim" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/AST/ResilienceExpansion.h" +#include "swift/SIL/BasicBlockUtils.h" +#include "swift/SIL/DebugUtils.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/Projection.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILDeclRef.h" @@ -33,14 +35,13 @@ #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SIL/BasicBlockUtils.h" #include "swift/SILOptimizer/Analysis/ArraySemantic.h" -#include "swift/SILOptimizer/Utils/IndexTrie.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/IndexTrie.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" +#include "swift/SILOptimizer/Utils/ValueLifetime.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp index 057d122b01b..9dc817b7337 100644 --- a/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp +++ b/lib/SILOptimizer/Transforms/DeadStoreElimination.cpp @@ -64,12 +64,12 @@ #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/LoadStoreOptUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/DestroyHoisting.cpp b/lib/SILOptimizer/Transforms/DestroyHoisting.cpp index e23458a2cf1..d3ab5ab15fd 100644 --- a/lib/SILOptimizer/Transforms/DestroyHoisting.cpp +++ b/lib/SILOptimizer/Transforms/DestroyHoisting.cpp @@ -13,9 +13,9 @@ #define DEBUG_TYPE "sil-destroy-hoisting" #include "swift/SIL/MemoryLifetime.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp index 14965b38849..82dd9d4d33c 100644 --- a/lib/SILOptimizer/Transforms/GenericSpecializer.cpp +++ b/lib/SILOptimizer/Transforms/GenericSpecializer.cpp @@ -20,9 +20,9 @@ #include "swift/SIL/OptimizationRemark.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" -#include "swift/SILOptimizer/Utils/Generics.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/Generics.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/SmallVector.h" diff --git a/lib/SILOptimizer/Transforms/MergeCondFail.cpp b/lib/SILOptimizer/Transforms/MergeCondFail.cpp index e8ad4f8fc5c..0b293850eb7 100644 --- a/lib/SILOptimizer/Transforms/MergeCondFail.cpp +++ b/lib/SILOptimizer/Transforms/MergeCondFail.cpp @@ -12,12 +12,12 @@ #define DEBUG_TYPE "merge-cond_fail" +#include "swift/SIL/SILBuilder.h" +#include "swift/SIL/SILInstruction.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SIL/SILBuilder.h" -#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp index 71c67baedc9..688ca6c30db 100644 --- a/lib/SILOptimizer/Transforms/ObjectOutliner.cpp +++ b/lib/SILOptimizer/Transforms/ObjectOutliner.cpp @@ -14,9 +14,9 @@ #include "swift/AST/ASTMangler.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILBuilder.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp index 4dfdf1f3a04..dce868a8902 100644 --- a/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp +++ b/lib/SILOptimizer/Transforms/OwnershipModelEliminator.cpp @@ -29,7 +29,7 @@ #include "swift/SIL/SILVisitor.h" #include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/CommandLine.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp index a8f04bb04c9..961c6b57419 100644 --- a/lib/SILOptimizer/Transforms/PerformanceInliner.cpp +++ b/lib/SILOptimizer/Transforms/PerformanceInliner.cpp @@ -17,7 +17,7 @@ #include "swift/SILOptimizer/Analysis/SideEffectAnalysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/Devirtualize.h" #include "swift/SILOptimizer/Utils/Generics.h" #include "swift/SILOptimizer/Utils/PerformanceInlinerUtils.h" diff --git a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp index 6bfe200e5c5..51af6042e5a 100644 --- a/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp +++ b/lib/SILOptimizer/Transforms/RedundantLoadElimination.cpp @@ -76,15 +76,15 @@ #include "swift/SIL/Projection.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" -#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" +#include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/Analysis/ValueTracking.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/LoadStoreOptUtils.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/BitVector.h" diff --git a/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp b/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp index 483ec3eab3d..63615c2c5cc 100644 --- a/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp +++ b/lib/SILOptimizer/Transforms/RedundantOverflowCheckRemoval.cpp @@ -16,13 +16,13 @@ #define DEBUG_TYPE "remove-redundant-overflow-checks" #include "swift/SIL/Dominance.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" -#include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp index cbb85bf7e16..a732dc12d8b 100644 --- a/lib/SILOptimizer/Transforms/SILCodeMotion.cpp +++ b/lib/SILOptimizer/Transforms/SILCodeMotion.cpp @@ -11,21 +11,21 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-codemotion" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/AST/Module.h" #include "swift/Basic/BlotMapVector.h" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILType.h" #include "swift/SIL/SILValue.h" #include "swift/SIL/SILVisitor.h" -#include "swift/SIL/DebugUtils.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/AliasAnalysis.h" #include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp b/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp index ad6f1f757d0..bb03fe51795 100644 --- a/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp +++ b/lib/SILOptimizer/Transforms/SILLowerAggregateInstrs.cpp @@ -23,7 +23,7 @@ #include "swift/SIL/TypeLowering.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp index 7386f16c3b9..51a4493a7da 100644 --- a/lib/SILOptimizer/Transforms/SILMem2Reg.cpp +++ b/lib/SILOptimizer/Transforms/SILMem2Reg.cpp @@ -20,23 +20,23 @@ #define DEBUG_TYPE "sil-mem2reg" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/AST/DiagnosticsSIL.h" #include "swift/SIL/Dominance.h" +#include "swift/SIL/Projection.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" -#include "swift/SIL/Projection.h" #include "swift/SIL/TypeLowering.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "llvm/ADT/DenseSet.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/DenseSet.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" #include #include diff --git a/lib/SILOptimizer/Transforms/SILSROA.cpp b/lib/SILOptimizer/Transforms/SILSROA.cpp index 50fa0d4f5a7..a15fe415ebf 100644 --- a/lib/SILOptimizer/Transforms/SILSROA.cpp +++ b/lib/SILOptimizer/Transforms/SILSROA.cpp @@ -26,7 +26,7 @@ #include "swift/SIL/SILUndef.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp index 95c3663dda1..bb4c3fb97d8 100644 --- a/lib/SILOptimizer/Transforms/SimplifyCFG.cpp +++ b/lib/SILOptimizer/Transforms/SimplifyCFG.cpp @@ -24,12 +24,13 @@ #include "swift/SILOptimizer/Analysis/SimplifyInstruction.h" #include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/CastOptimizer.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" -#include "swift/SILOptimizer/Utils/Local.h" #include "swift/SILOptimizer/Utils/ConstantFolding.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/SILOptimizer/Utils/SILInliner.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -201,125 +202,6 @@ namespace { } // end anonymous namespace -/// Return true if there are any users of V outside the specified block. -static bool isUsedOutsideOfBlock(SILValue V, SILBasicBlock *BB) { - for (auto UI : V->getUses()) - if (UI->getUser()->getParent() != BB) - return true; - return false; -} - -// Populate 'projections' with the chain of address projections leading -// to and including 'inst'. -// -// Populate 'inBlockDefs' with all the non-address value definitions in -// the block that will be used outside this block after projection sinking. -// -// Return true on success, even if projections is empty. -bool SinkAddressProjections::analyzeAddressProjections(SILInstruction *inst) { - projections.clear(); - inBlockDefs.clear(); - - SILBasicBlock *bb = inst->getParent(); - auto pushOperandVal = [&](SILValue def) { - if (def->getParentBlock() != bb) - return true; - - if (!def->getType().isAddress()) { - inBlockDefs.insert(def); - return true; - } - if (auto *addressProj = dyn_cast(def)) { - if (addressProj->isTriviallyDuplicatable()) { - projections.push_back(addressProj); - return true; - } - } - // Can't handle a multi-value or unclonable address producer. - return false; - }; - // Check the given instruction for any address-type results. - for (auto result : inst->getResults()) { - if (!isUsedOutsideOfBlock(result, bb)) - continue; - if (!pushOperandVal(result)) - return false; - } - // Recurse upward through address projections. - for (unsigned idx = 0; idx < projections.size(); ++idx) { - // Only one address result/operand can be handled per instruction. - if (projections.size() != idx + 1) - return false; - - for (SILValue operandVal : projections[idx]->getOperandValues()) - pushOperandVal(operandVal); - } - return true; -} - -// Clone the projections gathered by 'analyzeAddressProjections' at -// their use site outside this block. -bool SinkAddressProjections::cloneProjections() { - if (projections.empty()) - return false; - - SILBasicBlock *bb = projections.front()->getParent(); - SmallVector usesToReplace; - // Clone projections in last-to-first order. - for (unsigned idx = 0; idx < projections.size(); ++idx) { - auto *oldProj = projections[idx]; - assert(oldProj->getParent() == bb); - usesToReplace.clear(); - for (Operand *use : oldProj->getUses()) { - if (use->getUser()->getParent() != bb) - usesToReplace.push_back(use); - } - for (Operand *use : usesToReplace) { - auto *newProj = oldProj->clone(use->getUser()); - use->set(cast(newProj)); - } - } - return true; -} - -/// Helper function to perform SSA updates in case of jump threading. -void swift::updateSSAAfterCloning(BasicBlockCloner &Cloner, - SILBasicBlock *SrcBB, SILBasicBlock *DestBB) { - SILSSAUpdater SSAUp; - for (auto AvailValPair : Cloner.AvailVals) { - ValueBase *Inst = AvailValPair.first; - if (Inst->use_empty()) - continue; - - SILValue NewRes(AvailValPair.second); - - SmallVector UseList; - // Collect the uses of the value. - for (auto Use : Inst->getUses()) - UseList.push_back(UseWrapper(Use)); - - SSAUp.Initialize(Inst->getType()); - SSAUp.AddAvailableValue(DestBB, Inst); - SSAUp.AddAvailableValue(SrcBB, NewRes); - - if (UseList.empty()) - continue; - - // Update all the uses. - for (auto U : UseList) { - Operand *Use = U; - SILInstruction *User = Use->getUser(); - assert(User && "Missing user"); - - // Ignore uses in the same basic block. - if (User->getParent() == DestBB) - continue; - - SSAUp.RewriteUse(*Use); - } - } -} - static SILValue getTerminatorCondition(TermInst *Term) { if (auto *CondBr = dyn_cast(Term)) return stripExpectIntrinsic(CondBr->getCondition()); @@ -1044,7 +926,7 @@ bool SimplifyCFG::tryJumpThreading(BranchInst *BI) { // Are the arguments to this block used outside of the block. for (auto Arg : DestBB->getArguments()) - if ((NeedToUpdateSSA |= isUsedOutsideOfBlock(Arg, DestBB))) { + if ((NeedToUpdateSSA |= isUsedOutsideOfBlock(Arg))) { break; } diff --git a/lib/SILOptimizer/Transforms/Sink.cpp b/lib/SILOptimizer/Transforms/Sink.cpp index a1077f0cf0c..b9b7342c9f7 100644 --- a/lib/SILOptimizer/Transforms/Sink.cpp +++ b/lib/SILOptimizer/Transforms/Sink.cpp @@ -19,18 +19,18 @@ #define DEBUG_TYPE "sink-instructions" -#include "swift/SIL/Dominance.h" -#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" -#include "swift/SILOptimizer/Analysis/LoopAnalysis.h" -#include "swift/SILOptimizer/PassManager/Passes.h" -#include "swift/SIL/SILArgument.h" -#include "swift/SIL/SILValue.h" -#include "swift/SIL/SILDebugScope.h" #include "swift/SIL/DebugUtils.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SIL/Dominance.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILDebugScope.h" #include "swift/SIL/SILInstruction.h" +#include "swift/SIL/SILValue.h" +#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/Analysis/LoopAnalysis.h" +#include "swift/SILOptimizer/Analysis/PostOrderAnalysis.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/Statistic.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp b/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp index 25d43696336..b8968e0414e 100644 --- a/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp +++ b/lib/SILOptimizer/Transforms/SpecializeOpaqueArchetypes.cpp @@ -18,10 +18,10 @@ #include "swift/AST/Types.h" #include "swift/SIL/SILFunction.h" -#include "swift/SIL/TypeSubstCloner.h" #include "swift/SIL/SILInstruction.h" +#include "swift/SIL/TypeSubstCloner.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" #include "llvm/Support/CommandLine.h" diff --git a/lib/SILOptimizer/Transforms/StackPromotion.cpp b/lib/SILOptimizer/Transforms/StackPromotion.cpp index 1d3775668a4..b0243dc3198 100644 --- a/lib/SILOptimizer/Transforms/StackPromotion.cpp +++ b/lib/SILOptimizer/Transforms/StackPromotion.cpp @@ -10,15 +10,16 @@ // //===----------------------------------------------------------------------===// -#include "swift/SILOptimizer/PassManager/Passes.h" -#include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/StackNesting.h" -#include "swift/SIL/SILArgument.h" -#include "swift/SIL/SILBuilder.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/CFG.h" +#include "swift/SIL/SILArgument.h" +#include "swift/SIL/SILBuilder.h" +#include "swift/SILOptimizer/Analysis/EscapeAnalysis.h" +#include "swift/SILOptimizer/PassManager/Passes.h" +#include "swift/SILOptimizer/PassManager/Transforms.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/StackNesting.h" +#include "swift/SILOptimizer/Utils/ValueLifetime.h" #include "llvm/ADT/Statistic.h" #define DEBUG_TYPE "stack-promotion" diff --git a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp b/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp index 9aa693dc8f6..aa2de64bc4c 100644 --- a/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp +++ b/lib/SILOptimizer/Transforms/UnsafeGuaranteedPeephole.cpp @@ -31,7 +31,6 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "unsafe-guaranteed-peephole" -#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SIL/DebugUtils.h" #include "swift/SIL/SILFunction.h" #include "swift/SIL/SILInstruction.h" @@ -39,8 +38,9 @@ #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" #include "swift/SILOptimizer/Analysis/RCIdentityAnalysis.h" +#include "swift/SILOptimizer/PassManager/Passes.h" #include "swift/SILOptimizer/PassManager/Transforms.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp new file mode 100644 index 00000000000..0c1caf165e5 --- /dev/null +++ b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp @@ -0,0 +1,243 @@ +//===--- BasicBlockOptUtils.cpp - SILOptimizer basic block utilities ------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// + +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" + +using namespace swift; + +/// Remove all instructions in the body of \p BB in safe manner by using +/// undef. +void swift::clearBlockBody(SILBasicBlock *BB) { + // Instructions in the dead block may be used by other dead blocks. Replace + // any uses of them with undef values. + while (!BB->empty()) { + // Grab the last instruction in the BB. + auto *Inst = &BB->back(); + + // Replace any still-remaining uses with undef values and erase. + Inst->replaceAllUsesOfAllResultsWithUndef(); + Inst->eraseFromParent(); + } +} + +// Handle the mechanical aspects of removing an unreachable block. +void swift::removeDeadBlock(SILBasicBlock *BB) { + // Clear the body of BB. + clearBlockBody(BB); + + // Now that the BB is empty, eliminate it. + BB->eraseFromParent(); +} + + +bool swift::removeUnreachableBlocks(SILFunction &Fn) { + // All reachable blocks, but does not include the entry block. + llvm::SmallPtrSet Visited; + + // Walk over the CFG, starting at the entry block, until all reachable blocks are visited. + llvm::SmallVector Worklist(1, Fn.getEntryBlock()); + while (!Worklist.empty()) { + SILBasicBlock *BB = Worklist.pop_back_val(); + for (auto &Succ : BB->getSuccessors()) { + if (Visited.insert(Succ).second) + Worklist.push_back(Succ); + } + } + + // Remove the blocks we never reached. Exclude the entry block from the iteration because it's + // not included in the Visited set. + bool Changed = false; + for (auto It = std::next(Fn.begin()), End = Fn.end(); It != End; ) { + auto *BB = &*It++; + if (!Visited.count(BB)) { + removeDeadBlock(BB); + Changed = true; + } + } + return Changed; +} + +/// Helper function to perform SSA updates in case of jump threading. +void swift::updateSSAAfterCloning(BasicBlockCloner &Cloner, + SILBasicBlock *SrcBB, SILBasicBlock *DestBB) { + SILSSAUpdater SSAUp; + for (auto AvailValPair : Cloner.AvailVals) { + ValueBase *Inst = AvailValPair.first; + if (Inst->use_empty()) + continue; + + SILValue NewRes(AvailValPair.second); + + SmallVector UseList; + // Collect the uses of the value. + for (auto Use : Inst->getUses()) + UseList.push_back(UseWrapper(Use)); + + SSAUp.Initialize(Inst->getType()); + SSAUp.AddAvailableValue(DestBB, Inst); + SSAUp.AddAvailableValue(SrcBB, NewRes); + + if (UseList.empty()) + continue; + + // Update all the uses. + for (auto U : UseList) { + Operand *Use = U; + SILInstruction *User = Use->getUser(); + assert(User && "Missing user"); + + // Ignore uses in the same basic block. + if (User->getParent() == DestBB) + continue; + + SSAUp.RewriteUse(*Use); + } + } +} + +// FIXME: Remove this. SILCloner should not create critical edges. +bool BasicBlockCloner::splitCriticalEdges(DominanceInfo *DT, SILLoopInfo *LI) { + bool changed = false; + // Remove any critical edges that the EdgeThreadingCloner may have + // accidentally created. + for (unsigned succIdx = 0, succEnd = origBB->getSuccessors().size(); + succIdx != succEnd; ++succIdx) { + if (nullptr != splitCriticalEdge(origBB->getTerminator(), succIdx, DT, LI)) + changed |= true; + } + for (unsigned succIdx = 0, succEnd = getNewBB()->getSuccessors().size(); + succIdx != succEnd; ++succIdx) { + auto *newBB = + splitCriticalEdge(getNewBB()->getTerminator(), succIdx, DT, LI); + changed |= (newBB != nullptr); + } + return changed; +} + +// Populate 'projections' with the chain of address projections leading +// to and including 'inst'. +// +// Populate 'inBlockDefs' with all the non-address value definitions in +// the block that will be used outside this block after projection sinking. +// +// Return true on success, even if projections is empty. +bool SinkAddressProjections::analyzeAddressProjections(SILInstruction *inst) { + projections.clear(); + inBlockDefs.clear(); + + SILBasicBlock *bb = inst->getParent(); + auto pushOperandVal = [&](SILValue def) { + if (def->getParentBlock() != bb) + return true; + + if (!def->getType().isAddress()) { + inBlockDefs.insert(def); + return true; + } + if (auto *addressProj = dyn_cast(def)) { + if (addressProj->isTriviallyDuplicatable()) { + projections.push_back(addressProj); + return true; + } + } + // Can't handle a multi-value or unclonable address producer. + return false; + }; + // Check the given instruction for any address-type results. + for (auto result : inst->getResults()) { + if (!isUsedOutsideOfBlock(result)) + continue; + if (!pushOperandVal(result)) + return false; + } + // Recurse upward through address projections. + for (unsigned idx = 0; idx < projections.size(); ++idx) { + // Only one address result/operand can be handled per instruction. + if (projections.size() != idx + 1) + return false; + + for (SILValue operandVal : projections[idx]->getOperandValues()) + pushOperandVal(operandVal); + } + return true; +} + +// Clone the projections gathered by 'analyzeAddressProjections' at +// their use site outside this block. +bool SinkAddressProjections::cloneProjections() { + if (projections.empty()) + return false; + + SILBasicBlock *bb = projections.front()->getParent(); + SmallVector usesToReplace; + // Clone projections in last-to-first order. + for (unsigned idx = 0; idx < projections.size(); ++idx) { + auto *oldProj = projections[idx]; + assert(oldProj->getParent() == bb); + usesToReplace.clear(); + for (Operand *use : oldProj->getUses()) { + if (use->getUser()->getParent() != bb) + usesToReplace.push_back(use); + } + for (Operand *use : usesToReplace) { + auto *newProj = oldProj->clone(use->getUser()); + use->set(cast(newProj)); + } + } + return true; +} + +void StaticInitCloner::add(SILInstruction *InitVal) { + // Don't schedule an instruction twice for cloning. + if (NumOpsToClone.count(InitVal) != 0) + return; + + ArrayRef Ops = InitVal->getAllOperands(); + NumOpsToClone[InitVal] = Ops.size(); + if (Ops.empty()) { + // It's an instruction without operands, e.g. a literal. It's ready to be + // cloned first. + ReadyToClone.push_back(InitVal); + } else { + // Recursively add all operands. + for (const Operand &Op : Ops) { + add(cast(Op.get())); + } + } +} + +SingleValueInstruction * +StaticInitCloner::clone(SingleValueInstruction *InitVal) { + assert(NumOpsToClone.count(InitVal) != 0 && "InitVal was not added"); + // Find the right order to clone: all operands of an instruction must be + // cloned before the instruction itself. + while (!ReadyToClone.empty()) { + SILInstruction *I = ReadyToClone.pop_back_val(); + + // Clone the instruction into the SILGlobalVariable + visit(I); + + // Check if users of I can now be cloned. + for (SILValue result : I->getResults()) { + for (Operand *Use : result->getUses()) { + SILInstruction *User = Use->getUser(); + if (NumOpsToClone.count(User) != 0 && --NumOpsToClone[User] == 0) + ReadyToClone.push_back(User); + } + } + } + return cast(getMappedValue(InitVal)); +} + diff --git a/lib/SILOptimizer/Utils/CFG.cpp b/lib/SILOptimizer/Utils/CFGOptUtils.cpp similarity index 78% rename from lib/SILOptimizer/Utils/CFG.cpp rename to lib/SILOptimizer/Utils/CFGOptUtils.cpp index e92b57bb9ed..8a10396254b 100644 --- a/lib/SILOptimizer/Utils/CFG.cpp +++ b/lib/SILOptimizer/Utils/CFGOptUtils.cpp @@ -1,8 +1,8 @@ -//===--- CFG.cpp - Utilities for SIL CFG transformations ------------------===// +//===--- CFGOptUtils.cpp - SIL CFG edge utilities -------------------------===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2019 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 @@ -10,14 +10,15 @@ // //===----------------------------------------------------------------------===// +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/Demangling/ManglingMacros.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/Dominance.h" #include "swift/SIL/LoopInfo.h" -#include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "llvm/ADT/TinyPtrVector.h" using namespace swift; @@ -100,20 +101,22 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, llvm::copy(cbi->getFalseArgs(), std::back_inserter(falseArgs)); if (destBlock == cbi->getTrueBB()) { - deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(), argIndex); + deleteTriviallyDeadOperandsOfDeadArgument(cbi->getTrueOperands(), + argIndex); trueArgs.erase(trueArgs.begin() + argIndex); } if (destBlock == cbi->getFalseBB()) { - deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(), argIndex); + deleteTriviallyDeadOperandsOfDeadArgument(cbi->getFalseOperands(), + argIndex); falseArgs.erase(falseArgs.begin() + argIndex); } SILBuilderWithScope builder(cbi); - auto *result = builder.createCondBranch(cbi->getLoc(), cbi->getCondition(), - cbi->getTrueBB(), trueArgs, cbi->getFalseBB(), - falseArgs, cbi->getTrueBBCount(), - cbi->getFalseBBCount()); + auto *result = builder.createCondBranch( + cbi->getLoc(), cbi->getCondition(), cbi->getTrueBB(), trueArgs, + cbi->getFalseBB(), falseArgs, cbi->getTrueBBCount(), + cbi->getFalseBBCount()); branch->eraseFromParent(); return result; } @@ -124,7 +127,8 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, deleteTriviallyDeadOperandsOfDeadArgument(bi->getAllOperands(), argIndex); args.erase(args.begin() + argIndex); - auto *result = SILBuilderWithScope(bi).createBranch(bi->getLoc(), bi->getDestBB(), args); + auto *result = SILBuilderWithScope(bi).createBranch(bi->getLoc(), + bi->getDestBB(), args); branch->eraseFromParent(); return result; } @@ -133,8 +137,8 @@ TermInst *swift::deleteEdgeValue(TermInst *branch, SILBasicBlock *destBlock, } void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex) { - assert(block->getArgument(argIndex)->isPhiArgument() && - "Only should be used on phi arguments"); + assert(block->getArgument(argIndex)->isPhiArgument() + && "Only should be used on phi arguments"); block->eraseArgument(argIndex); // Determine the set of predecessors in case any predecessor has @@ -182,8 +186,8 @@ TermInst *swift::changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, else TrueArgs.push_back(OldTrueArgs[i]); } - assert(TrueArgs.size() == CBI->getTrueBB()->getNumArguments() && - "Destination block's number of arguments must match"); + assert(TrueArgs.size() == CBI->getTrueBB()->getNumArguments() + && "Destination block's number of arguments must match"); OperandValueArrayRef OldFalseArgs = CBI->getFalseArgs(); bool BranchOnFalse = CBI->getFalseBB() == Dest; @@ -196,8 +200,8 @@ TermInst *swift::changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, else FalseArgs.push_back(OldFalseArgs[i]); } - assert(FalseArgs.size() == CBI->getFalseBB()->getNumArguments() && - "Destination block's number of arguments must match"); + assert(FalseArgs.size() == CBI->getFalseBB()->getNumArguments() + && "Destination block's number of arguments must match"); CBI = Builder.createCondBranch( CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, @@ -234,32 +238,32 @@ TermInst *swift::changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, template SILBasicBlock *replaceSwitchDest(SwitchEnumTy *S, - SmallVectorImpl &Cases, - unsigned EdgeIdx, SILBasicBlock *NewDest) { - auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; - for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) - if (EdgeIdx != i) - Cases.push_back(S->getCase(i)); - else - Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); - if (EdgeIdx == S->getNumCases()) - DefaultBB = NewDest; - return DefaultBB; + SmallVectorImpl &Cases, + unsigned EdgeIdx, SILBasicBlock *NewDest) { + auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; + for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) + if (EdgeIdx != i) + Cases.push_back(S->getCase(i)); + else + Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); + if (EdgeIdx == S->getNumCases()) + DefaultBB = NewDest; + return DefaultBB; } template -SILBasicBlock *replaceSwitchDest(SwitchEnumTy *S, - SmallVectorImpl &Cases, - SILBasicBlock *OldDest, SILBasicBlock *NewDest) { - auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; - for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) - if (S->getCase(i).second != OldDest) - Cases.push_back(S->getCase(i)); - else - Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); - if (OldDest == DefaultBB) - DefaultBB = NewDest; - return DefaultBB; +SILBasicBlock * +replaceSwitchDest(SwitchEnumTy *S, SmallVectorImpl &Cases, + SILBasicBlock *OldDest, SILBasicBlock *NewDest) { + auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; + for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) + if (S->getCase(i).second != OldDest) + Cases.push_back(S->getCase(i)); + else + Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); + if (OldDest == DefaultBB) + DefaultBB = NewDest; + return DefaultBB; } /// Replace a branch target. @@ -269,7 +273,7 @@ SILBasicBlock *replaceSwitchDest(SwitchEnumTy *S, /// \param NewDest The new target block. /// \param PreserveArgs If set, preserve arguments on the replaced edge. void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, - SILBasicBlock *NewDest, bool PreserveArgs) { + SILBasicBlock *NewDest, bool PreserveArgs) { SILBuilderWithScope B(T); switch (T->getTermKind()) { @@ -328,7 +332,7 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::SwitchEnumInst: { auto SEI = cast(T); - SmallVector, 8> Cases; + SmallVector, 8> Cases; auto *DefaultBB = replaceSwitchDest(SEI, Cases, OldDest, NewDest); B.createSwitchEnum(SEI->getLoc(), SEI->getOperand(), DefaultBB, Cases); SEI->eraseFromParent(); @@ -337,7 +341,7 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::SwitchEnumAddrInst: { auto SEI = cast(T); - SmallVector, 8> Cases; + SmallVector, 8> Cases; auto *DefaultBB = replaceSwitchDest(SEI, Cases, OldDest, NewDest); B.createSwitchEnumAddr(SEI->getLoc(), SEI->getOperand(), DefaultBB, Cases); SEI->eraseFromParent(); @@ -346,20 +350,26 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::DynamicMethodBranchInst: { auto DMBI = cast(T); - assert(OldDest == DMBI->getHasMethodBB() || OldDest == DMBI->getNoMethodBB() && "Invalid edge index"); - auto HasMethodBB = OldDest == DMBI->getHasMethodBB() ? NewDest : DMBI->getHasMethodBB(); - auto NoMethodBB = OldDest == DMBI->getNoMethodBB() ? NewDest : DMBI->getNoMethodBB(); + assert(OldDest == DMBI->getHasMethodBB() + || OldDest == DMBI->getNoMethodBB() && "Invalid edge index"); + auto HasMethodBB = + OldDest == DMBI->getHasMethodBB() ? NewDest : DMBI->getHasMethodBB(); + auto NoMethodBB = + OldDest == DMBI->getNoMethodBB() ? NewDest : DMBI->getNoMethodBB(); B.createDynamicMethodBranch(DMBI->getLoc(), DMBI->getOperand(), - DMBI->getMember(), HasMethodBB, NoMethodBB); + DMBI->getMember(), HasMethodBB, NoMethodBB); DMBI->eraseFromParent(); return; } case TermKind::CheckedCastBranchInst: { auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() || OldDest == CBI->getFailureBB() && "Invalid edge index"); - auto SuccessBB = OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); - auto FailureBB = OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); + assert(OldDest == CBI->getSuccessBB() + || OldDest == CBI->getFailureBB() && "Invalid edge index"); + auto SuccessBB = + OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); + auto FailureBB = + OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); B.createCheckedCastBranch(CBI->getLoc(), CBI->isExact(), CBI->getOperand(), CBI->getCastType(), SuccessBB, FailureBB, CBI->getTrueBBCount(), CBI->getFalseBBCount()); @@ -369,8 +379,8 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::CheckedCastValueBranchInst: { auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() || - OldDest == CBI->getFailureBB() && "Invalid edge index"); + assert(OldDest == CBI->getSuccessBB() + || OldDest == CBI->getFailureBB() && "Invalid edge index"); auto SuccessBB = OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); auto FailureBB = @@ -383,9 +393,12 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::CheckedCastAddrBranchInst: { auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() || OldDest == CBI->getFailureBB() && "Invalid edge index"); - auto SuccessBB = OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); - auto FailureBB = OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); + assert(OldDest == CBI->getSuccessBB() + || OldDest == CBI->getFailureBB() && "Invalid edge index"); + auto SuccessBB = + OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); + auto FailureBB = + OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); auto TrueCount = CBI->getTrueBBCount(); auto FalseCount = CBI->getFalseBBCount(); B.createCheckedCastAddrBranch(CBI->getLoc(), CBI->getConsumptionKind(), @@ -402,7 +415,8 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, case TermKind::UnreachableInst: case TermKind::UnwindInst: case TermKind::YieldInst: - llvm_unreachable("Branch target cannot be replaced for this terminator instruction!"); + llvm_unreachable( + "Branch target cannot be replaced for this terminator instruction!"); } llvm_unreachable("Not yet implemented!"); } @@ -412,7 +426,7 @@ bool swift::isCriticalEdge(TermInst *T, unsigned EdgeIdx) { assert(T->getSuccessors().size() > EdgeIdx && "Not enough successors"); auto SrcSuccs = T->getSuccessors(); - + if (SrcSuccs.size() <= 1 && // Also consider non-branch instructions with a single successor for // critical edges, for example: a switch_enum of a single-case enum. @@ -571,7 +585,8 @@ bool swift::mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT, bool swift::mergeBasicBlocks(SILFunction *F) { bool merged = false; for (auto BBIter = F->begin(); BBIter != F->end();) { - if (mergeBasicBlockWithSuccessor(&*BBIter, /*DT*/ nullptr, /*LI*/ nullptr)) { + if (mergeBasicBlockWithSuccessor(&*BBIter, /*DT*/ nullptr, + /*LI*/ nullptr)) { merged = true; // Continue to merge the current block without advancing. continue; @@ -584,8 +599,7 @@ bool swift::mergeBasicBlocks(SILFunction *F) { /// Splits the critical edges between from and to. This code assumes there is /// only one edge between the two basic blocks. SILBasicBlock *swift::splitIfCriticalEdge(SILBasicBlock *From, - SILBasicBlock *To, - DominanceInfo *DT, + SILBasicBlock *To, DominanceInfo *DT, SILLoopInfo *LI) { auto *T = From->getTerminator(); for (unsigned i = 0, e = T->getSuccessors().size(); i != e; ++i) { @@ -603,8 +617,8 @@ void swift::completeJointPostDominanceSet( // If we have only one def block and one user block and they are the same // block, then just return. - if (DefBlocks.size() == 1 && UserBlocks.size() == 1 && - UserBlocks[0] == DefBlocks[0]) { + if (DefBlocks.size() == 1 && UserBlocks.size() == 1 + && UserBlocks[0] == DefBlocks[0]) { return; } @@ -645,8 +659,9 @@ void swift::completeJointPostDominanceSet( while (!Worklist.empty()) { // Grab the next block from the worklist. auto *Block = Worklist.pop_back_val(); - assert(VisitedBlocks.count(Block) && "All blocks from worklist should be " - "in the visited blocks set."); + assert(VisitedBlocks.count(Block) + && "All blocks from worklist should be " + "in the visited blocks set."); // Since we are visiting this block now, we know that this block can not be // apart of a the post-dominance closure of our UseBlocks. @@ -715,29 +730,86 @@ bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn, return true; } -bool swift::removeUnreachableBlocks(SILFunction &Fn) { - // All reachable blocks, but does not include the entry block. - llvm::SmallPtrSet Visited; - - // Walk over the CFG, starting at the entry block, until all reachable blocks are visited. - llvm::SmallVector Worklist(1, Fn.getEntryBlock()); - while (!Worklist.empty()) { - SILBasicBlock *BB = Worklist.pop_back_val(); - for (auto &Succ : BB->getSuccessors()) { - if (Visited.insert(Succ).second) - Worklist.push_back(Succ); - } +static bool isSafeNonExitTerminator(TermInst *TI) { + switch (TI->getTermKind()) { + case TermKind::BranchInst: + case TermKind::CondBranchInst: + case TermKind::SwitchValueInst: + case TermKind::SwitchEnumInst: + case TermKind::SwitchEnumAddrInst: + case TermKind::DynamicMethodBranchInst: + case TermKind::CheckedCastBranchInst: + case TermKind::CheckedCastValueBranchInst: + case TermKind::CheckedCastAddrBranchInst: + return true; + case TermKind::UnreachableInst: + case TermKind::ReturnInst: + case TermKind::ThrowInst: + case TermKind::UnwindInst: + return false; + // yield is special because it can do arbitrary, + // potentially-process-terminating things. + case TermKind::YieldInst: + return false; + case TermKind::TryApplyInst: + return true; } - // Remove the blocks we never reached. Exclude the entry block from the iteration because it's - // not included in the Visited set. - bool Changed = false; - for (auto It = std::next(Fn.begin()), End = Fn.end(); It != End; ) { - auto *BB = &*It++; - if (!Visited.count(BB)) { - removeDeadBlock(BB); - Changed = true; - } - } - return Changed; + llvm_unreachable("Unhandled TermKind in switch."); +} + +static bool isTrapNoReturnFunction(ApplyInst *AI) { + const char *fatalName = MANGLE_AS_STRING( + MANGLE_SYM(s18_fatalErrorMessageyys12StaticStringV_AcCSutF)); + auto *Fn = AI->getReferencedFunctionOrNull(); + + // We use endswith here since if we specialize fatal error we will always + // prepend the specialization records to fatalName. + if (!Fn || !Fn->getName().endswith(fatalName)) + return false; + + return true; +} + +bool swift::findAllNonFailureExitBBs( + SILFunction *F, llvm::TinyPtrVector &BBs) { + for (SILBasicBlock &BB : *F) { + TermInst *TI = BB.getTerminator(); + + // If we know that this terminator is not an exit terminator, continue. + if (isSafeNonExitTerminator(TI)) + continue; + + // A return inst is always a non-failure exit bb. + if (TI->isFunctionExiting()) { + BBs.push_back(&BB); + continue; + } + + // If we don't have an unreachable inst at this point, this is a terminator + // we don't understand. Be conservative and return false. + if (!isa(TI)) + return false; + + // Ok, at this point we know we have a terminator. If it is the only + // instruction in our BB, it is a failure BB. continue... + if (TI == &*BB.begin()) + continue; + + // If the unreachable is preceded by a no-return apply inst, then it is a + // non-failure exit BB. Add it to our list and continue. + auto PrevIter = std::prev(SILBasicBlock::iterator(TI)); + if (auto *AI = dyn_cast(&*PrevIter)) { + if (AI->isCalleeNoReturn() && !isTrapNoReturnFunction(AI)) { + BBs.push_back(&BB); + continue; + } + } + + // Otherwise, it must be a failure BB where we leak, continue. + continue; + } + + // We understood all terminators, return true. + return true; } diff --git a/lib/SILOptimizer/Utils/CMakeLists.txt b/lib/SILOptimizer/Utils/CMakeLists.txt index b45f12afffd..36f43361f0a 100644 --- a/lib/SILOptimizer/Utils/CMakeLists.txt +++ b/lib/SILOptimizer/Utils/CMakeLists.txt @@ -1,5 +1,6 @@ silopt_register_sources( - CFG.cpp + BasicBlockOptUtils.cpp + CFGOptUtils.cpp CanonicalizeInstruction.cpp CastOptimizer.cpp CheckedCastBrJumpThreading.cpp @@ -9,8 +10,8 @@ silopt_register_sources( Existential.cpp GenericCloner.cpp Generics.cpp + InstOptUtils.cpp LoadStoreOptUtils.cpp - Local.cpp LoopUtils.cpp OptimizerStatsUtils.cpp PerformanceInlinerUtils.cpp @@ -18,4 +19,5 @@ silopt_register_sources( SILSSAUpdater.cpp SpecializationMangler.cpp StackNesting.cpp + ValueLifetime.cpp ) diff --git a/lib/SILOptimizer/Utils/CastOptimizer.cpp b/lib/SILOptimizer/Utils/CastOptimizer.cpp index da136f54532..8891d3bb643 100644 --- a/lib/SILOptimizer/Utils/CastOptimizer.cpp +++ b/lib/SILOptimizer/Utils/CastOptimizer.cpp @@ -26,15 +26,15 @@ #include "swift/SIL/InstructionUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" #include "swift/SIL/TypeLowering.h" #include "swift/SILOptimizer/Analysis/ARCAnalysis.h" #include "swift/SILOptimizer/Analysis/Analysis.h" #include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSwitch.h" @@ -1215,8 +1215,8 @@ CastOptimizer::optimizeCheckedCastBranchInst(CheckedCastBranchInst *Inst) { if (Inst->isExact()) return nullptr; - // Local helper we use to simplify replacing a checked_cast_branch with an - // optimized checked cast branch. + // InstOptUtils.helper we use to simplify replacing a checked_cast_branch with + // an optimized checked cast branch. auto replaceCastHelper = [](SILBuilderWithScope &B, SILDynamicCastInst dynamicCast, MetatypeInst *mi) -> SILInstruction * { diff --git a/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp b/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp index 3f49cae3c1d..390e6e826a6 100644 --- a/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp +++ b/lib/SILOptimizer/Utils/CheckedCastBrJumpThreading.cpp @@ -11,15 +11,16 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-simplify-cfg" +#include "swift/SIL/InstructionUtils.h" +#include "swift/SIL/SILInstruction.h" +#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/Utils/BasicBlockOptUtils.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILInliner.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" -#include "swift/SIL/SILInstruction.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/SILInliner.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/ConstantFolding.cpp b/lib/SILOptimizer/Utils/ConstantFolding.cpp index 978da5e7d29..dc276b27f4d 100644 --- a/lib/SILOptimizer/Utils/ConstantFolding.cpp +++ b/lib/SILOptimizer/Utils/ConstantFolding.cpp @@ -18,8 +18,7 @@ #include "swift/SIL/PatternMatch.h" #include "swift/SIL/SILBuilder.h" #include "swift/SILOptimizer/Utils/CastOptimizer.h" -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SIL/InstructionUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 4dff796e54c..7ebaccf1065 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -11,13 +11,13 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "sil-devirtualize-utility" -#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" #include "swift/SILOptimizer/Utils/Devirtualize.h" #include "swift/AST/Decl.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" #include "swift/AST/Types.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/OptimizationRemark.h" #include "swift/SIL/SILDeclRef.h" #include "swift/SIL/SILFunction.h" @@ -25,8 +25,8 @@ #include "swift/SIL/SILModule.h" #include "swift/SIL/SILType.h" #include "swift/SIL/SILValue.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Analysis/ClassHierarchyAnalysis.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/Statistic.h" diff --git a/lib/SILOptimizer/Utils/Existential.cpp b/lib/SILOptimizer/Utils/Existential.cpp index 04d10a6990b..07a78d27479 100644 --- a/lib/SILOptimizer/Utils/Existential.cpp +++ b/lib/SILOptimizer/Utils/Existential.cpp @@ -15,8 +15,8 @@ #include "swift/AST/ProtocolConformance.h" #include "swift/SIL/BasicBlockUtils.h" #include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/ADT/SmallPtrSet.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/GenericCloner.cpp b/lib/SILOptimizer/Utils/GenericCloner.cpp index ccee64e9647..f41e67384b1 100644 --- a/lib/SILOptimizer/Utils/GenericCloner.cpp +++ b/lib/SILOptimizer/Utils/GenericCloner.cpp @@ -15,11 +15,11 @@ #include "swift/AST/Type.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILFunction.h" -#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "swift/SIL/SILInstruction.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILValue.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" +#include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" diff --git a/lib/SILOptimizer/Utils/Local.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp similarity index 74% rename from lib/SILOptimizer/Utils/Local.cpp rename to lib/SILOptimizer/Utils/InstOptUtils.cpp index 55852170192..c5677537e07 100644 --- a/lib/SILOptimizer/Utils/Local.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -1,8 +1,8 @@ -//===--- Local.cpp - Functions that perform local SIL transformations. ----===// +//===--- InstOptUtils.cpp - SILOptimizer instruction utilities ------------===// // // This source file is part of the Swift.org open source project // -// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors +// Copyright (c) 2014 - 2019 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 @@ -10,22 +10,22 @@ // //===----------------------------------------------------------------------===// -#include "swift/SILOptimizer/Utils/Local.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Analysis/Analysis.h" -#include "swift/SILOptimizer/Analysis/ARCAnalysis.h" -#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/SubstitutionMap.h" +#include "swift/SIL/BasicBlockUtils.h" +#include "swift/SIL/DebugUtils.h" #include "swift/SIL/DynamicCasts.h" +#include "swift/SIL/InstructionUtils.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" #include "swift/SIL/TypeLowering.h" -#include "swift/SIL/DebugUtils.h" -#include "swift/SIL/InstructionUtils.h" -#include "swift/SIL/BasicBlockUtils.h" +#include "swift/SILOptimizer/Analysis/ARCAnalysis.h" +#include "swift/SILOptimizer/Analysis/Analysis.h" +#include "swift/SILOptimizer/Analysis/DominanceAnalysis.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/StringSwitch.h" @@ -67,7 +67,8 @@ swift::createIncrementBefore(SILValue Ptr, SILInstruction *InsertPt) { /// Creates a decrement on \p Ptr before insertion point \p InsertPt that /// creates a strong_release if \p Ptr has reference semantics itself or -/// a release_value if \p Ptr is a non-trivial value without reference-semantics. +/// a release_value if \p Ptr is a non-trivial value without +/// reference-semantics. NullablePtr swift::createDecrementBefore(SILValue Ptr, SILInstruction *InsertPt) { // Setup the builder we will use to insert at our insertion point. @@ -92,13 +93,12 @@ swift::createDecrementBefore(SILValue Ptr, SILInstruction *InsertPt) { /// Perform a fast local check to see if the instruction is dead. /// /// This routine only examines the state of the instruction at hand. -bool -swift::isInstructionTriviallyDead(SILInstruction *I) { +bool swift::isInstructionTriviallyDead(SILInstruction *I) { // At Onone, consider all uses, including the debug_info. // This way, debug_info is preserved at Onone. - if (I->hasUsesOfAnyResult() && - I->getFunction()->getEffectiveOptimizationMode() <= - OptimizationMode::NoOptimization) + if (I->hasUsesOfAnyResult() + && I->getFunction()->getEffectiveOptimizationMode() + <= OptimizationMode::NoOptimization) return false; if (!onlyHaveDebugUsesOfAllResults(I) || isa(I)) @@ -129,7 +129,7 @@ swift::isInstructionTriviallyDead(SILInstruction *I) { // operation so we can remove these if they are trivially dead. if (isa(I)) return true; - + if (!I->mayHaveSideEffects()) return true; @@ -167,7 +167,7 @@ bool swift::isIntermediateRelease(SILInstruction *I, } namespace { - using CallbackTy = llvm::function_ref; +using CallbackTy = llvm::function_ref; } // end anonymous namespace void swift::recursivelyDeleteTriviallyDeadInstructions( @@ -200,8 +200,8 @@ void swift::recursivelyDeleteTriviallyDeadInstructions( // If the operand is an instruction that is only used by the instruction // being deleted, delete it. if (auto *OpValInst = OpVal->getDefiningInstruction()) - if (!DeadInsts.count(OpValInst) && - isInstructionTriviallyDead(OpValInst)) + if (!DeadInsts.count(OpValInst) + && isInstructionTriviallyDead(OpValInst)) NextInsts.insert(OpValInst); } @@ -243,8 +243,7 @@ void swift::recursivelyDeleteTriviallyDeadInstructions(SILInstruction *I, recursivelyDeleteTriviallyDeadInstructions(AI, Force, Callback); } -void swift::eraseUsesOfInstruction(SILInstruction *Inst, - CallbackTy Callback) { +void swift::eraseUsesOfInstruction(SILInstruction *Inst, CallbackTy Callback) { for (auto result : Inst->getResults()) { while (!result->use_empty()) { auto UI = result->use_begin(); @@ -274,8 +273,8 @@ void swift::eraseUsesOfInstruction(SILInstruction *Inst, } } -void swift:: -collectUsesOfValue(SILValue V, llvm::SmallPtrSetImpl &Insts) { +void swift::collectUsesOfValue(SILValue V, + llvm::SmallPtrSetImpl &Insts) { for (auto UI = V->use_begin(), E = V->use_end(); UI != E; UI++) { auto *User = UI->getUser(); // Instruction has been processed. @@ -311,7 +310,7 @@ FullApplySite swift::findApplyFromDevirtualizedResult(SILValue V) { if (isa(V) || isa(V) || isa(V)) return findApplyFromDevirtualizedResult( - cast(V)->getOperand(0)); + cast(V)->getOperand(0)); return FullApplySite(); } @@ -335,14 +334,14 @@ bool swift::mayBindDynamicSelf(SILFunction *F) { static SILValue skipAddrProjections(SILValue V) { for (;;) { switch (V->getKind()) { - case ValueKind::IndexAddrInst: - case ValueKind::IndexRawPointerInst: - case ValueKind::StructElementAddrInst: - case ValueKind::TupleElementAddrInst: - V = cast(V)->getOperand(0); - break; - default: - return V; + case ValueKind::IndexAddrInst: + case ValueKind::IndexRawPointerInst: + case ValueKind::StructElementAddrInst: + case ValueKind::TupleElementAddrInst: + V = cast(V)->getOperand(0); + break; + default: + return V; } } llvm_unreachable("there is no escape from an infinite loop"); @@ -374,7 +373,7 @@ bool swift::isAddressOfArrayElement(SILValue addr) { void swift::placeFuncRef(ApplyInst *AI, DominanceInfo *DT) { FunctionRefInst *FuncRef = cast(AI->getCallee()); SILBasicBlock *DomBB = - DT->findNearestCommonDominator(AI->getParent(), FuncRef->getParent()); + DT->findNearestCommonDominator(AI->getParent(), FuncRef->getParent()); if (DomBB == AI->getParent() && DomBB != FuncRef->getParent()) // Prefer to place the FuncRef immediately before the call. Since we're // moving FuncRef up, this must be the only call to it in the block. @@ -409,7 +408,10 @@ TermInst *swift::addArgumentToBranch(SILValue Val, SILBasicBlock *Dest, assert(FalseArgs.size() == Dest->getNumArguments()); } - return Builder.createCondBranch(CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), CBI->getFalseBBCount()); + return Builder.createCondBranch( + CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, + CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), + CBI->getFalseBBCount()); } if (auto *BI = dyn_cast(Branch)) { @@ -427,8 +429,7 @@ TermInst *swift::addArgumentToBranch(SILValue Val, SILBasicBlock *Dest, } SILLinkage swift::getSpecializedLinkage(SILFunction *F, SILLinkage L) { - if (hasPrivateVisibility(L) && - !F->isSerialized()) { + if (hasPrivateVisibility(L) && !F->isSerialized()) { // Specializations of private symbols should remain so, unless // they were serialized, which can only happen when specializing // definitions from a standard library built with -sil-serialize-all. @@ -438,30 +439,6 @@ SILLinkage swift::getSpecializedLinkage(SILFunction *F, SILLinkage L) { return SILLinkage::Shared; } -/// Remove all instructions in the body of \p BB in safe manner by using -/// undef. -void swift::clearBlockBody(SILBasicBlock *BB) { - // Instructions in the dead block may be used by other dead blocks. Replace - // any uses of them with undef values. - while (!BB->empty()) { - // Grab the last instruction in the BB. - auto *Inst = &BB->back(); - - // Replace any still-remaining uses with undef values and erase. - Inst->replaceAllUsesOfAllResultsWithUndef(); - Inst->eraseFromParent(); - } -} - -// Handle the mechanical aspects of removing an unreachable block. -void swift::removeDeadBlock(SILBasicBlock *BB) { - // Clear the body of BB. - clearBlockBody(BB); - - // Now that the BB is empty, eliminate it. - BB->eraseFromParent(); -} - /// Cast a value into the expected, ABI compatible type if necessary. /// This may happen e.g. when: /// - a type of the return value is a subclass of the expected return type. @@ -475,22 +452,23 @@ void swift::removeDeadBlock(SILBasicBlock *BB) { /// If CheckOnly is not set, then a casting code is generated and the final /// casted value is returned. /// -/// NOTE: We intentionally combine the checking of the cast's handling possibility -/// and the transformation performing the cast in the same function, to avoid -/// any divergence between the check and the implementation in the future. +/// NOTE: We intentionally combine the checking of the cast's handling +/// possibility and the transformation performing the cast in the same function, +/// to avoid any divergence between the check and the implementation in the +/// future. /// /// NOTE: The implementation of this function is very closely related to the /// rules checked by SILVerifier::requireABICompatibleFunctionTypes. SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, - SILValue Value, - SILType SrcTy, SILType DestTy) { + SILValue Value, SILType SrcTy, + SILType DestTy) { // No cast is required if types are the same. if (SrcTy == DestTy) return Value; - assert(SrcTy.isAddress() == DestTy.isAddress() && - "Addresses aren't compatible with values"); + assert(SrcTy.isAddress() == DestTy.isAddress() + && "Addresses aren't compatible with values"); if (SrcTy.isAddress() && DestTy.isAddress()) { // Cast between two addresses and that's it. @@ -503,8 +481,7 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, return B->createUpcast(Loc, Value, DestTy); } - if (SrcTy.isHeapObjectReferenceType() && - DestTy.isHeapObjectReferenceType()) { + if (SrcTy.isHeapObjectReferenceType() && DestTy.isHeapObjectReferenceType()) { return B->createUncheckedRefCast(Loc, Value, DestTy); } @@ -514,11 +491,10 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, // If B.Type needs to be casted to A.Type and // A is a superclass of B, then it can be done by means // of a simple upcast. - if (mt2.getInstanceType()->isExactSuperclassOf( - mt1.getInstanceType())) { + if (mt2.getInstanceType()->isExactSuperclassOf(mt1.getInstanceType())) { return B->createUpcast(Loc, Value, DestTy); } - + // Cast between two metatypes and that's it. return B->createUncheckedBitCast(Loc, Value, DestTy); } @@ -554,15 +530,12 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, // Handle the Some case. B->setInsertionPoint(SomeBB); - SILValue UnwrappedValue = B->createUncheckedEnumData(Loc, Value, - SomeDecl); + SILValue UnwrappedValue = B->createUncheckedEnumData(Loc, Value, SomeDecl); // Cast the unwrapped value. - auto CastedUnwrappedValue = - castValueToABICompatibleType(B, Loc, UnwrappedValue, - OptionalSrcTy, - OptionalDestTy); + auto CastedUnwrappedValue = castValueToABICompatibleType( + B, Loc, UnwrappedValue, OptionalSrcTy, OptionalDestTy); // Wrap into optional. - auto CastedValue = B->createOptionalSome(Loc, CastedUnwrappedValue, DestTy); + auto CastedValue = B->createOptionalSome(Loc, CastedUnwrappedValue, DestTy); B->createBranch(Loc, ContBB, {CastedValue}); // Handle the None case. @@ -576,18 +549,17 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, // Src is not optional, but dest is optional. if (!OptionalSrcTy && OptionalDestTy) { - auto OptionalSrcCanTy = OptionalType::get(SrcTy.getASTType()) - ->getCanonicalType(); - auto LoweredOptionalSrcType = SILType::getPrimitiveObjectType( - OptionalSrcCanTy); + auto OptionalSrcCanTy = + OptionalType::get(SrcTy.getASTType())->getCanonicalType(); + auto LoweredOptionalSrcType = + SILType::getPrimitiveObjectType(OptionalSrcCanTy); // Wrap the source value into an optional first. - SILValue WrappedValue = B->createOptionalSome(Loc, Value, - LoweredOptionalSrcType); + SILValue WrappedValue = + B->createOptionalSome(Loc, Value, LoweredOptionalSrcType); // Cast the wrapped value. return castValueToABICompatibleType(B, Loc, WrappedValue, - WrappedValue->getType(), - DestTy); + WrappedValue->getType(), DestTy); } // Handle tuple types. @@ -609,12 +581,13 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, // Function types are interchangeable if they're also ABI-compatible. if (SrcTy.is()) { if (DestTy.is()) { - assert(SrcTy.getAs()->isNoEscape() == - DestTy.getAs()->isNoEscape() || - SrcTy.getAs()->getRepresentation() != - SILFunctionType::Representation::Thick && - "Swift thick functions that differ in escapeness are not ABI " - "compatible"); + assert(SrcTy.getAs()->isNoEscape() + == DestTy.getAs()->isNoEscape() + || SrcTy.getAs()->getRepresentation() + != SILFunctionType::Representation::Thick + && "Swift thick functions that differ in escapeness are " + "not ABI " + "compatible"); // Insert convert_function. return B->createConvertFunction(Loc, Value, DestTy, /*WithoutActuallyEscaping=*/false); @@ -626,11 +599,12 @@ SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, llvm_unreachable("Unknown combination of types for casting"); } -ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *ABI, unsigned Index){ +ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *ABI, + unsigned Index) { SILBasicBlock::iterator Iter(ABI); Iter++; - assert(Iter != ABI->getParent()->end() && - "alloc_box cannot be the last instruction of a block"); + assert(Iter != ABI->getParent()->end() + && "alloc_box cannot be the last instruction of a block"); SILInstruction *NextInst = &*Iter; if (auto *PBI = dyn_cast(NextInst)) { if (PBI->getOperand() == ABI && PBI->getFieldIndex() == Index) @@ -763,8 +737,8 @@ bool StringConcatenationOptimizer::extractStringConcatOperands() { auto *FRILeftFun = FRILeft->getReferencedFunctionOrNull(); auto *FRIRightFun = FRIRight->getReferencedFunctionOrNull(); - if (FRILeftFun->getEffectsKind() >= EffectsKind::ReleaseNone || - FRIRightFun->getEffectsKind() >= EffectsKind::ReleaseNone) + if (FRILeftFun->getEffectsKind() >= EffectsKind::ReleaseNone + || FRIRightFun->getEffectsKind() >= EffectsKind::ReleaseNone) return false; if (!FRILeftFun->hasSemanticsAttrs() || !FRIRightFun->hasSemanticsAttrs()) @@ -775,10 +749,10 @@ bool StringConcatenationOptimizer::extractStringConcatOperands() { // makeUTF8 should have following parameters: // (start: RawPointer, utf8CodeUnitCount: Word, isASCII: Int1) - if (!((FRILeftFun->hasSemanticsAttr("string.makeUTF8") && - AILeftOperandsNum == 5) || - (FRIRightFun->hasSemanticsAttr("string.makeUTF8") && - AIRightOperandsNum == 5))) + if (!((FRILeftFun->hasSemanticsAttr("string.makeUTF8") + && AILeftOperandsNum == 5) + || (FRIRightFun->hasSemanticsAttr("string.makeUTF8") + && AIRightOperandsNum == 5))) return false; SLILeft = dyn_cast(AILeft->getOperand(1)); @@ -789,12 +763,12 @@ bool StringConcatenationOptimizer::extractStringConcatOperands() { // Only UTF-8 and UTF-16 encoded string literals are supported by this // optimization. - if (SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF8 && - SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF16) + if (SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF8 + && SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF16) return false; - if (SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF8 && - SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF16) + if (SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF8 + && SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF16) return false; return true; @@ -817,8 +791,8 @@ void StringConcatenationOptimizer::adjustEncodings() { // If one of the string literals is UTF8 and another one is UTF16, // convert the UTF8-encoded string literal into UTF16-encoding first. - if (SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF8 && - SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF16) { + if (SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF8 + && SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF16) { FuncResultType = AIRight->getOperand(3); FRIConvertFromBuiltin = FRIRight; // Convert UTF8 representation into UTF16. @@ -826,8 +800,8 @@ void StringConcatenationOptimizer::adjustEncodings() { StringLiteralInst::Encoding::UTF16); } - if (SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF8 && - SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF16) { + if (SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF8 + && SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF16) { FuncResultType = AILeft->getOperand(3); FRIConvertFromBuiltin = FRILeft; // Convert UTF8 representation into UTF16. @@ -837,8 +811,9 @@ void StringConcatenationOptimizer::adjustEncodings() { // It should be impossible to have two operands with different // encodings at this point. - assert(SLILeft->getEncoding() == SLIRight->getEncoding() && - "Both operands of string concatenation should have the same encoding"); + assert( + SLILeft->getEncoding() == SLIRight->getEncoding() + && "Both operands of string concatenation should have the same encoding"); } /// Computes the length of a concatenated string literal. @@ -846,28 +821,27 @@ APInt StringConcatenationOptimizer::getConcatenatedLength() { // Real length of string literals computed based on its contents. // Length is in code units. auto SLILenLeft = SLILeft->getCodeUnitCount(); - (void) SLILenLeft; + (void)SLILenLeft; auto SLILenRight = SLIRight->getCodeUnitCount(); - (void) SLILenRight; + (void)SLILenRight; // Length of string literals as reported by string.make functions. auto *LenLeft = dyn_cast(AILeft->getOperand(2)); auto *LenRight = dyn_cast(AIRight->getOperand(2)); // Real and reported length should be the same. - assert(SLILenLeft == LenLeft->getValue() && - "Size of string literal in @_semantics(string.make) is wrong"); - - assert(SLILenRight == LenRight->getValue() && - "Size of string literal in @_semantics(string.make) is wrong"); + assert(SLILenLeft == LenLeft->getValue() + && "Size of string literal in @_semantics(string.make) is wrong"); + assert(SLILenRight == LenRight->getValue() + && "Size of string literal in @_semantics(string.make) is wrong"); // Compute length of the concatenated literal. return LenLeft->getValue() + LenRight->getValue(); } /// Computes the isAscii flag of a concatenated UTF8-encoded string literal. -bool StringConcatenationOptimizer::isAscii() const{ +bool StringConcatenationOptimizer::isAscii() const { // Add the isASCII argument in case of UTF8. // IsASCII is true only if IsASCII of both literals is true. auto *AsciiLeft = dyn_cast(AILeft->getOperand(3)); @@ -922,8 +896,8 @@ SingleValueInstruction *StringConcatenationOptimizer::optimize() { } /// Top level entry point -SingleValueInstruction * -swift::tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B) { +SingleValueInstruction *swift::tryToConcatenateStrings(ApplyInst *AI, + SILBuilder &B) { return StringConcatenationOptimizer(AI, B).optimize(); } @@ -1089,8 +1063,9 @@ static bool releaseCapturedArgsOfDeadPartialApply(PartialApplyInst *PAI, Args.emplace_back(v); } unsigned Delta = Params.size() - Args.size(); - assert(Delta <= Params.size() && "Error, more Args to partial apply than " - "params in its interface."); + assert(Delta <= Params.size() + && "Error, more Args to partial apply than " + "params in its interface."); Params = Params.drop_front(Delta); llvm::SmallVector ExitingBlocks; @@ -1106,7 +1081,8 @@ static bool releaseCapturedArgsOfDeadPartialApply(PartialApplyInst *PAI, SILParameterInfo PInfo = Params[i]; // If we are not going to destroy this partial_apply, continue. - if (!shouldDestroyPartialApplyCapturedArg(Arg, PInfo, Builder.getFunction())) + if (!shouldDestroyPartialApplyCapturedArg(Arg, PInfo, + Builder.getFunction())) continue; // If we have an object, we will not have live range issues, just continue. @@ -1161,10 +1137,10 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure, // A stack allocated partial apply does not have any release users. Delete it // if the only users are the dealloc_stack and mark_dependence instructions. if (PA && PA->isOnStack()) { - SmallVector DeleteInsts; + SmallVector DeleteInsts; for (auto *Use : PA->getUses()) { - if (isa(Use->getUser()) || - isa(Use->getUser())) + if (isa(Use->getUser()) + || isa(Use->getUser())) DeleteInsts.push_back(Use->getUser()); else if (!deadMarkDependenceUser(Use->getUser(), DeleteInsts)) return false; @@ -1201,10 +1177,10 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure, // Then delete all user instructions in reverse so that leaf uses are deleted // first. for (auto *User : reverse(Tracker.getTrackedUsers())) { - assert(User->getResults().empty() || - useHasTransitiveOwnership(User) && - "We expect only ARC operations without " - "results or a cast from escape to noescape without users"); + assert(User->getResults().empty() + || useHasTransitiveOwnership(User) + && "We expect only ARC operations without " + "results or a cast from escape to noescape without users"); Callbacks.DeleteInst(User); } @@ -1214,273 +1190,16 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure, return true; } -//===----------------------------------------------------------------------===// -// Value Lifetime -//===----------------------------------------------------------------------===// - -void ValueLifetimeAnalysis::propagateLiveness() { - assert(LiveBlocks.empty() && "frontier computed twice"); - - auto DefBB = DefValue->getParentBlock(); - llvm::SmallVector Worklist; - int NumUsersBeforeDef = 0; - - // Find the initial set of blocks where the value is live, because - // it is used in those blocks. - for (SILInstruction *User : UserSet) { - SILBasicBlock *UserBlock = User->getParent(); - if (LiveBlocks.insert(UserBlock)) - Worklist.push_back(UserBlock); - - // A user in the DefBB could potentially be located before the DefValue. - if (UserBlock == DefBB) - NumUsersBeforeDef++; - } - // Don't count any users in the DefBB which are actually located _after_ - // the DefValue. - auto InstIter = DefValue->getIterator(); - while (NumUsersBeforeDef > 0 && ++InstIter != DefBB->end()) { - if (UserSet.count(&*InstIter)) - NumUsersBeforeDef--; - } - - // Now propagate liveness backwards until we hit the block that defines the - // value. - while (!Worklist.empty()) { - auto *BB = Worklist.pop_back_val(); - - // Don't go beyond the definition. - if (BB == DefBB && NumUsersBeforeDef == 0) - continue; - - for (SILBasicBlock *Pred : BB->getPredecessorBlocks()) { - // If it's already in the set, then we've already queued and/or - // processed the predecessors. - if (LiveBlocks.insert(Pred)) - Worklist.push_back(Pred); - } - } -} - -SILInstruction *ValueLifetimeAnalysis:: findLastUserInBlock(SILBasicBlock *BB) { - // Walk backwards in BB looking for last use of the value. - for (auto II = BB->rbegin(); II != BB->rend(); ++II) { - assert(DefValue != &*II && "Found def before finding use!"); - - if (UserSet.count(&*II)) - return &*II; - } - llvm_unreachable("Expected to find use of value in block!"); -} - -bool ValueLifetimeAnalysis::computeFrontier(Frontier &Fr, Mode mode, - DeadEndBlocks *DEBlocks) { - assert(!isAliveAtBeginOfBlock(DefValue->getFunction()->getEntryBlock()) && - "Can't compute frontier for def which does not dominate all uses"); - - bool NoCriticalEdges = true; - - // Exit-blocks from the lifetime region. The value is live at the end of - // a predecessor block but not in the frontier block itself. - llvm::SmallSetVector FrontierBlocks; - - // Blocks where the value is live at the end of the block and which have - // a frontier block as successor. - llvm::SmallSetVector LiveOutBlocks; - - /// The lifetime ends if we have a live block and a not-live successor. - for (SILBasicBlock *BB : LiveBlocks) { - if (DEBlocks && DEBlocks->isDeadEnd(BB)) - continue; - - bool LiveInSucc = false; - bool DeadInSucc = false; - for (const SILSuccessor &Succ : BB->getSuccessors()) { - if (isAliveAtBeginOfBlock(Succ)) { - LiveInSucc = true; - } else if (!DEBlocks || !DEBlocks->isDeadEnd(Succ)) { - DeadInSucc = true; - } - } - if (!LiveInSucc) { - // The value is not live in any of the successor blocks. This means the - // block contains a last use of the value. The next instruction after - // the last use is part of the frontier. - SILInstruction *LastUser = findLastUserInBlock(BB); - if (!isa(LastUser)) { - Fr.push_back(&*std::next(LastUser->getIterator())); - continue; - } - // In case the last user is a TermInst we add all successor blocks to the - // frontier (see below). - assert(DeadInSucc && "The final using TermInst must have successors"); - } - if (DeadInSucc) { - if (mode == UsersMustPostDomDef) - return false; - - // The value is not live in some of the successor blocks. - LiveOutBlocks.insert(BB); - for (const SILSuccessor &Succ : BB->getSuccessors()) { - if (!isAliveAtBeginOfBlock(Succ)) { - // It's an "exit" edge from the lifetime region. - FrontierBlocks.insert(Succ); - } - } - } - } - // Handle "exit" edges from the lifetime region. - llvm::SmallPtrSet UnhandledFrontierBlocks; - for (SILBasicBlock *FrontierBB: FrontierBlocks) { - assert(mode != UsersMustPostDomDef); - bool needSplit = false; - // If the value is live only in part of the predecessor blocks we have to - // split those predecessor edges. - for (SILBasicBlock *Pred : FrontierBB->getPredecessorBlocks()) { - if (!LiveOutBlocks.count(Pred)) { - needSplit = true; - break; - } - } - if (needSplit) { - if (mode == DontModifyCFG) - return false; - // We need to split the critical edge to create a frontier instruction. - UnhandledFrontierBlocks.insert(FrontierBB); - } else { - // The first instruction of the exit-block is part of the frontier. - Fr.push_back(&*FrontierBB->begin()); - } - } - // Split critical edges from the lifetime region to not yet handled frontier - // blocks. - for (SILBasicBlock *FrontierPred : LiveOutBlocks) { - assert(mode != UsersMustPostDomDef); - auto *T = FrontierPred->getTerminator(); - // Cache the successor blocks because splitting critical edges invalidates - // the successor list iterator of T. - llvm::SmallVector SuccBlocks; - for (const SILSuccessor &Succ : T->getSuccessors()) - SuccBlocks.push_back(Succ); - - for (unsigned i = 0, e = SuccBlocks.size(); i != e; ++i) { - if (UnhandledFrontierBlocks.count(SuccBlocks[i])) { - assert(mode == AllowToModifyCFG); - assert(isCriticalEdge(T, i) && "actually not a critical edge?"); - SILBasicBlock *NewBlock = splitEdge(T, i); - // The single terminator instruction is part of the frontier. - Fr.push_back(&*NewBlock->begin()); - NoCriticalEdges = false; - } - } - } - return NoCriticalEdges; -} - -bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *Inst) { - SILBasicBlock *BB = Inst->getParent(); - // Check if the value is not live anywhere in Inst's block. - if (!LiveBlocks.count(BB)) - return false; - for (const SILSuccessor &Succ : BB->getSuccessors()) { - // If the value is live at the beginning of any successor block it is also - // live at the end of BB and therefore Inst is definitely in the lifetime - // region (Note that we don't check in upward direction against the value's - // definition). - if (isAliveAtBeginOfBlock(Succ)) - return true; - } - // The value is live in the block but not at the end of the block. Check if - // Inst is located before (or at) the last use. - for (auto II = BB->rbegin(); II != BB->rend(); ++II) { - if (UserSet.count(&*II)) { - return true; - } - if (Inst == &*II) - return false; - } - llvm_unreachable("Expected to find use of value in block!"); -} - -// Searches \p BB backwards from the instruction before \p FrontierInst -// to the beginning of the list and returns true if we find a dealloc_ref -// /before/ we find \p DefValue (the instruction that defines our target value). -static bool blockContainsDeallocRef(SILBasicBlock *BB, SILInstruction *DefValue, - SILInstruction *FrontierInst) { - SILBasicBlock::reverse_iterator End = BB->rend(); - SILBasicBlock::reverse_iterator Iter = FrontierInst->getReverseIterator(); - for (++Iter; Iter != End; ++Iter) { - SILInstruction *I = &*Iter; - if (isa(I)) - return true; - if (I == DefValue) - return false; - } - return false; -} - -bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &Frontier) { - SmallPtrSet FrontierBlocks; - // Search in live blocks where the value is not alive until the end of the - // block, i.e. the live range is terminated by a frontier instruction. - for (SILInstruction *FrontierInst : Frontier) { - SILBasicBlock *BB = FrontierInst->getParent(); - if (blockContainsDeallocRef(BB, DefValue, FrontierInst)) - return true; - FrontierBlocks.insert(BB); - } - // Search in all other live blocks where the value is alive until the end of - // the block. - for (SILBasicBlock *BB : LiveBlocks) { - if (FrontierBlocks.count(BB) == 0) { - if (blockContainsDeallocRef(BB, DefValue, BB->getTerminator())) - return true; - } - } - return false; -} - -void ValueLifetimeAnalysis::dump() const { - llvm::errs() << "lifetime of def: " << *DefValue; - for (SILInstruction *Use : UserSet) { - llvm::errs() << " use: " << *Use; - } - llvm::errs() << " live blocks:"; - for (SILBasicBlock *BB : LiveBlocks) { - llvm::errs() << ' ' << BB->getDebugID(); - } - llvm::errs() << '\n'; -} - -// FIXME: Remove this. SILCloner should not create critical edges. -bool BasicBlockCloner::splitCriticalEdges(DominanceInfo *DT, - SILLoopInfo *LI) { - bool changed = false; - // Remove any critical edges that the EdgeThreadingCloner may have - // accidentally created. - for (unsigned succIdx = 0, succEnd = origBB->getSuccessors().size(); - succIdx != succEnd; ++succIdx) { - if (nullptr != splitCriticalEdge(origBB->getTerminator(), succIdx, DT, LI)) - changed |= true; - } - for (unsigned succIdx = 0, succEnd = getNewBB()->getSuccessors().size(); - succIdx != succEnd; ++succIdx) { - auto *newBB = - splitCriticalEdge(getNewBB()->getTerminator(), succIdx, DT, LI); - changed |= (newBB != nullptr); - } - return changed; -} - bool swift::simplifyUsers(SingleValueInstruction *I) { bool Changed = false; - for (auto UI = I->use_begin(), UE = I->use_end(); UI != UE; ) { + for (auto UI = I->use_begin(), UE = I->use_end(); UI != UE;) { SILInstruction *User = UI->getUser(); ++UI; auto SVI = dyn_cast(User); - if (!SVI) continue; + if (!SVI) + continue; SILValue S = simplifyInstruction(SVI); if (!S) @@ -1651,8 +1370,7 @@ bool swift::canReplaceLoadSequence(SILInstruction *I) { /// FIXME: this utility does not make sense as an API. How can the caller /// guarantee that the only uses of `I` are struct_element_addr and /// tuple_element_addr? -void swift::replaceLoadSequence(SILInstruction *I, - SILValue Value) { +void swift::replaceLoadSequence(SILInstruction *I, SILValue Value) { if (auto *CAI = dyn_cast(I)) { SILBuilder B(CAI); B.createStore(CAI->getLoc(), Value, CAI->getDest(), @@ -1746,48 +1464,6 @@ bool swift::calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl) { llvm_unreachable("Unhandled access level in switch."); } -void StaticInitCloner::add(SILInstruction *InitVal) { - // Don't schedule an instruction twice for cloning. - if (NumOpsToClone.count(InitVal) != 0) - return; - - ArrayRef Ops = InitVal->getAllOperands(); - NumOpsToClone[InitVal] = Ops.size(); - if (Ops.empty()) { - // It's an instruction without operands, e.g. a literal. It's ready to be - // cloned first. - ReadyToClone.push_back(InitVal); - } else { - // Recursively add all operands. - for (const Operand &Op : Ops) { - add(cast(Op.get())); - } - } -} - -SingleValueInstruction * -StaticInitCloner::clone(SingleValueInstruction *InitVal) { - assert(NumOpsToClone.count(InitVal) != 0 && "InitVal was not added"); - // Find the right order to clone: all operands of an instruction must be - // cloned before the instruction itself. - while (!ReadyToClone.empty()) { - SILInstruction *I = ReadyToClone.pop_back_val(); - - // Clone the instruction into the SILGlobalVariable - visit(I); - - // Check if users of I can now be cloned. - for (SILValue result : I->getResults()) { - for (Operand *Use : result->getUses()) { - SILInstruction *User = Use->getUser(); - if (NumOpsToClone.count(User) != 0 && --NumOpsToClone[User] == 0) - ReadyToClone.push_back(User); - } - } - } - return cast(getMappedValue(InitVal)); -} - Optional swift::findLocalApplySites(FunctionRefBaseInst *FRI) { SmallVector worklist(FRI->use_begin(), FRI->use_end()); @@ -1880,7 +1556,8 @@ void swift::insertDestroyOfCapturedArguments( PAI->getModule()); auto loc = RegularLocation::getAutoGeneratedLocation(); for (auto &arg : PAI->getArgumentOperands()) { - if (!shouldInsertDestroy(arg.get())) continue; + if (!shouldInsertDestroy(arg.get())) + continue; unsigned calleeArgumentIndex = site.getCalleeArgIndex(arg); assert(calleeArgumentIndex >= calleeConv.getSILArgIndexOfFirstParam()); auto paramInfo = calleeConv.getParamInfoForSILArg(calleeArgumentIndex); diff --git a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp index a16be4bc5df..93dcad0c477 100644 --- a/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp +++ b/lib/SILOptimizer/Utils/LoadStoreOptUtils.cpp @@ -13,7 +13,7 @@ #define DEBUG_TYPE "sil-lsbase" #include "swift/SILOptimizer/Utils/LoadStoreOptUtils.h" #include "swift/SIL/InstructionUtils.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/LoopUtils.cpp b/lib/SILOptimizer/Utils/LoopUtils.cpp index 0437d5b6d3d..9f0802b62f5 100644 --- a/lib/SILOptimizer/Utils/LoopUtils.cpp +++ b/lib/SILOptimizer/Utils/LoopUtils.cpp @@ -19,7 +19,7 @@ #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILModule.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "llvm/Support/Debug.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp index 21e08139fe9..0f0f78d9f7e 100644 --- a/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp +++ b/lib/SILOptimizer/Utils/PerformanceInlinerUtils.cpp @@ -12,7 +12,7 @@ #include "swift/SILOptimizer/Utils/PerformanceInlinerUtils.h" #include "swift/AST/Module.h" -#include "swift/SILOptimizer/Utils/Local.h" +#include "swift/SILOptimizer/Utils/InstOptUtils.h" //===----------------------------------------------------------------------===// // ConstantTracker diff --git a/lib/SILOptimizer/Utils/SILInliner.cpp b/lib/SILOptimizer/Utils/SILInliner.cpp index d20ab659b74..8954dcb4f82 100644 --- a/lib/SILOptimizer/Utils/SILInliner.cpp +++ b/lib/SILOptimizer/Utils/SILInliner.cpp @@ -16,7 +16,7 @@ #include "swift/SIL/PrettyStackTrace.h" #include "swift/SIL/SILDebugScope.h" #include "swift/SIL/TypeSubstCloner.h" -#include "swift/SILOptimizer/Utils/CFG.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" #include "swift/SILOptimizer/Utils/SILOptFunctionBuilder.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Debug.h" diff --git a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp index fb9b17fe7eb..9625114d8fa 100644 --- a/lib/SILOptimizer/Utils/SILSSAUpdater.cpp +++ b/lib/SILOptimizer/Utils/SILSSAUpdater.cpp @@ -10,19 +10,18 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/Utils/SSAUpdaterImpl.h" +#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" #include "swift/Basic/Malloc.h" #include "swift/SIL/SILArgument.h" #include "swift/SIL/SILBasicBlock.h" #include "swift/SIL/SILBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILUndef.h" -#include "swift/SILOptimizer/Utils/CFG.h" -#include "swift/SILOptimizer/Utils/SILSSAUpdater.h" - +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/SSAUpdaterImpl.h" using namespace swift; diff --git a/lib/SILOptimizer/Utils/ValueLifetime.cpp b/lib/SILOptimizer/Utils/ValueLifetime.cpp new file mode 100644 index 00000000000..b4ef78b7d78 --- /dev/null +++ b/lib/SILOptimizer/Utils/ValueLifetime.cpp @@ -0,0 +1,251 @@ +//===--- ValueLifetime.cpp - ValueLifetimeAnalysis ------------------------===// +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2014 - 2019 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 +// +//===----------------------------------------------------------------------===// + +#include "swift/SILOptimizer/Utils/ValueLifetime.h" +#include "swift/SIL/BasicBlockUtils.h" +#include "swift/SILOptimizer/Utils/CFGOptUtils.h" + +using namespace swift; + +void ValueLifetimeAnalysis::propagateLiveness() { + assert(LiveBlocks.empty() && "frontier computed twice"); + + auto DefBB = DefValue->getParentBlock(); + llvm::SmallVector Worklist; + int NumUsersBeforeDef = 0; + + // Find the initial set of blocks where the value is live, because + // it is used in those blocks. + for (SILInstruction *User : UserSet) { + SILBasicBlock *UserBlock = User->getParent(); + if (LiveBlocks.insert(UserBlock)) + Worklist.push_back(UserBlock); + + // A user in the DefBB could potentially be located before the DefValue. + if (UserBlock == DefBB) + NumUsersBeforeDef++; + } + // Don't count any users in the DefBB which are actually located _after_ + // the DefValue. + auto InstIter = DefValue->getIterator(); + while (NumUsersBeforeDef > 0 && ++InstIter != DefBB->end()) { + if (UserSet.count(&*InstIter)) + NumUsersBeforeDef--; + } + + // Now propagate liveness backwards until we hit the block that defines the + // value. + while (!Worklist.empty()) { + auto *BB = Worklist.pop_back_val(); + + // Don't go beyond the definition. + if (BB == DefBB && NumUsersBeforeDef == 0) + continue; + + for (SILBasicBlock *Pred : BB->getPredecessorBlocks()) { + // If it's already in the set, then we've already queued and/or + // processed the predecessors. + if (LiveBlocks.insert(Pred)) + Worklist.push_back(Pred); + } + } +} + +SILInstruction *ValueLifetimeAnalysis:: findLastUserInBlock(SILBasicBlock *BB) { + // Walk backwards in BB looking for last use of the value. + for (auto II = BB->rbegin(); II != BB->rend(); ++II) { + assert(DefValue != &*II && "Found def before finding use!"); + + if (UserSet.count(&*II)) + return &*II; + } + llvm_unreachable("Expected to find use of value in block!"); +} + +bool ValueLifetimeAnalysis::computeFrontier(Frontier &Fr, Mode mode, + DeadEndBlocks *DEBlocks) { + assert(!isAliveAtBeginOfBlock(DefValue->getFunction()->getEntryBlock()) && + "Can't compute frontier for def which does not dominate all uses"); + + bool NoCriticalEdges = true; + + // Exit-blocks from the lifetime region. The value is live at the end of + // a predecessor block but not in the frontier block itself. + llvm::SmallSetVector FrontierBlocks; + + // Blocks where the value is live at the end of the block and which have + // a frontier block as successor. + llvm::SmallSetVector LiveOutBlocks; + + /// The lifetime ends if we have a live block and a not-live successor. + for (SILBasicBlock *BB : LiveBlocks) { + if (DEBlocks && DEBlocks->isDeadEnd(BB)) + continue; + + bool LiveInSucc = false; + bool DeadInSucc = false; + for (const SILSuccessor &Succ : BB->getSuccessors()) { + if (isAliveAtBeginOfBlock(Succ)) { + LiveInSucc = true; + } else if (!DEBlocks || !DEBlocks->isDeadEnd(Succ)) { + DeadInSucc = true; + } + } + if (!LiveInSucc) { + // The value is not live in any of the successor blocks. This means the + // block contains a last use of the value. The next instruction after + // the last use is part of the frontier. + SILInstruction *LastUser = findLastUserInBlock(BB); + if (!isa(LastUser)) { + Fr.push_back(&*std::next(LastUser->getIterator())); + continue; + } + // In case the last user is a TermInst we add all successor blocks to the + // frontier (see below). + assert(DeadInSucc && "The final using TermInst must have successors"); + } + if (DeadInSucc) { + if (mode == UsersMustPostDomDef) + return false; + + // The value is not live in some of the successor blocks. + LiveOutBlocks.insert(BB); + for (const SILSuccessor &Succ : BB->getSuccessors()) { + if (!isAliveAtBeginOfBlock(Succ)) { + // It's an "exit" edge from the lifetime region. + FrontierBlocks.insert(Succ); + } + } + } + } + // Handle "exit" edges from the lifetime region. + llvm::SmallPtrSet UnhandledFrontierBlocks; + for (SILBasicBlock *FrontierBB: FrontierBlocks) { + assert(mode != UsersMustPostDomDef); + bool needSplit = false; + // If the value is live only in part of the predecessor blocks we have to + // split those predecessor edges. + for (SILBasicBlock *Pred : FrontierBB->getPredecessorBlocks()) { + if (!LiveOutBlocks.count(Pred)) { + needSplit = true; + break; + } + } + if (needSplit) { + if (mode == DontModifyCFG) + return false; + // We need to split the critical edge to create a frontier instruction. + UnhandledFrontierBlocks.insert(FrontierBB); + } else { + // The first instruction of the exit-block is part of the frontier. + Fr.push_back(&*FrontierBB->begin()); + } + } + // Split critical edges from the lifetime region to not yet handled frontier + // blocks. + for (SILBasicBlock *FrontierPred : LiveOutBlocks) { + assert(mode != UsersMustPostDomDef); + auto *T = FrontierPred->getTerminator(); + // Cache the successor blocks because splitting critical edges invalidates + // the successor list iterator of T. + llvm::SmallVector SuccBlocks; + for (const SILSuccessor &Succ : T->getSuccessors()) + SuccBlocks.push_back(Succ); + + for (unsigned i = 0, e = SuccBlocks.size(); i != e; ++i) { + if (UnhandledFrontierBlocks.count(SuccBlocks[i])) { + assert(mode == AllowToModifyCFG); + assert(isCriticalEdge(T, i) && "actually not a critical edge?"); + SILBasicBlock *NewBlock = splitEdge(T, i); + // The single terminator instruction is part of the frontier. + Fr.push_back(&*NewBlock->begin()); + NoCriticalEdges = false; + } + } + } + return NoCriticalEdges; +} + +bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *Inst) { + SILBasicBlock *BB = Inst->getParent(); + // Check if the value is not live anywhere in Inst's block. + if (!LiveBlocks.count(BB)) + return false; + for (const SILSuccessor &Succ : BB->getSuccessors()) { + // If the value is live at the beginning of any successor block it is also + // live at the end of BB and therefore Inst is definitely in the lifetime + // region (Note that we don't check in upward direction against the value's + // definition). + if (isAliveAtBeginOfBlock(Succ)) + return true; + } + // The value is live in the block but not at the end of the block. Check if + // Inst is located before (or at) the last use. + for (auto II = BB->rbegin(); II != BB->rend(); ++II) { + if (UserSet.count(&*II)) { + return true; + } + if (Inst == &*II) + return false; + } + llvm_unreachable("Expected to find use of value in block!"); +} + +// Searches \p BB backwards from the instruction before \p FrontierInst +// to the beginning of the list and returns true if we find a dealloc_ref +// /before/ we find \p DefValue (the instruction that defines our target value). +static bool blockContainsDeallocRef(SILBasicBlock *BB, SILInstruction *DefValue, + SILInstruction *FrontierInst) { + SILBasicBlock::reverse_iterator End = BB->rend(); + SILBasicBlock::reverse_iterator Iter = FrontierInst->getReverseIterator(); + for (++Iter; Iter != End; ++Iter) { + SILInstruction *I = &*Iter; + if (isa(I)) + return true; + if (I == DefValue) + return false; + } + return false; +} + +bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &Frontier) { + SmallPtrSet FrontierBlocks; + // Search in live blocks where the value is not alive until the end of the + // block, i.e. the live range is terminated by a frontier instruction. + for (SILInstruction *FrontierInst : Frontier) { + SILBasicBlock *BB = FrontierInst->getParent(); + if (blockContainsDeallocRef(BB, DefValue, FrontierInst)) + return true; + FrontierBlocks.insert(BB); + } + // Search in all other live blocks where the value is alive until the end of + // the block. + for (SILBasicBlock *BB : LiveBlocks) { + if (FrontierBlocks.count(BB) == 0) { + if (blockContainsDeallocRef(BB, DefValue, BB->getTerminator())) + return true; + } + } + return false; +} + +void ValueLifetimeAnalysis::dump() const { + llvm::errs() << "lifetime of def: " << *DefValue; + for (SILInstruction *Use : UserSet) { + llvm::errs() << " use: " << *Use; + } + llvm::errs() << " live blocks:"; + for (SILBasicBlock *BB : LiveBlocks) { + llvm::errs() << ' ' << BB->getDebugID(); + } + llvm::errs() << '\n'; +} From 22500e7e6b3a7735da338f67e58f94a53db48ac3 Mon Sep 17 00:00:00 2001 From: Andrew Trick Date: Tue, 1 Oct 2019 13:25:01 -0700 Subject: [PATCH 2/4] Update the coding style for all code moved in the previous commit. Requested by gottesmm during review. Update the variable naming conventions to lower-camel. Run clang-format. I'm sure I missed some local variables somewhere--this was a best effort. --- include/swift/SIL/OptimizationRemark.h | 6 +- .../SILOptimizer/Utils/BasicBlockOptUtils.h | 100 +- .../swift/SILOptimizer/Utils/CFGOptUtils.h | 94 +- .../swift/SILOptimizer/Utils/InstOptUtils.h | 180 +-- .../swift/SILOptimizer/Utils/ValueLifetime.h | 46 +- .../LoopTransforms/LoopRotate.cpp | 451 +++---- lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp | 145 +-- lib/SILOptimizer/Utils/CFGOptUtils.cpp | 727 +++++------ lib/SILOptimizer/Utils/Devirtualize.cpp | 898 +++++++------ lib/SILOptimizer/Utils/InstOptUtils.cpp | 1109 +++++++++-------- lib/SILOptimizer/Utils/ValueLifetime.cpp | 214 ++-- 11 files changed, 1997 insertions(+), 1973 deletions(-) diff --git a/include/swift/SIL/OptimizationRemark.h b/include/swift/SIL/OptimizationRemark.h index f5c74888dcc..5accdbc2e76 100644 --- a/include/swift/SIL/OptimizationRemark.h +++ b/include/swift/SIL/OptimizationRemark.h @@ -157,9 +157,9 @@ public: using RemarkT = decltype(RemarkBuilder()); // Avoid building the remark unless remarks are enabled. if (isEnabled() || Module.getOptRecordStream()) { - auto R = RemarkBuilder(); - R.setPassName(PassName); - emit(R); + auto rb = RemarkBuilder(); + rb.setPassName(PassName); + emit(rb); } } diff --git a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h index 8b6e07bcc42..2d0bb0e4578 100644 --- a/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h +++ b/include/swift/SILOptimizer/Utils/BasicBlockOptUtils.h @@ -32,21 +32,21 @@ class BasicBlockCloner; class SILLoop; class SILLoopInfo; -/// Remove all instructions in the body of \p BB in safe manner by using +/// Remove all instructions in the body of \p bb in safe manner by using /// undef. -void clearBlockBody(SILBasicBlock *BB); +void clearBlockBody(SILBasicBlock *bb); /// Handle the mechanical aspects of removing an unreachable block. -void removeDeadBlock(SILBasicBlock *BB); +void removeDeadBlock(SILBasicBlock *bb); /// Remove all unreachable blocks in a function. -bool removeUnreachableBlocks(SILFunction &Fn); +bool removeUnreachableBlocks(SILFunction &f); -/// Return true if there are any users of V outside the specified block. -inline bool isUsedOutsideOfBlock(SILValue V) { - auto *BB = V->getParentBlock(); - for (auto UI : V->getUses()) - if (UI->getUser()->getParent() != BB) +/// Return true if there are any users of v outside the specified block. +inline bool isUsedOutsideOfBlock(SILValue v) { + auto *bb = v->getParentBlock(); + for (auto *use : v->getUses()) + if (use->getUser()->getParent() != bb) return true; return false; } @@ -57,13 +57,13 @@ inline bool isUsedOutsideOfBlock(SILValue V) { /// rotated once. ShouldVerify specifies whether to perform verification after /// the transformation. /// Returns true if the loop could be rotated. -bool rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, - bool RotateSingleBlockLoops, SILBasicBlock *UpTo, - bool ShouldVerify); +bool rotateLoop(SILLoop *loop, DominanceInfo *domInfo, SILLoopInfo *loopInfo, + bool rotateSingleBlockLoops, SILBasicBlock *upToBB, + bool shouldVerify); /// Helper function to perform SSA updates in case of jump threading. -void updateSSAAfterCloning(BasicBlockCloner &Cloner, SILBasicBlock *SrcBB, - SILBasicBlock *DestBB); +void updateSSAAfterCloning(BasicBlockCloner &cloner, SILBasicBlock *srcBB, + SILBasicBlock *destBB); /// Clone a single basic block and any required successor edges within the same /// function. @@ -95,14 +95,14 @@ public: /// Clone the given branch instruction's destination block, splitting /// its successors, and rewrite the branch instruction. - void cloneBranchTarget(BranchInst *BI) { - assert(origBB == BI->getDestBB()); + void cloneBranchTarget(BranchInst *bi) { + assert(origBB == bi->getDestBB()); - cloneBlock(/*insertAfter*/BI->getParent()); + cloneBlock(/*insertAfter*/ bi->getParent()); - SILBuilderWithScope(BI).createBranch(BI->getLoc(), getNewBB(), - BI->getArgs()); - BI->eraseFromParent(); + SILBuilderWithScope(bi).createBranch(bi->getLoc(), getNewBB(), + bi->getArgs()); + bi->eraseFromParent(); } /// Get the newly cloned block corresponding to `origBB`. @@ -112,27 +112,27 @@ public: /// Call this after processing all instructions to fix the control flow /// graph. The branch cloner may have left critical edges. - bool splitCriticalEdges(DominanceInfo *DT, SILLoopInfo *LI); + bool splitCriticalEdges(DominanceInfo *domInfo, SILLoopInfo *loopInfo); protected: // MARK: CRTP overrides. /// Override getMappedValue to allow values defined outside the block to be /// cloned to be reused in the newly cloned block. - SILValue getMappedValue(SILValue Value) { - if (auto SI = Value->getDefiningInstruction()) { - if (!isBlockCloned(SI->getParent())) - return Value; - } else if (auto BBArg = dyn_cast(Value)) { - if (!isBlockCloned(BBArg->getParent())) - return Value; + SILValue getMappedValue(SILValue value) { + if (auto si = value->getDefiningInstruction()) { + if (!isBlockCloned(si->getParent())) + return value; + } else if (auto bbArg = dyn_cast(value)) { + if (!isBlockCloned(bbArg->getParent())) + return value; } else { - assert(isa(Value) && "Unexpected Value kind"); - return Value; + assert(isa(value) && "Unexpected Value kind"); + return value; } // `value` is not defined outside the cloned block, so consult the cloner's // map of cloned values. - return SuperTy::getMappedValue(Value); + return SuperTy::getMappedValue(value); } void mapValue(SILValue origValue, SILValue mappedValue) { @@ -150,18 +150,18 @@ public: typedef std::function FilterType; private: - FilterType Filter; + FilterType filter; // Pairs of collected instructions; (new, old) - llvm::SmallVector InstructionPairs; + llvm::SmallVector instructionpairs; - void collect(SILInstruction *Old, SILInstruction *New) { - if (Filter(New)) - InstructionPairs.push_back(std::make_pair(New, Old)); + void collect(SILInstruction *oldI, SILInstruction *newI) { + if (filter(newI)) + instructionpairs.push_back(std::make_pair(newI, oldI)); } public: - CloneCollector(FilterType Filter) : Filter(Filter) {} + CloneCollector(FilterType filter) : filter(filter) {} CallbackType getCallback() { return std::bind(&CloneCollector::collect, this, std::placeholders::_1, @@ -169,7 +169,7 @@ public: } llvm::SmallVectorImpl &getInstructionPairs() { - return InstructionPairs; + return instructionpairs; } }; @@ -220,37 +220,37 @@ class StaticInitCloner : public SILCloner { friend class SILCloner; /// The number of not yet cloned operands for each instruction. - llvm::DenseMap NumOpsToClone; + llvm::DenseMap numOpsToClone; /// List of instructions for which all operands are already cloned (or which /// don't have any operands). - llvm::SmallVector ReadyToClone; + llvm::SmallVector readyToClone; public: - StaticInitCloner(SILGlobalVariable *GVar) - : SILCloner(GVar) { } + StaticInitCloner(SILGlobalVariable *gVar) + : SILCloner(gVar) {} /// Add \p InitVal and all its operands (transitively) for cloning. /// /// Note: all init values must are added, before calling clone(). - void add(SILInstruction *InitVal); + void add(SILInstruction *initVal); /// Clone \p InitVal and all its operands into the initializer of the /// SILGlobalVariable. /// /// \return Returns the cloned instruction in the SILGlobalVariable. - SingleValueInstruction *clone(SingleValueInstruction *InitVal); + SingleValueInstruction *clone(SingleValueInstruction *initVal); /// Convenience function to clone a single \p InitVal. - static void appendToInitializer(SILGlobalVariable *GVar, - SingleValueInstruction *InitVal) { - StaticInitCloner Cloner(GVar); - Cloner.add(InitVal); - Cloner.clone(InitVal); + static void appendToInitializer(SILGlobalVariable *gVar, + SingleValueInstruction *initVal) { + StaticInitCloner cloner(gVar); + cloner.add(initVal); + cloner.clone(initVal); } protected: - SILLocation remapLocation(SILLocation Loc) { + SILLocation remapLocation(SILLocation loc) { return ArtificialUnreachableLocation(); } }; diff --git a/include/swift/SILOptimizer/Utils/CFGOptUtils.h b/include/swift/SILOptimizer/Utils/CFGOptUtils.h index d67ba9267a7..9c3f8189ff7 100644 --- a/include/swift/SILOptimizer/Utils/CFGOptUtils.h +++ b/include/swift/SILOptimizer/Utils/CFGOptUtils.h @@ -39,25 +39,25 @@ class SILLoopInfo; /// Adds a new argument to an edge between a branch and a destination /// block. /// -/// \param Branch The terminator to add the argument to. -/// \param Dest The destination block of the edge. -/// \param Val The value to the arguments of the branch. +/// \param branch The terminator to add the argument to. +/// \param dest The destination block of the edge. +/// \param val The value to the arguments of the branch. /// \return The created branch. The old branch is deleted. /// The argument is appended at the end of the argument tuple. -TermInst *addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest, - SILValue Val); +TermInst *addNewEdgeValueToBranch(TermInst *branch, SILBasicBlock *dest, + SILValue val); /// Changes the edge value between a branch and destination basic block /// at the specified index. Changes all edges from \p Branch to \p Dest to carry /// the value. /// -/// \param Branch The branch to modify. -/// \param Dest The destination of the edge. -/// \param Idx The index of the argument to modify. -/// \param Val The new value to use. +/// \param branch The branch to modify. +/// \param dest The destination of the edge. +/// \param idx The index of the argument to modify. +/// \param val The new value to use. /// \return The new branch. Deletes the old one. -TermInst *changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, size_t Idx, - SILValue Val); +TermInst *changeEdgeValue(TermInst *branch, SILBasicBlock *dest, size_t idx, + SILValue val); /// Deletes the edge value between a branch and a destination basic block at the /// specified index. Asserts internally that the argument along the edge does @@ -73,24 +73,24 @@ void erasePhiArgument(SILBasicBlock *block, unsigned argIndex); /// Replace a branch target. /// -/// \param T The terminating instruction to modify. -/// \param OldDest The successor block that will be replaced. -/// \param NewDest The new target block. -/// \param PreserveArgs If set, preserve arguments on the replaced edge. -void replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, - SILBasicBlock *NewDest, bool PreserveArgs); +/// \param t The terminating instruction to modify. +/// \param oldDest The successor block that will be replaced. +/// \param newDest The new target block. +/// \param preserveArgs If set, preserve arguments on the replaced edge. +void replaceBranchTarget(TermInst *t, SILBasicBlock *oldDest, + SILBasicBlock *newDest, bool preserveArgs); /// Check if the edge from the terminator is critical. -bool isCriticalEdge(TermInst *T, unsigned EdgeIdx); +bool isCriticalEdge(TermInst *t, unsigned edgeIdx); /// Splits the edge from terminator if it is critical. /// /// Updates dominance information and loop information if not null. /// Returns the newly created basic block on success or nullptr otherwise (if /// the edge was not critical). -SILBasicBlock *splitCriticalEdge(TermInst *T, unsigned EdgeIdx, - DominanceInfo *DT = nullptr, - SILLoopInfo *LI = nullptr); +SILBasicBlock *splitCriticalEdge(TermInst *, unsigned edgeIdx, + DominanceInfo *domInfo = nullptr, + SILLoopInfo *loopInfo = nullptr); /// Splits the critical edges between from and to. This code assumes there is /// exactly one edge between the two basic blocks. It will return the wrong @@ -98,35 +98,39 @@ SILBasicBlock *splitCriticalEdge(TermInst *T, unsigned EdgeIdx, /// between the two blocks. /// /// Updates dominance information and loop information if not null. -SILBasicBlock *splitIfCriticalEdge(SILBasicBlock *From, SILBasicBlock *To, - DominanceInfo *DT = nullptr, - SILLoopInfo *LI = nullptr); +SILBasicBlock *splitIfCriticalEdge(SILBasicBlock *from, SILBasicBlock *to, + DominanceInfo *domInfo = nullptr, + SILLoopInfo *loopInfo = nullptr); /// Splits all critical edges originating from `fromBB`. -bool splitCriticalEdgesFrom(SILBasicBlock *fromBB, DominanceInfo *DT = nullptr, - SILLoopInfo *LI = nullptr); +bool splitCriticalEdgesFrom(SILBasicBlock *fromBB, + DominanceInfo *domInfo = nullptr, + SILLoopInfo *loopInfo = nullptr); /// Splits the edges between two basic blocks. /// /// Updates dominance information and loop information if not null. -void splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To, - DominanceInfo *DT = nullptr, SILLoopInfo *LI = nullptr); +void splitEdgesFromTo(SILBasicBlock *from, SILBasicBlock *to, + DominanceInfo *domInfo = nullptr, + SILLoopInfo *loopInfo = nullptr); /// Splits the basic block before the instruction with an unconditional branch /// and updates the dominator tree and loop info. Returns the new, branched to /// block that contains the end of \p SplitBeforeInst's block. -SILBasicBlock *splitBasicBlockAndBranch(SILBuilder &B, - SILInstruction *SplitBeforeInst, - DominanceInfo *DT, SILLoopInfo *LI); +SILBasicBlock *splitBasicBlockAndBranch(SILBuilder &builder, + SILInstruction *splitBeforeInst, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo); /// Return true if the function has a critical edge, false otherwise. -bool hasCriticalEdges(SILFunction &F, bool OnlyNonCondBr); +bool hasCriticalEdges(SILFunction &f, bool onlyNonCondBr); /// Split all critical edges in the given function, updating the /// dominator tree and loop information if they are provided. /// /// FIXME: This should never be called! Fix passes that create critical edges. -bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *DT, SILLoopInfo *LI); +bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *domInfo, + SILLoopInfo *loopInfo); /// Split all cond_br critical edges with non-trivial arguments in the /// function updating the dominator tree and loop information (if they are not @@ -134,15 +138,15 @@ bool splitAllCriticalEdges(SILFunction &F, DominanceInfo *DT, SILLoopInfo *LI); /// /// A current invariant of Ownership SIL is that cond_br can only have critical /// edges with non-trivial arguments. This simplifies computation. -bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn, - DominanceInfo *DT, - SILLoopInfo *LI); +bool splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &fn, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo); /// Merge a basic block ending in a branch with its successor /// if possible. If dominance information or loop info is non null update it. /// Return true if block was merged. -bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT, - SILLoopInfo *LI); +bool mergeBasicBlockWithSuccessor(SILBasicBlock *bb, DominanceInfo *domInfo, + SILLoopInfo *loopInfo); /// Merge basic blocks in the given function by eliminating all unconditional /// branches to single-predecessor branch targets. @@ -152,7 +156,7 @@ bool mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT, /// is not done on-the-fly after splitting blocks because merging is linear in /// the number of instructions, so interleaved merging and splitting is /// quadratic. -bool mergeBasicBlocks(SILFunction *F); +bool mergeBasicBlocks(SILFunction *f); /// Given a list of \p UserBlocks and a list of \p DefBlocks, find a set of /// blocks that together with \p UserBlocks joint-postdominate \p @@ -181,11 +185,11 @@ bool mergeBasicBlocks(SILFunction *F); /// /// *NOTE* This completion may not be unique. void completeJointPostDominanceSet( - ArrayRef UserBlocks, ArrayRef DefBlocks, - llvm::SmallVectorImpl &Completion); + ArrayRef userBlocks, ArrayRef defBlocks, + llvm::SmallVectorImpl &completion); -/// Return true if we conservatively find all BB's that are non-failure exit -/// basic blocks and place them in \p BBs. If we find something we don't +/// Return true if we conservatively find all bb's that are non-failure exit +/// basic blocks and place them in \p bbs. If we find something we don't /// understand, bail. /// /// A non-failure exit BB is defined as a BB that: @@ -202,8 +206,8 @@ void completeJointPostDominanceSet( /// implying in most cases this will be one element. /// /// TODO: -bool findAllNonFailureExitBBs(SILFunction *F, - llvm::TinyPtrVector &BBs); +bool findAllNonFailureExitBBs(SILFunction *f, + llvm::TinyPtrVector &bbs); } // end namespace swift diff --git a/include/swift/SILOptimizer/Utils/InstOptUtils.h b/include/swift/SILOptimizer/Utils/InstOptUtils.h index de2521a9a9a..15c5f82089d 100644 --- a/include/swift/SILOptimizer/Utils/InstOptUtils.h +++ b/include/swift/SILOptimizer/Utils/InstOptUtils.h @@ -41,52 +41,54 @@ using ValueBaseUserRange = TransformRange, UserTransform>; inline ValueBaseUserRange -makeUserRange(iterator_range R) { - auto toUser = [](Operand *O) { return O->getUser(); }; - return makeTransformRange(makeIteratorRange(R.begin(), R.end()), +makeUserRange(iterator_range range) { + auto toUser = [](Operand *operand) { return operand->getUser(); }; + return makeTransformRange(makeIteratorRange(range.begin(), range.end()), UserTransform(toUser)); } using DeadInstructionSet = llvm::SmallSetVector; /// Create a retain of \p Ptr before the \p InsertPt. -NullablePtr createIncrementBefore(SILValue Ptr, - SILInstruction *InsertPt); +NullablePtr createIncrementBefore(SILValue ptr, + SILInstruction *insertpt); /// Create a release of \p Ptr before the \p InsertPt. -NullablePtr createDecrementBefore(SILValue Ptr, - SILInstruction *InsertPt); +NullablePtr createDecrementBefore(SILValue ptr, + SILInstruction *insertpt); /// For each of the given instructions, if they are dead delete them /// along with their dead operands. /// -/// \param I The ArrayRef of instructions to be deleted. -/// \param Force If Force is set, don't check if the top level instructions +/// \param inst The ArrayRef of instructions to be deleted. +/// \param force If Force is set, don't check if the top level instructions /// are considered dead - delete them regardless. -/// \param C a callback called whenever an instruction is deleted. +/// \param callback a callback called whenever an instruction is deleted. void recursivelyDeleteTriviallyDeadInstructions( - ArrayRef I, bool Force = false, - llvm::function_ref C = [](SILInstruction *) {}); + ArrayRef inst, bool force = false, + llvm::function_ref callback = [](SILInstruction *) { + }); /// If the given instruction is dead, delete it along with its dead /// operands. /// -/// \param I The instruction to be deleted. -/// \param Force If Force is set, don't check if the top level instruction is +/// \param inst The instruction to be deleted. +/// \param force If Force is set, don't check if the top level instruction is /// considered dead - delete it regardless. -/// \param C a callback called whenever an instruction is deleted. +/// \param callback a callback called whenever an instruction is deleted. void recursivelyDeleteTriviallyDeadInstructions( - SILInstruction *I, bool Force = false, - llvm::function_ref C = [](SILInstruction *) {}); + SILInstruction *inst, bool force = false, + llvm::function_ref callback = [](SILInstruction *) { + }); /// Perform a fast local check to see if the instruction is dead. /// /// This routine only examines the state of the instruction at hand. -bool isInstructionTriviallyDead(SILInstruction *I); +bool isInstructionTriviallyDead(SILInstruction *inst); /// Return true if this is a release instruction that's not going to /// free the object. -bool isIntermediateRelease(SILInstruction *I, EpilogueARCFunctionInfo *ERFI); +bool isIntermediateRelease(SILInstruction *inst, EpilogueARCFunctionInfo *erfi); /// Recursively collect all the uses and transitive uses of the /// instruction. @@ -96,12 +98,12 @@ void collectUsesOfValue(SILValue V, /// Recursively erase all of the uses of the instruction (but not the /// instruction itself) void eraseUsesOfInstruction( - SILInstruction *Inst, - llvm::function_ref C = [](SILInstruction *) {}); + SILInstruction *inst, llvm::function_ref callback = + [](SILInstruction *) {}); /// Recursively erase all of the uses of the value (but not the /// value itself) -void eraseUsesOfValue(SILValue V); +void eraseUsesOfValue(SILValue value); FullApplySite findApplyFromDevirtualizedResult(SILValue value); @@ -110,61 +112,62 @@ FullApplySite findApplyFromDevirtualizedResult(SILValue value); /// - a type of the return value is a subclass of the expected return type. /// - actual return type and expected return type differ in optionality. /// - both types are tuple-types and some of the elements need to be casted. -SILValue castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, - SILValue Value, SILType SrcTy, - SILType DestTy); +SILValue castValueToABICompatibleType(SILBuilder *builder, SILLocation Loc, + SILValue value, SILType srcTy, + SILType destTy); /// Peek through trivial Enum initialization, typically for pointless /// Optionals. /// /// The returned InitEnumDataAddr dominates the given /// UncheckedTakeEnumDataAddrInst. InitEnumDataAddrInst * -findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *UTEDAI); +findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai); /// Returns a project_box if it is the next instruction after \p ABI and /// and has \p ABI as operand. Otherwise it creates a new project_box right /// after \p ABI and returns it. -ProjectBoxInst *getOrCreateProjectBox(AllocBoxInst *ABI, unsigned Index); +ProjectBoxInst *getOrCreateProjectBox(AllocBoxInst *abi, unsigned index); /// Return true if any call inside the given function may bind dynamic /// 'Self' to a generic argument of the callee. -bool mayBindDynamicSelf(SILFunction *F); +bool mayBindDynamicSelf(SILFunction *f); /// Check whether the \p addr is an address of a tail-allocated array element. bool isAddressOfArrayElement(SILValue addr); /// Move an ApplyInst's FuncRef so that it dominates the call site. -void placeFuncRef(ApplyInst *AI, DominanceInfo *DT); +void placeFuncRef(ApplyInst *ai, DominanceInfo *dt); /// Add an argument, \p val, to the branch-edge that is pointing into /// block \p Dest. Return a new instruction and do not erase the old /// instruction. -TermInst *addArgumentToBranch(SILValue Val, SILBasicBlock *Dest, - TermInst *Branch); +TermInst *addArgumentToBranch(SILValue val, SILBasicBlock *dest, + TermInst *branch); /// Get the linkage to be used for specializations of a function with /// the given linkage. -SILLinkage getSpecializedLinkage(SILFunction *F, SILLinkage L); +SILLinkage getSpecializedLinkage(SILFunction *f, SILLinkage linkage); /// Tries to optimize a given apply instruction if it is a concatenation of /// string literals. Returns a new instruction if optimization was possible. -SingleValueInstruction *tryToConcatenateStrings(ApplyInst *AI, SILBuilder &B); +SingleValueInstruction *tryToConcatenateStrings(ApplyInst *ai, + SILBuilder &builder); /// Tries to perform jump-threading on all checked_cast_br instruction in /// function \p Fn. bool tryCheckedCastBrJumpThreading( - SILFunction *Fn, DominanceInfo *DT, - SmallVectorImpl &BlocksForWorklist); + SILFunction *fn, DominanceInfo *dt, + SmallVectorImpl &blocksForWorklist); /// A structure containing callbacks that are called when an instruction is /// removed or added. struct InstModCallbacks { using CallbackTy = std::function; - CallbackTy DeleteInst = [](SILInstruction *I) { I->eraseFromParent(); }; - CallbackTy CreatedNewInst = [](SILInstruction *) {}; + CallbackTy deleteInst = [](SILInstruction *inst) { inst->eraseFromParent(); }; + CallbackTy createdNewInst = [](SILInstruction *) {}; - InstModCallbacks(CallbackTy DeleteInst, CallbackTy CreatedNewInst) - : DeleteInst(DeleteInst), CreatedNewInst(CreatedNewInst) {} + InstModCallbacks(CallbackTy deleteInst, CallbackTy createdNewInst) + : deleteInst(deleteInst), createdNewInst(createdNewInst) {} InstModCallbacks() = default; ~InstModCallbacks() = default; InstModCallbacks(const InstModCallbacks &) = default; @@ -179,19 +182,20 @@ struct InstModCallbacks { /// captured args if we have a partial_apply. /// /// In the future this should be extended to be less conservative with users. -bool tryDeleteDeadClosure(SingleValueInstruction *Closure, - InstModCallbacks Callbacks = InstModCallbacks()); +bool tryDeleteDeadClosure(SingleValueInstruction *closure, + InstModCallbacks callbacks = InstModCallbacks()); /// Given a SILValue argument to a partial apply \p Arg and the associated /// parameter info for that argument, perform the necessary cleanups to Arg when /// one is attempting to delete the partial apply. void releasePartialApplyCapturedArg( - SILBuilder &Builder, SILLocation Loc, SILValue Arg, SILParameterInfo PInfo, - InstModCallbacks Callbacks = InstModCallbacks()); + SILBuilder &builder, SILLocation loc, SILValue arg, + SILParameterInfo paramInfo, + InstModCallbacks callbacks = InstModCallbacks()); /// Insert destroys of captured arguments of partial_apply [stack]. void insertDestroyOfCapturedArguments( - PartialApplyInst *PAI, SILBuilder &B, + PartialApplyInst *pai, SILBuilder &builder, llvm::function_ref shouldInsertDestroy = [](SILValue arg) -> bool { return true; }); @@ -201,57 +205,57 @@ void insertDestroyOfCapturedArguments( /// interposed. class IgnoreExpectUseIterator : public std::iterator { - ValueBaseUseIterator OrigUseChain; - ValueBaseUseIterator CurrentIter; + ValueBaseUseIterator origUseChain; + ValueBaseUseIterator currentIter; - static BuiltinInst *isExpect(Operand *Use) { - if (auto *BI = dyn_cast(Use->getUser())) - if (BI->getIntrinsicInfo().ID == llvm::Intrinsic::expect) - return BI; + static BuiltinInst *isExpect(Operand *use) { + if (auto *bi = dyn_cast(use->getUser())) + if (bi->getIntrinsicInfo().ID == llvm::Intrinsic::expect) + return bi; return nullptr; } // Advance through expect users to their users until we encounter a user that // is not an expect. void advanceThroughExpects() { - while (CurrentIter == OrigUseChain - && CurrentIter != ValueBaseUseIterator(nullptr)) { - auto *Expect = isExpect(*CurrentIter); + while (currentIter == origUseChain + && currentIter != ValueBaseUseIterator(nullptr)) { + auto *Expect = isExpect(*currentIter); if (!Expect) return; - CurrentIter = Expect->use_begin(); + currentIter = Expect->use_begin(); // Expect with no users advance to next item in original use chain. - if (CurrentIter == Expect->use_end()) - CurrentIter = ++OrigUseChain; + if (currentIter == Expect->use_end()) + currentIter = ++origUseChain; } } public: - IgnoreExpectUseIterator(ValueBase *V) - : OrigUseChain(V->use_begin()), CurrentIter(V->use_begin()) { + IgnoreExpectUseIterator(ValueBase *value) + : origUseChain(value->use_begin()), currentIter(value->use_begin()) { advanceThroughExpects(); } IgnoreExpectUseIterator() = default; - Operand *operator*() const { return *CurrentIter; } - Operand *operator->() const { return *CurrentIter; } - SILInstruction *getUser() const { return CurrentIter->getUser(); } + Operand *operator*() const { return *currentIter; } + Operand *operator->() const { return *currentIter; } + SILInstruction *getUser() const { return currentIter->getUser(); } IgnoreExpectUseIterator &operator++() { assert(**this && "increment past end()!"); - if (OrigUseChain == CurrentIter) { + if (origUseChain == currentIter) { // Use chain of the original value. - ++OrigUseChain; - ++CurrentIter; + ++origUseChain; + ++currentIter; // Ignore expects. advanceThroughExpects(); } else { // Use chain of an expect. - ++CurrentIter; - if (CurrentIter == ValueBaseUseIterator(nullptr)) { + ++currentIter; + if (currentIter == ValueBaseUseIterator(nullptr)) { // At the end of the use chain of an expect. - CurrentIter = ++OrigUseChain; + currentIter = ++origUseChain; advanceThroughExpects(); } } @@ -259,13 +263,13 @@ public: } IgnoreExpectUseIterator operator++(int unused) { - IgnoreExpectUseIterator Copy = *this; + IgnoreExpectUseIterator copy = *this; ++*this; - return Copy; + return copy; } friend bool operator==(IgnoreExpectUseIterator lhs, IgnoreExpectUseIterator rhs) { - return lhs.CurrentIter == rhs.CurrentIter; + return lhs.currentIter == rhs.currentIter; } friend bool operator!=(IgnoreExpectUseIterator lhs, IgnoreExpectUseIterator rhs) { @@ -274,8 +278,8 @@ public: }; inline iterator_range -ignore_expect_uses(ValueBase *V) { - return make_range(IgnoreExpectUseIterator(V), IgnoreExpectUseIterator()); +ignore_expect_uses(ValueBase *value) { + return make_range(IgnoreExpectUseIterator(value), IgnoreExpectUseIterator()); } /// Run simplifyInstruction() on all of the instruction I's users if they only @@ -286,53 +290,53 @@ ignore_expect_uses(ValueBase *V) { /// An example of how this is useful is in cases where one is splitting up an /// aggregate and reforming it, the reformed aggregate may have extract /// operations from it. These can be simplified and removed. -bool simplifyUsers(SingleValueInstruction *I); +bool simplifyUsers(SingleValueInstruction *inst); /// True if a type can be expanded /// without a significant increase to code size. -bool shouldExpand(SILModule &Module, SILType Ty); +bool shouldExpand(SILModule &module, SILType ty); -/// Check if the value of V is computed by means of a simple initialization. +/// Check if the value of value is computed by means of a simple initialization. /// Store the actual SILValue into \p Val and the reversed list of instructions /// initializing it in \p Insns. /// The check is performed by recursively walking the computation of the /// SIL value being analyzed. -bool analyzeStaticInitializer(SILValue V, - SmallVectorImpl &Insns); +bool analyzeStaticInitializer(SILValue value, + SmallVectorImpl &insns); /// Returns true if the below operation will succeed. -bool canReplaceLoadSequence(SILInstruction *I); +bool canReplaceLoadSequence(SILInstruction *inst); /// Replace load sequence which may contain /// a chain of struct_element_addr followed by a load. /// The sequence is traversed inside out, i.e. /// starting with the innermost struct_element_addr -void replaceLoadSequence(SILInstruction *I, SILValue Value); +void replaceLoadSequence(SILInstruction *inst, SILValue value); /// Do we have enough information to determine all callees that could /// be reached by calling the function represented by Decl? -bool calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl); +bool calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl); -// Attempt to get the instance for S, whose static type is the same as +// Attempt to get the instance for , whose static type is the same as // its exact dynamic type, returning a null SILValue() if we cannot find it. // The information that a static type is the same as the exact dynamic, // can be derived e.g.: // - from a constructor or // - from a successful outcome of a checked_cast_br [exact] instruction. -SILValue getInstanceWithExactDynamicType(SILValue S, - ClassHierarchyAnalysis *CHA); +SILValue getInstanceWithExactDynamicType(SILValue instance, + ClassHierarchyAnalysis *cha); /// Try to determine the exact dynamic type of an object. /// returns the exact dynamic type of the object, or an empty type if the exact /// type could not be determined. -SILType getExactDynamicType(SILValue S, ClassHierarchyAnalysis *CHA, - bool ForUnderlyingObject = false); +SILType getExactDynamicType(SILValue instance, ClassHierarchyAnalysis *cha, + bool forUnderlyingObject = false); /// Try to statically determine the exact dynamic type of the underlying object. /// returns the exact dynamic type of the underlying object, or an empty SILType /// if the exact type could not be determined. -SILType getExactDynamicTypeOfUnderlyingObject(SILValue S, - ClassHierarchyAnalysis *CHA); +SILType getExactDynamicTypeOfUnderlyingObject(SILValue instance, + ClassHierarchyAnalysis *cha); // Move only data structure that is the result of findLocalApplySite. /// @@ -379,7 +383,7 @@ struct LLVM_LIBRARY_VISIBILITY FindLocalApplySitesResult { /// 1. We discovered that the function_ref never escapes. /// 2. We were able to find either a partial apply or a full apply site. Optional -findLocalApplySites(FunctionRefBaseInst *FRI); +findLocalApplySites(FunctionRefBaseInst *fri); } // end namespace swift diff --git a/include/swift/SILOptimizer/Utils/ValueLifetime.h b/include/swift/SILOptimizer/Utils/ValueLifetime.h index b0215ce7d82..85be58077e6 100644 --- a/include/swift/SILOptimizer/Utils/ValueLifetime.h +++ b/include/swift/SILOptimizer/Utils/ValueLifetime.h @@ -39,16 +39,17 @@ public: /// Constructor for the value \p Def with a specific set of users of Def's /// users. - ValueLifetimeAnalysis(SILInstruction *Def, ArrayRef UserList) : - DefValue(Def), UserSet(UserList.begin(), UserList.end()) { + ValueLifetimeAnalysis(SILInstruction *def, + ArrayRef userList) + : defValue(def), userSet(userList.begin(), userList.end()) { propagateLiveness(); } - /// Constructor for the value \p Def considering all the value's uses. - ValueLifetimeAnalysis(SILInstruction *Def) : DefValue(Def) { - for (auto result : Def->getResults()) { + /// Constructor for the value \p def considering all the value's uses. + ValueLifetimeAnalysis(SILInstruction *def) : defValue(def) { + for (auto result : def->getResults()) { for (Operand *op : result->getUses()) { - UserSet.insert(op->getUser()); + userSet.insert(op->getUser()); } } propagateLiveness(); @@ -69,31 +70,32 @@ public: UsersMustPostDomDef }; - /// Computes and returns the lifetime frontier for the value in \p Fr. + /// Computes and returns the lifetime frontier for the value in \p frontier. /// /// Returns true if all instructions in the frontier could be found in /// non-critical edges. /// Returns false if some frontier instructions are located on critical edges. /// In this case, if \p mode is AllowToModifyCFG, those critical edges are - /// split, otherwise nothing is done and the returned \p Fr is not valid. + /// split, otherwise nothing is done and the returned \p frontier is not + /// valid. /// - /// If \p deadEndBlocks is provided, all dead-end blocks are ignored. This + /// If \p deBlocks is provided, all dead-end blocks are ignored. This /// prevents unreachable-blocks to be included in the frontier. - bool computeFrontier(Frontier &Fr, Mode mode, - DeadEndBlocks *DEBlocks = nullptr); + bool computeFrontier(Frontier &frontier, Mode mode, + DeadEndBlocks *deBlocks = nullptr); /// Returns true if the instruction \p Inst is located within the value's /// lifetime. - /// It is assumed that \p Inst is located after the value's definition. - bool isWithinLifetime(SILInstruction *Inst); + /// It is assumed that \p inst is located after the value's definition. + bool isWithinLifetime(SILInstruction *inst); - /// Returns true if the value is alive at the begin of block \p BB. - bool isAliveAtBeginOfBlock(SILBasicBlock *BB) { - return LiveBlocks.count(BB) && BB != DefValue->getParent(); + /// Returns true if the value is alive at the begin of block \p bb. + bool isAliveAtBeginOfBlock(SILBasicBlock *bb) { + return liveBlocks.count(bb) && bb != defValue->getParent(); } /// Checks if there is a dealloc_ref inside the value's live range. - bool containsDeallocRef(const Frontier &Frontier); + bool containsDeallocRef(const Frontier &frontier); /// For debug dumping. void dump() const; @@ -101,20 +103,20 @@ public: private: /// The value. - SILInstruction *DefValue; + SILInstruction *defValue; /// The set of blocks where the value is live. - llvm::SmallSetVector LiveBlocks; + llvm::SmallSetVector liveBlocks; /// The set of instructions where the value is used, or the users-list /// provided with the constructor. - llvm::SmallPtrSet UserSet; + llvm::SmallPtrSet userSet; /// Propagates the liveness information up the control flow graph. void propagateLiveness(); - /// Returns the last use of the value in the live block \p BB. - SILInstruction *findLastUserInBlock(SILBasicBlock *BB); + /// Returns the last use of the value in the live block \p bb. + SILInstruction *findLastUserInBlock(SILBasicBlock *bb); }; diff --git a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp index abc97756f24..31500702043 100644 --- a/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp +++ b/lib/SILOptimizer/LoopTransforms/LoopRotate.cpp @@ -35,18 +35,18 @@ static llvm::cl::opt ShouldRotate("sil-looprotate", llvm::cl::init(true)); /// Check whether all operands are loop invariant. -static bool hasLoopInvariantOperands(SILInstruction *I, SILLoop *L, - llvm::DenseSet &Inv) { - auto Opds = I->getAllOperands(); +static bool +hasLoopInvariantOperands(SILInstruction *inst, SILLoop *loop, + llvm::DenseSet &invariant) { + auto operands = inst->getAllOperands(); - return std::all_of(Opds.begin(), Opds.end(), [=](Operand &Op) { - - ValueBase *Def = Op.get(); + return llvm::all_of(operands, [=](Operand &operand) { + ValueBase *def = operand.get(); // Operand is outside the loop or marked invariant. - if (auto *Inst = Def->getDefiningInstruction()) - return !L->contains(Inst->getParent()) || Inv.count(Inst); - if (auto *Arg = dyn_cast(Def)) - return !L->contains(Arg->getParent()); + if (auto *inst = def->getDefiningInstruction()) + return !loop->contains(inst->getParent()) || invariant.count(inst); + if (auto *arg = dyn_cast(def)) + return !loop->contains(arg->getParent()); return false; }); @@ -55,76 +55,72 @@ static bool hasLoopInvariantOperands(SILInstruction *I, SILLoop *L, /// We cannot duplicate blocks with AllocStack instructions (they need to be /// FIFO). Other instructions can be moved to the preheader. static bool -canDuplicateOrMoveToPreheader(SILLoop *L, SILBasicBlock *Preheader, - SILBasicBlock *Blk, - SmallVectorImpl &Move) { - llvm::DenseSet Invariant; - for (auto &I : *Blk) { - auto *Inst = &I; - if (auto *MI = dyn_cast(Inst)) { +canDuplicateOrMoveToPreheader(SILLoop *loop, SILBasicBlock *preheader, + SILBasicBlock *bb, + SmallVectorImpl &moves) { + llvm::DenseSet invariants; + for (auto &instRef : *bb) { + auto *inst = &instRef; + if (auto *MI = dyn_cast(inst)) { if (MI->getMember().isForeign) return false; - if (!hasLoopInvariantOperands(Inst, L, Invariant)) + if (!hasLoopInvariantOperands(inst, loop, invariants)) continue; - Move.push_back(Inst); - Invariant.insert(Inst); - } else if (!I.isTriviallyDuplicatable()) + moves.push_back(inst); + invariants.insert(inst); + } else if (!inst->isTriviallyDuplicatable()) return false; - else if (isa(Inst)) { - Move.push_back(Inst); - Invariant.insert(Inst); - } else if (isa(Inst)) { - Move.push_back(Inst); - Invariant.insert(Inst); - } - else if (isa(Inst)) { - Move.push_back(Inst); - Invariant.insert(Inst); - } else if (isa(Inst)) { - Move.push_back(Inst); - Invariant.insert(Inst); - } else if (!Inst->mayHaveSideEffects() && - !Inst->mayReadFromMemory() && - !isa(Inst) && - !isa(Inst) && /* not marked mayhavesideffects */ - hasLoopInvariantOperands(Inst, L, Invariant)) { - Move.push_back(Inst); - Invariant.insert(Inst); + else if (isa(inst)) { + moves.push_back(inst); + invariants.insert(inst); + } else if (isa(inst)) { + moves.push_back(inst); + invariants.insert(inst); + } else if (isa(inst)) { + moves.push_back(inst); + invariants.insert(inst); + } else if (isa(inst)) { + moves.push_back(inst); + invariants.insert(inst); + } else if (!inst->mayHaveSideEffects() && !inst->mayReadFromMemory() + && !isa(inst) && !isa(inst) + && /* not marked mayhavesideffects */ + hasLoopInvariantOperands(inst, loop, invariants)) { + moves.push_back(inst); + invariants.insert(inst); } } return true; } -static void mapOperands(SILInstruction *I, - const llvm::DenseMap &ValueMap) { - for (auto &Opd : I->getAllOperands()) { - SILValue OrigVal = Opd.get(); - ValueBase *OrigDef = OrigVal; - auto Found = ValueMap.find(OrigDef); - if (Found != ValueMap.end()) { - SILValue MappedVal = Found->second; - Opd.set(MappedVal); +static void mapOperands(SILInstruction *inst, + const llvm::DenseMap &valueMap) { + for (auto &operand : inst->getAllOperands()) { + SILValue origVal = operand.get(); + ValueBase *origDef = origVal; + auto found = valueMap.find(origDef); + if (found != valueMap.end()) { + SILValue mappedVal = found->second; + operand.set(mappedVal); } } } static void updateSSAForUseOfValue( - SILSSAUpdater &Updater, SmallVectorImpl &InsertedPHIs, - const llvm::DenseMap &ValueMap, - SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, - SILValue Res) { + SILSSAUpdater &updater, SmallVectorImpl &insertedPhis, + const llvm::DenseMap &valueMap, + SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, SILValue Res) { // Find the mapped instruction. - assert(ValueMap.count(Res) && "Expected to find value in map!"); - SILValue MappedValue = ValueMap.find(Res)->second; + assert(valueMap.count(Res) && "Expected to find value in map!"); + SILValue MappedValue = valueMap.find(Res)->second; assert(MappedValue); assert(Res->getType() == MappedValue->getType() && "The types must match"); - InsertedPHIs.clear(); - Updater.Initialize(Res->getType()); - Updater.AddAvailableValue(Header, Res); - Updater.AddAvailableValue(EntryCheckBlock, MappedValue); - + insertedPhis.clear(); + updater.Initialize(Res->getType()); + updater.AddAvailableValue(Header, Res); + updater.AddAvailableValue(EntryCheckBlock, MappedValue); // Because of the way that phi nodes are represented we have to collect all // uses before we update SSA. Modifying one phi node can invalidate another @@ -132,26 +128,26 @@ static void updateSSAForUseOfValue( // has to be modified). This would invalidate a plain ValueUseIterator. // Instead we collect uses wrapping uses in branches specially so that we // can reconstruct the use even after the branch has been modified. - SmallVector StoredUses; - for (auto *U : Res->getUses()) - StoredUses.push_back(UseWrapper(U)); - for (auto U : StoredUses) { - Operand *Use = U; - SILInstruction *User = Use->getUser(); - assert(User && "Missing user"); + SmallVector storedUses; + for (auto *use : Res->getUses()) + storedUses.push_back(UseWrapper(use)); + for (auto useWrapper : storedUses) { + Operand *use = useWrapper; + SILInstruction *user = use->getUser(); + assert(user && "Missing user"); // Ignore uses in the same basic block. - if (User->getParent() == Header) + if (user->getParent() == Header) continue; - assert(User->getParent() != EntryCheckBlock && - "The entry check block should dominate the header"); - Updater.RewriteUse(*Use); + assert(user->getParent() != EntryCheckBlock + && "The entry check block should dominate the header"); + updater.RewriteUse(*use); } // Canonicalize inserted phis to avoid extra BB Args. - for (SILPhiArgument *Arg : InsertedPHIs) { - if (SILValue Inst = replaceBBArgWithCast(Arg)) { - Arg->replaceAllUsesWith(Inst); + for (SILPhiArgument *arg : insertedPhis) { + if (SILValue inst = replaceBBArgWithCast(arg)) { + arg->replaceAllUsesWith(inst); // DCE+SimplifyCFG runs as a post-pass cleanup. // DCE replaces dead arg values with undef. // SimplifyCFG deletes the dead BB arg. @@ -159,72 +155,76 @@ static void updateSSAForUseOfValue( } } -static void updateSSAForUseOfInst( - SILSSAUpdater &Updater, SmallVectorImpl &InsertedPHIs, - const llvm::DenseMap &ValueMap, - SILBasicBlock *Header, SILBasicBlock *EntryCheckBlock, - SILInstruction *Inst) { - for (auto result : Inst->getResults()) - updateSSAForUseOfValue(Updater, InsertedPHIs, ValueMap, Header, - EntryCheckBlock, result); +static void +updateSSAForUseOfInst(SILSSAUpdater &updater, + SmallVectorImpl &insertedPhis, + const llvm::DenseMap &valueMap, + SILBasicBlock *header, SILBasicBlock *entryCheckBlock, + SILInstruction *inst) { + for (auto result : inst->getResults()) + updateSSAForUseOfValue(updater, insertedPhis, valueMap, header, + entryCheckBlock, result); } /// Rewrite the code we just created in the preheader and update SSA form. -static void -rewriteNewLoopEntryCheckBlock(SILBasicBlock *Header, - SILBasicBlock *EntryCheckBlock, - const llvm::DenseMap &ValueMap) { - SmallVector InsertedPHIs; - SILSSAUpdater Updater(&InsertedPHIs); +static void rewriteNewLoopEntryCheckBlock( + SILBasicBlock *header, SILBasicBlock *entryCheckBlock, + const llvm::DenseMap &valueMap) { + SmallVector insertedPhis; + SILSSAUpdater updater(&insertedPhis); // Fix PHIs (incoming arguments). - for (auto *Arg : Header->getArguments()) - updateSSAForUseOfValue(Updater, InsertedPHIs, ValueMap, Header, - EntryCheckBlock, Arg); + for (auto *arg : header->getArguments()) + updateSSAForUseOfValue(updater, insertedPhis, valueMap, header, + entryCheckBlock, arg); - auto InstIter = Header->begin(); + auto instIter = header->begin(); // The terminator might change from under us. - while (InstIter != Header->end()) { - auto &Inst = *InstIter; - updateSSAForUseOfInst(Updater, InsertedPHIs, ValueMap, Header, - EntryCheckBlock, &Inst); - InstIter++; + while (instIter != header->end()) { + auto &inst = *instIter; + updateSSAForUseOfInst(updater, insertedPhis, valueMap, header, + entryCheckBlock, &inst); + instIter++; } } /// Update the dominator tree after rotating the loop. /// The former preheader now dominates all of the former headers children. The /// former latch now dominates the former header. -static void updateDomTree(DominanceInfo *DT, SILBasicBlock *Preheader, - SILBasicBlock *Latch, SILBasicBlock *Header) { - auto *HeaderN = DT->getNode(Header); - SmallVector Children(HeaderN->begin(), - HeaderN->end()); - auto *PreheaderN = DT->getNode(Preheader); +static void updateDomTree(DominanceInfo *domInfo, SILBasicBlock *preheader, + SILBasicBlock *latch, SILBasicBlock *header) { + auto *headerN = domInfo->getNode(header); + SmallVector Children(headerN->begin(), + headerN->end()); + auto *preheaderN = domInfo->getNode(preheader); for (auto *Child : Children) - DT->changeImmediateDominator(Child, PreheaderN); + domInfo->changeImmediateDominator(Child, preheaderN); - if (Header != Latch) - DT->changeImmediateDominator(HeaderN, DT->getNode(Latch)); + if (header != latch) + domInfo->changeImmediateDominator(headerN, domInfo->getNode(latch)); } -static bool rotateLoopAtMostUpToLatch(SILLoop *L, DominanceInfo *DT, - SILLoopInfo *LI, bool ShouldVerify) { - auto *Latch = L->getLoopLatch(); - if (!Latch) { - LLVM_DEBUG(llvm::dbgs() << *L << " does not have a single latch block\n"); +static bool rotateLoopAtMostUpToLatch(SILLoop *loop, DominanceInfo *domInfo, + SILLoopInfo *loopInfo, + bool ShouldVerify) { + auto *latch = loop->getLoopLatch(); + if (!latch) { + LLVM_DEBUG(llvm::dbgs() + << *loop << " does not have a single latch block\n"); return false; } - bool DidRotate = rotateLoop(L, DT, LI, false /* RotateSingleBlockLoops */, - Latch, ShouldVerify); + bool didRotate = + rotateLoop(loop, domInfo, loopInfo, false /* rotateSingleBlockLoops */, + latch, ShouldVerify); // Keep rotating at most until we hit the original latch. - if (DidRotate) - while (rotateLoop(L, DT, LI, false, Latch, ShouldVerify)) {} + if (didRotate) + while (rotateLoop(loop, domInfo, loopInfo, false, latch, ShouldVerify)) { + } - return DidRotate; + return didRotate; } /// Check whether this a single basic block loop - ignoring split back edges. @@ -237,16 +237,16 @@ static bool isSingleBlockLoop(SILLoop *L) { if (NumBlocks == 1) return true; - auto *Header = L->getHeader(); + auto *header = L->getHeader(); auto *BackEdge = Blocks[1]; - if (BackEdge == Header) + if (BackEdge == header) BackEdge = Blocks[0]; if (!BackEdge->getSingleSuccessorBlock()) return false; - assert(BackEdge->getSingleSuccessorBlock() == Header && - "Loop not well formed"); + assert(BackEdge->getSingleSuccessorBlock() == header + && "Loop not well formed"); // Check whether the back-edge block is just a split-edge. return ++BackEdge->begin() == BackEdge->end(); @@ -260,153 +260,155 @@ static bool isSingleBlockLoop(SILLoop *L) { /// /// We will rotate at most up to the basic block passed as an argument. /// We will not rotate a loop where the header is equal to the latch except is -/// RotateSingleBlockLoops is true. +/// rotateSingleBlockLoops is true. /// /// Note: The code relies on the 'UpTo' basic block to stay within the rotate /// loop for termination. -bool swift::rotateLoop(SILLoop *L, DominanceInfo *DT, SILLoopInfo *LI, - bool RotateSingleBlockLoops, SILBasicBlock *UpTo, - bool ShouldVerify) { - assert(L != nullptr && DT != nullptr && LI != nullptr && - "Missing loop information"); +bool swift::rotateLoop(SILLoop *loop, DominanceInfo *domInfo, + SILLoopInfo *loopInfo, bool rotateSingleBlockLoops, + SILBasicBlock *upToBB, bool shouldVerify) { + assert(loop != nullptr && domInfo != nullptr && loopInfo != nullptr + && "Missing loop information"); - auto *Header = L->getHeader(); - if (!Header) + auto *header = loop->getHeader(); + if (!header) return false; // We need a preheader - this is also a canonicalization for follow-up // passes. - auto *Preheader = L->getLoopPreheader(); - if (!Preheader) { - LLVM_DEBUG(llvm::dbgs() << *L << " no preheader\n"); - LLVM_DEBUG(L->getHeader()->getParent()->dump()); + auto *preheader = loop->getLoopPreheader(); + if (!preheader) { + LLVM_DEBUG(llvm::dbgs() << *loop << " no preheader\n"); + LLVM_DEBUG(loop->getHeader()->getParent()->dump()); return false; } - if (!RotateSingleBlockLoops && (Header == UpTo || isSingleBlockLoop(L))) + if (!rotateSingleBlockLoops && (header == upToBB || isSingleBlockLoop(loop))) return false; - assert(RotateSingleBlockLoops || L->getBlocks().size() != 1); + assert(rotateSingleBlockLoops || loop->getBlocks().size() != 1); // Need a conditional branch that guards the entry into the loop. - auto *LoopEntryBranch = dyn_cast(Header->getTerminator()); - if (!LoopEntryBranch) + auto *loopEntryBranch = dyn_cast(header->getTerminator()); + if (!loopEntryBranch) return false; // The header needs to exit the loop. - if (!L->isLoopExiting(Header)) { - LLVM_DEBUG(llvm::dbgs() << *L << " not an exiting header\n"); - LLVM_DEBUG(L->getHeader()->getParent()->dump()); + if (!loop->isLoopExiting(header)) { + LLVM_DEBUG(llvm::dbgs() << *loop << " not an exiting header\n"); + LLVM_DEBUG(loop->getHeader()->getParent()->dump()); return false; } // We need a single backedge and the latch must not exit the loop if it is // also the header. - auto *Latch = L->getLoopLatch(); - if (!Latch) { - LLVM_DEBUG(llvm::dbgs() << *L << " no single latch\n"); + auto *latch = loop->getLoopLatch(); + if (!latch) { + LLVM_DEBUG(llvm::dbgs() << *loop << " no single latch\n"); return false; } // Make sure we can duplicate the header. - SmallVector MoveToPreheader; - if (!canDuplicateOrMoveToPreheader(L, Preheader, Header, MoveToPreheader)) { - LLVM_DEBUG(llvm::dbgs() << *L - << " instructions in header preventing rotating\n"); + SmallVector moveToPreheader; + if (!canDuplicateOrMoveToPreheader(loop, preheader, header, + moveToPreheader)) { + LLVM_DEBUG(llvm::dbgs() + << *loop << " instructions in header preventing rotating\n"); return false; } - auto *NewHeader = LoopEntryBranch->getTrueBB(); - auto *Exit = LoopEntryBranch->getFalseBB(); - if (L->contains(Exit)) - std::swap(NewHeader, Exit); - assert(L->contains(NewHeader) && !L->contains(Exit) && - "Could not find loop header and exit block"); + auto *newHeader = loopEntryBranch->getTrueBB(); + auto *exit = loopEntryBranch->getFalseBB(); + if (loop->contains(exit)) + std::swap(newHeader, exit); + assert(loop->contains(newHeader) && !loop->contains(exit) + && "Could not find loop header and exit block"); // We don't want to rotate such that we merge two headers of separate loops // into one. This can be turned into an assert again once we have guaranteed // preheader insertions. - if (!NewHeader->getSinglePredecessorBlock() && Header != Latch) + if (!newHeader->getSinglePredecessorBlock() && header != latch) return false; // Now that we know we can perform the rotation - move the instructions that // need moving. - for (auto *Inst : MoveToPreheader) - Inst->moveBefore(Preheader->getTerminator()); + for (auto *inst : moveToPreheader) + inst->moveBefore(preheader->getTerminator()); - LLVM_DEBUG(llvm::dbgs() << " Rotating " << *L); + LLVM_DEBUG(llvm::dbgs() << " Rotating " << *loop); // Map the values for the duplicated header block. We are duplicating the // header instructions into the end of the preheader. - llvm::DenseMap ValueMap; + llvm::DenseMap valueMap; // The original 'phi' argument values are just the values coming from the // preheader edge. - ArrayRef PHIs = Header->getArguments(); - OperandValueArrayRef PreheaderArgs = - cast(Preheader->getTerminator())->getArgs(); - assert(PHIs.size() == PreheaderArgs.size() && - "Basic block arguments and incoming edge mismatch"); + ArrayRef phis = header->getArguments(); + OperandValueArrayRef preheaderArgs = + cast(preheader->getTerminator())->getArgs(); + assert(phis.size() == preheaderArgs.size() + && "Basic block arguments and incoming edge mismatch"); // Here we also store the value index to use into the value map (versus // non-argument values where the operand use decides which value index to // use). - for (unsigned Idx = 0, E = PHIs.size(); Idx != E; ++Idx) - ValueMap[PHIs[Idx]] = PreheaderArgs[Idx]; + for (unsigned Idx = 0, E = phis.size(); Idx != E; ++Idx) + valueMap[phis[Idx]] = preheaderArgs[Idx]; // The other instructions are just cloned to the preheader. - TermInst *PreheaderBranch = Preheader->getTerminator(); - for (auto &Inst : *Header) { - if (SILInstruction *cloned = Inst.clone(PreheaderBranch)) { - mapOperands(cloned, ValueMap); + TermInst *preheaderBranch = preheader->getTerminator(); + for (auto &inst : *header) { + if (SILInstruction *cloned = inst.clone(preheaderBranch)) { + mapOperands(cloned, valueMap); // The actual operand will sort out which result idx to use. - auto instResults = Inst.getResults(); + auto instResults = inst.getResults(); auto clonedResults = cloned->getResults(); assert(instResults.size() == clonedResults.size()); for (auto i : indices(instResults)) - ValueMap[instResults[i]] = clonedResults[i]; + valueMap[instResults[i]] = clonedResults[i]; } } - PreheaderBranch->dropAllReferences(); - PreheaderBranch->eraseFromParent(); + preheaderBranch->dropAllReferences(); + preheaderBranch->eraseFromParent(); // If there were any uses of instructions in the duplicated loop entry check // block rewrite them using the ssa updater. - rewriteNewLoopEntryCheckBlock(Header, Preheader, ValueMap); + rewriteNewLoopEntryCheckBlock(header, preheader, valueMap); - L->moveToHeader(NewHeader); + loop->moveToHeader(newHeader); // Now the original preheader dominates all of headers children and the // original latch dominates the header. - updateDomTree(DT, Preheader, Latch, Header); + updateDomTree(domInfo, preheader, latch, header); - assert(DT->getNode(NewHeader)->getIDom() == DT->getNode(Preheader)); - assert(!DT->dominates(Header, Exit) || - DT->getNode(Exit)->getIDom() == DT->getNode(Preheader)); - assert(DT->getNode(Header)->getIDom() == DT->getNode(Latch) || - ((Header == Latch) && - DT->getNode(Header)->getIDom() == DT->getNode(Preheader))); + assert(domInfo->getNode(newHeader)->getIDom() == domInfo->getNode(preheader)); + assert(!domInfo->dominates(header, exit) + || domInfo->getNode(exit)->getIDom() == domInfo->getNode(preheader)); + assert(domInfo->getNode(header)->getIDom() == domInfo->getNode(latch) + || ((header == latch) + && domInfo->getNode(header)->getIDom() + == domInfo->getNode(preheader))); // Beautify the IR. Move the old header to after the old latch as it is now // the latch. - Header->moveAfter(Latch); + header->moveAfter(latch); // Merge the old latch with the old header if possible. - mergeBasicBlockWithSuccessor(Latch, DT, LI); + mergeBasicBlockWithSuccessor(latch, domInfo, loopInfo); // Create a new preheader. - splitIfCriticalEdge(Preheader, NewHeader, DT, LI); + splitIfCriticalEdge(preheader, newHeader, domInfo, loopInfo); - if (ShouldVerify) { - DT->verify(); - LI->verify(); - Latch->getParent()->verify(); + if (shouldVerify) { + domInfo->verify(); + loopInfo->verify(); + latch->getParent()->verify(); } - LLVM_DEBUG(llvm::dbgs() << " to " << *L); - LLVM_DEBUG(L->getHeader()->getParent()->dump()); + LLVM_DEBUG(llvm::dbgs() << " to " << *loop); + LLVM_DEBUG(loop->getHeader()->getParent()->dump()); return true; } @@ -415,58 +417,59 @@ namespace { class LoopRotation : public SILFunctionTransform { void run() override { - SILLoopAnalysis *LA = PM->getAnalysis(); - assert(LA); - DominanceAnalysis *DA = PM->getAnalysis(); - assert(DA); + SILLoopAnalysis *loopAnalysis = PM->getAnalysis(); + assert(loopAnalysis); + DominanceAnalysis *domAnalysis = PM->getAnalysis(); + assert(domAnalysis); - SILFunction *F = getFunction(); - assert(F); + SILFunction *f = getFunction(); + assert(f); // FIXME: Add ownership support. - if (F->hasOwnership()) + if (f->hasOwnership()) return; - SILLoopInfo *LI = LA->get(F); - assert(LI); - DominanceInfo *DT = DA->get(F); + SILLoopInfo *loopInfo = loopAnalysis->get(f); + assert(loopInfo); + DominanceInfo *domInfo = domAnalysis->get(f); - if (LI->empty()) { - LLVM_DEBUG(llvm::dbgs() << "No loops in " << F->getName() << "\n"); + if (loopInfo->empty()) { + LLVM_DEBUG(llvm::dbgs() << "No loops in " << f->getName() << "\n"); return; } if (!ShouldRotate) { - LLVM_DEBUG(llvm::dbgs() << "Skipping loop rotation in " << F->getName() - << "\n"); + LLVM_DEBUG(llvm::dbgs() + << "Skipping loop rotation in " << f->getName() << "\n"); return; } - LLVM_DEBUG(llvm::dbgs() << "Rotating loops in " << F->getName() << "\n"); - bool ShouldVerify = getOptions().VerifyAll; + LLVM_DEBUG(llvm::dbgs() << "Rotating loops in " << f->getName() << "\n"); + bool shouldVerify = getOptions().VerifyAll; - bool Changed = false; - for (auto *LoopIt : *LI) { + bool changed = false; + for (auto *LoopIt : *loopInfo) { // Rotate loops recursively bottom-up in the loop tree. - SmallVector Worklist; - Worklist.push_back(LoopIt); - for (unsigned i = 0; i < Worklist.size(); ++i) { - auto *L = Worklist[i]; + SmallVector worklist; + worklist.push_back(LoopIt); + for (unsigned i = 0; i < worklist.size(); ++i) { + auto *L = worklist[i]; for (auto *SubLoop : *L) - Worklist.push_back(SubLoop); + worklist.push_back(SubLoop); } - while (!Worklist.empty()) { - SILLoop *Loop = Worklist.pop_back_val(); - Changed |= canonicalizeLoop(Loop, DT, LI); - Changed |= rotateLoopAtMostUpToLatch(Loop, DT, LI, ShouldVerify); + while (!worklist.empty()) { + SILLoop *loop = worklist.pop_back_val(); + changed |= canonicalizeLoop(loop, domInfo, loopInfo); + changed |= + rotateLoopAtMostUpToLatch(loop, domInfo, loopInfo, shouldVerify); } } - if (Changed) { + if (changed) { // We preserve loop info and the dominator tree. - DA->lockInvalidation(); - LA->lockInvalidation(); - PM->invalidateAnalysis(F, SILAnalysis::InvalidationKind::FunctionBody); - DA->unlockInvalidation(); - LA->unlockInvalidation(); + domAnalysis->lockInvalidation(); + loopAnalysis->lockInvalidation(); + PM->invalidateAnalysis(f, SILAnalysis::InvalidationKind::FunctionBody); + domAnalysis->unlockInvalidation(); + loopAnalysis->unlockInvalidation(); } } }; diff --git a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp index 0c1caf165e5..88f11083c49 100644 --- a/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp +++ b/lib/SILOptimizer/Utils/BasicBlockOptUtils.cpp @@ -17,110 +17,112 @@ using namespace swift; -/// Remove all instructions in the body of \p BB in safe manner by using +/// Remove all instructions in the body of \p bb in safe manner by using /// undef. -void swift::clearBlockBody(SILBasicBlock *BB) { +void swift::clearBlockBody(SILBasicBlock *bb) { // Instructions in the dead block may be used by other dead blocks. Replace // any uses of them with undef values. - while (!BB->empty()) { - // Grab the last instruction in the BB. - auto *Inst = &BB->back(); + while (!bb->empty()) { + // Grab the last instruction in the bb. + auto *inst = &bb->back(); // Replace any still-remaining uses with undef values and erase. - Inst->replaceAllUsesOfAllResultsWithUndef(); - Inst->eraseFromParent(); + inst->replaceAllUsesOfAllResultsWithUndef(); + inst->eraseFromParent(); } } // Handle the mechanical aspects of removing an unreachable block. -void swift::removeDeadBlock(SILBasicBlock *BB) { - // Clear the body of BB. - clearBlockBody(BB); +void swift::removeDeadBlock(SILBasicBlock *bb) { + // Clear the body of bb. + clearBlockBody(bb); - // Now that the BB is empty, eliminate it. - BB->eraseFromParent(); + // Now that the bb is empty, eliminate it. + bb->eraseFromParent(); } - -bool swift::removeUnreachableBlocks(SILFunction &Fn) { +bool swift::removeUnreachableBlocks(SILFunction &f) { // All reachable blocks, but does not include the entry block. - llvm::SmallPtrSet Visited; + llvm::SmallPtrSet visited; // Walk over the CFG, starting at the entry block, until all reachable blocks are visited. - llvm::SmallVector Worklist(1, Fn.getEntryBlock()); - while (!Worklist.empty()) { - SILBasicBlock *BB = Worklist.pop_back_val(); - for (auto &Succ : BB->getSuccessors()) { - if (Visited.insert(Succ).second) - Worklist.push_back(Succ); + llvm::SmallVector worklist(1, f.getEntryBlock()); + while (!worklist.empty()) { + SILBasicBlock *bb = worklist.pop_back_val(); + for (auto &Succ : bb->getSuccessors()) { + if (visited.insert(Succ).second) + worklist.push_back(Succ); } } // Remove the blocks we never reached. Exclude the entry block from the iteration because it's // not included in the Visited set. - bool Changed = false; - for (auto It = std::next(Fn.begin()), End = Fn.end(); It != End; ) { - auto *BB = &*It++; - if (!Visited.count(BB)) { - removeDeadBlock(BB); - Changed = true; + bool changed = false; + for (auto ii = std::next(f.begin()), end = f.end(); ii != end;) { + auto *bb = &*ii++; + if (!visited.count(bb)) { + removeDeadBlock(bb); + changed = true; } } - return Changed; + return changed; } /// Helper function to perform SSA updates in case of jump threading. -void swift::updateSSAAfterCloning(BasicBlockCloner &Cloner, - SILBasicBlock *SrcBB, SILBasicBlock *DestBB) { - SILSSAUpdater SSAUp; - for (auto AvailValPair : Cloner.AvailVals) { - ValueBase *Inst = AvailValPair.first; - if (Inst->use_empty()) +void swift::updateSSAAfterCloning(BasicBlockCloner &cloner, + SILBasicBlock *srcBB, SILBasicBlock *destBB) { + SILSSAUpdater ssaUpdater; + for (auto availValPair : cloner.AvailVals) { + ValueBase *inst = availValPair.first; + if (inst->use_empty()) continue; - SILValue NewRes(AvailValPair.second); + SILValue newResult(availValPair.second); - SmallVector UseList; + SmallVector useList; // Collect the uses of the value. - for (auto Use : Inst->getUses()) - UseList.push_back(UseWrapper(Use)); + for (auto *use : inst->getUses()) + useList.push_back(UseWrapper(use)); - SSAUp.Initialize(Inst->getType()); - SSAUp.AddAvailableValue(DestBB, Inst); - SSAUp.AddAvailableValue(SrcBB, NewRes); + ssaUpdater.Initialize(inst->getType()); + ssaUpdater.AddAvailableValue(destBB, inst); + ssaUpdater.AddAvailableValue(srcBB, newResult); - if (UseList.empty()) + if (useList.empty()) continue; // Update all the uses. - for (auto U : UseList) { - Operand *Use = U; - SILInstruction *User = Use->getUser(); - assert(User && "Missing user"); + for (auto useWrapper : useList) { + Operand *use = useWrapper; + SILInstruction *user = use->getUser(); + assert(user && "Missing user"); // Ignore uses in the same basic block. - if (User->getParent() == DestBB) + if (user->getParent() == destBB) continue; - SSAUp.RewriteUse(*Use); + ssaUpdater.RewriteUse(*use); } } } // FIXME: Remove this. SILCloner should not create critical edges. -bool BasicBlockCloner::splitCriticalEdges(DominanceInfo *DT, SILLoopInfo *LI) { +bool BasicBlockCloner::splitCriticalEdges(DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { bool changed = false; // Remove any critical edges that the EdgeThreadingCloner may have // accidentally created. for (unsigned succIdx = 0, succEnd = origBB->getSuccessors().size(); succIdx != succEnd; ++succIdx) { - if (nullptr != splitCriticalEdge(origBB->getTerminator(), succIdx, DT, LI)) + if (nullptr + != splitCriticalEdge(origBB->getTerminator(), succIdx, domInfo, + loopInfo)) changed |= true; } for (unsigned succIdx = 0, succEnd = getNewBB()->getSuccessors().size(); succIdx != succEnd; ++succIdx) { - auto *newBB = - splitCriticalEdge(getNewBB()->getTerminator(), succIdx, DT, LI); + auto *newBB = splitCriticalEdge(getNewBB()->getTerminator(), succIdx, + domInfo, loopInfo); changed |= (newBB != nullptr); } return changed; @@ -199,45 +201,44 @@ bool SinkAddressProjections::cloneProjections() { return true; } -void StaticInitCloner::add(SILInstruction *InitVal) { +void StaticInitCloner::add(SILInstruction *initVal) { // Don't schedule an instruction twice for cloning. - if (NumOpsToClone.count(InitVal) != 0) + if (numOpsToClone.count(initVal) != 0) return; - ArrayRef Ops = InitVal->getAllOperands(); - NumOpsToClone[InitVal] = Ops.size(); - if (Ops.empty()) { + ArrayRef operands = initVal->getAllOperands(); + numOpsToClone[initVal] = operands.size(); + if (operands.empty()) { // It's an instruction without operands, e.g. a literal. It's ready to be // cloned first. - ReadyToClone.push_back(InitVal); + readyToClone.push_back(initVal); } else { // Recursively add all operands. - for (const Operand &Op : Ops) { - add(cast(Op.get())); + for (const Operand &operand : operands) { + add(cast(operand.get())); } } } SingleValueInstruction * -StaticInitCloner::clone(SingleValueInstruction *InitVal) { - assert(NumOpsToClone.count(InitVal) != 0 && "InitVal was not added"); +StaticInitCloner::clone(SingleValueInstruction *initVal) { + assert(numOpsToClone.count(initVal) != 0 && "initVal was not added"); // Find the right order to clone: all operands of an instruction must be // cloned before the instruction itself. - while (!ReadyToClone.empty()) { - SILInstruction *I = ReadyToClone.pop_back_val(); + while (!readyToClone.empty()) { + SILInstruction *inst = readyToClone.pop_back_val(); // Clone the instruction into the SILGlobalVariable - visit(I); + visit(inst); // Check if users of I can now be cloned. - for (SILValue result : I->getResults()) { - for (Operand *Use : result->getUses()) { - SILInstruction *User = Use->getUser(); - if (NumOpsToClone.count(User) != 0 && --NumOpsToClone[User] == 0) - ReadyToClone.push_back(User); + for (SILValue result : inst->getResults()) { + for (Operand *use : result->getUses()) { + SILInstruction *user = use->getUser(); + if (numOpsToClone.count(user) != 0 && --numOpsToClone[user] == 0) + readyToClone.push_back(user); } } } - return cast(getMappedValue(InitVal)); + return cast(getMappedValue(initVal)); } - diff --git a/lib/SILOptimizer/Utils/CFGOptUtils.cpp b/lib/SILOptimizer/Utils/CFGOptUtils.cpp index 8a10396254b..b310323cc27 100644 --- a/lib/SILOptimizer/Utils/CFGOptUtils.cpp +++ b/lib/SILOptimizer/Utils/CFGOptUtils.cpp @@ -25,57 +25,57 @@ using namespace swift; /// Adds a new argument to an edge between a branch and a destination /// block. /// -/// \param Branch The terminator to add the argument to. -/// \param Dest The destination block of the edge. +/// \param branch The terminator to add the argument to. +/// \param dest The destination block of the edge. /// \param Val The value to the arguments of the branch. /// \return The created branch. The old branch is deleted. /// The argument is appended at the end of the argument tuple. -TermInst *swift::addNewEdgeValueToBranch(TermInst *Branch, SILBasicBlock *Dest, - SILValue Val) { - SILBuilderWithScope Builder(Branch); - TermInst *NewBr = nullptr; +TermInst *swift::addNewEdgeValueToBranch(TermInst *branch, SILBasicBlock *dest, + SILValue val) { + SILBuilderWithScope builder(branch); + TermInst *newBr = nullptr; - if (auto *CBI = dyn_cast(Branch)) { - SmallVector TrueArgs; - SmallVector FalseArgs; + if (auto *cbi = dyn_cast(branch)) { + SmallVector trueArgs; + SmallVector falseArgs; - for (auto A : CBI->getTrueArgs()) - TrueArgs.push_back(A); + for (auto arg : cbi->getTrueArgs()) + trueArgs.push_back(arg); - for (auto A : CBI->getFalseArgs()) - FalseArgs.push_back(A); + for (auto arg : cbi->getFalseArgs()) + falseArgs.push_back(arg); - if (Dest == CBI->getTrueBB()) { - TrueArgs.push_back(Val); - assert(TrueArgs.size() == Dest->getNumArguments()); + if (dest == cbi->getTrueBB()) { + trueArgs.push_back(val); + assert(trueArgs.size() == dest->getNumArguments()); } - if (Dest == CBI->getFalseBB()) { - FalseArgs.push_back(Val); - assert(FalseArgs.size() == Dest->getNumArguments()); + if (dest == cbi->getFalseBB()) { + falseArgs.push_back(val); + assert(falseArgs.size() == dest->getNumArguments()); } - NewBr = Builder.createCondBranch( - CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, - CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), - CBI->getFalseBBCount()); - } else if (auto *BI = dyn_cast(Branch)) { - SmallVector Args; + newBr = builder.createCondBranch( + cbi->getLoc(), cbi->getCondition(), cbi->getTrueBB(), trueArgs, + cbi->getFalseBB(), falseArgs, cbi->getTrueBBCount(), + cbi->getFalseBBCount()); + } else if (auto *bi = dyn_cast(branch)) { + SmallVector args; - for (auto A : BI->getArgs()) - Args.push_back(A); + for (auto arg : bi->getArgs()) + args.push_back(arg); - Args.push_back(Val); - assert(Args.size() == Dest->getNumArguments()); - NewBr = Builder.createBranch(BI->getLoc(), BI->getDestBB(), Args); + args.push_back(val); + assert(args.size() == dest->getNumArguments()); + newBr = builder.createBranch(bi->getLoc(), bi->getDestBB(), args); } else { // At the moment we can only add arguments to br and cond_br. llvm_unreachable("Can't add argument to terminator"); } - Branch->dropAllReferences(); - Branch->eraseFromParent(); + branch->dropAllReferences(); + branch->eraseFromParent(); - return NewBr; + return newBr; } static void @@ -157,255 +157,260 @@ void swift::erasePhiArgument(SILBasicBlock *block, unsigned argIndex) { } /// Changes the edge value between a branch and destination basic block -/// at the specified index. Changes all edges from \p Branch to \p Dest to carry +/// at the specified index. Changes all edges from \p branch to \p dest to carry /// the value. /// -/// \param Branch The branch to modify. -/// \param Dest The destination of the edge. -/// \param Idx The index of the argument to modify. +/// \param branch The branch to modify. +/// \param dest The destination of the edge. +/// \param idx The index of the argument to modify. /// \param Val The new value to use. /// \return The new branch. Deletes the old one. /// Changes the edge value between a branch and destination basic block at the /// specified index. -TermInst *swift::changeEdgeValue(TermInst *Branch, SILBasicBlock *Dest, - size_t Idx, SILValue Val) { - SILBuilderWithScope Builder(Branch); +TermInst *swift::changeEdgeValue(TermInst *branch, SILBasicBlock *dest, + size_t idx, SILValue Val) { + SILBuilderWithScope builder(branch); - if (auto *CBI = dyn_cast(Branch)) { - SmallVector TrueArgs; - SmallVector FalseArgs; + if (auto *cbi = dyn_cast(branch)) { + SmallVector trueArgs; + SmallVector falseArgs; - OperandValueArrayRef OldTrueArgs = CBI->getTrueArgs(); - bool BranchOnTrue = CBI->getTrueBB() == Dest; - assert((!BranchOnTrue || Idx < OldTrueArgs.size()) && "Not enough edges"); + OperandValueArrayRef oldTrueArgs = cbi->getTrueArgs(); + bool branchOnTrue = cbi->getTrueBB() == dest; + assert((!branchOnTrue || idx < oldTrueArgs.size()) && "Not enough edges"); - // Copy the edge values overwriting the edge at Idx. - for (unsigned i = 0, e = OldTrueArgs.size(); i != e; ++i) { - if (BranchOnTrue && Idx == i) - TrueArgs.push_back(Val); + // Copy the edge values overwriting the edge at idx. + for (unsigned i = 0, e = oldTrueArgs.size(); i != e; ++i) { + if (branchOnTrue && idx == i) + trueArgs.push_back(Val); else - TrueArgs.push_back(OldTrueArgs[i]); + trueArgs.push_back(oldTrueArgs[i]); } - assert(TrueArgs.size() == CBI->getTrueBB()->getNumArguments() + assert(trueArgs.size() == cbi->getTrueBB()->getNumArguments() && "Destination block's number of arguments must match"); - OperandValueArrayRef OldFalseArgs = CBI->getFalseArgs(); - bool BranchOnFalse = CBI->getFalseBB() == Dest; - assert((!BranchOnFalse || Idx < OldFalseArgs.size()) && "Not enough edges"); + OperandValueArrayRef oldFalseArgs = cbi->getFalseArgs(); + bool branchOnFalse = cbi->getFalseBB() == dest; + assert((!branchOnFalse || idx < oldFalseArgs.size()) && "Not enough edges"); - // Copy the edge values overwriting the edge at Idx. - for (unsigned i = 0, e = OldFalseArgs.size(); i != e; ++i) { - if (BranchOnFalse && Idx == i) - FalseArgs.push_back(Val); + // Copy the edge values overwriting the edge at idx. + for (unsigned i = 0, e = oldFalseArgs.size(); i != e; ++i) { + if (branchOnFalse && idx == i) + falseArgs.push_back(Val); else - FalseArgs.push_back(OldFalseArgs[i]); + falseArgs.push_back(oldFalseArgs[i]); } - assert(FalseArgs.size() == CBI->getFalseBB()->getNumArguments() + assert(falseArgs.size() == cbi->getFalseBB()->getNumArguments() && "Destination block's number of arguments must match"); - CBI = Builder.createCondBranch( - CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, - CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), - CBI->getFalseBBCount()); - Branch->dropAllReferences(); - Branch->eraseFromParent(); - return CBI; + cbi = builder.createCondBranch( + cbi->getLoc(), cbi->getCondition(), cbi->getTrueBB(), trueArgs, + cbi->getFalseBB(), falseArgs, cbi->getTrueBBCount(), + cbi->getFalseBBCount()); + branch->dropAllReferences(); + branch->eraseFromParent(); + return cbi; } - if (auto *BI = dyn_cast(Branch)) { - SmallVector Args; + if (auto *bi = dyn_cast(branch)) { + SmallVector args; - assert(Idx < BI->getNumArgs() && "Not enough edges"); - OperandValueArrayRef OldArgs = BI->getArgs(); + assert(idx < bi->getNumArgs() && "Not enough edges"); + OperandValueArrayRef oldArgs = bi->getArgs(); - // Copy the edge values overwriting the edge at Idx. - for (unsigned i = 0, e = OldArgs.size(); i != e; ++i) { - if (Idx == i) - Args.push_back(Val); + // Copy the edge values overwriting the edge at idx. + for (unsigned i = 0, e = oldArgs.size(); i != e; ++i) { + if (idx == i) + args.push_back(Val); else - Args.push_back(OldArgs[i]); + args.push_back(oldArgs[i]); } - assert(Args.size() == Dest->getNumArguments()); + assert(args.size() == dest->getNumArguments()); - BI = Builder.createBranch(BI->getLoc(), BI->getDestBB(), Args); - Branch->dropAllReferences(); - Branch->eraseFromParent(); - return BI; + bi = builder.createBranch(bi->getLoc(), bi->getDestBB(), args); + branch->dropAllReferences(); + branch->eraseFromParent(); + return bi; } llvm_unreachable("Unhandled terminator leading to merge block"); } template -SILBasicBlock *replaceSwitchDest(SwitchEnumTy *S, - SmallVectorImpl &Cases, - unsigned EdgeIdx, SILBasicBlock *NewDest) { - auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; - for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) - if (EdgeIdx != i) - Cases.push_back(S->getCase(i)); +SILBasicBlock *replaceSwitchDest(SwitchEnumTy *sTy, + SmallVectorImpl &cases, + unsigned edgeIdx, SILBasicBlock *newDest) { + auto *defaultBB = sTy->hasDefault() ? sTy->getDefaultBB() : nullptr; + for (unsigned i = 0, e = sTy->getNumCases(); i != e; ++i) + if (edgeIdx != i) + cases.push_back(sTy->getCase(i)); else - Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); - if (EdgeIdx == S->getNumCases()) - DefaultBB = NewDest; - return DefaultBB; + cases.push_back(std::make_pair(sTy->getCase(i).first, newDest)); + if (edgeIdx == sTy->getNumCases()) + defaultBB = newDest; + return defaultBB; } template SILBasicBlock * -replaceSwitchDest(SwitchEnumTy *S, SmallVectorImpl &Cases, - SILBasicBlock *OldDest, SILBasicBlock *NewDest) { - auto *DefaultBB = S->hasDefault() ? S->getDefaultBB() : nullptr; - for (unsigned i = 0, e = S->getNumCases(); i != e; ++i) - if (S->getCase(i).second != OldDest) - Cases.push_back(S->getCase(i)); +replaceSwitchDest(SwitchEnumTy *sTy, SmallVectorImpl &cases, + SILBasicBlock *oldDest, SILBasicBlock *newDest) { + auto *defaultBB = sTy->hasDefault() ? sTy->getDefaultBB() : nullptr; + for (unsigned i = 0, e = sTy->getNumCases(); i != e; ++i) + if (sTy->getCase(i).second != oldDest) + cases.push_back(sTy->getCase(i)); else - Cases.push_back(std::make_pair(S->getCase(i).first, NewDest)); - if (OldDest == DefaultBB) - DefaultBB = NewDest; - return DefaultBB; + cases.push_back(std::make_pair(sTy->getCase(i).first, newDest)); + if (oldDest == defaultBB) + defaultBB = newDest; + return defaultBB; } /// Replace a branch target. /// /// \param T The terminating instruction to modify. -/// \param OldDest The successor block that will be replaced. -/// \param NewDest The new target block. -/// \param PreserveArgs If set, preserve arguments on the replaced edge. -void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, - SILBasicBlock *NewDest, bool PreserveArgs) { - SILBuilderWithScope B(T); +/// \param oldDest The successor block that will be replaced. +/// \param newDest The new target block. +/// \param preserveArgs If set, preserve arguments on the replaced edge. +void swift::replaceBranchTarget(TermInst *t, SILBasicBlock *oldDest, + SILBasicBlock *newDest, bool preserveArgs) { + SILBuilderWithScope builder(t); - switch (T->getTermKind()) { + switch (t->getTermKind()) { // Only Branch and CondBranch may have arguments. case TermKind::BranchInst: { - auto Br = cast(T); - assert(OldDest == Br->getDestBB() && "wrong branch target"); - SmallVector Args; - if (PreserveArgs) { - for (auto Arg : Br->getArgs()) - Args.push_back(Arg); + auto br = cast(t); + assert(oldDest == br->getDestBB() && "wrong branch target"); + SmallVector args; + if (preserveArgs) { + for (auto arg : br->getArgs()) + args.push_back(arg); } - B.createBranch(T->getLoc(), NewDest, Args); - Br->dropAllReferences(); - Br->eraseFromParent(); + builder.createBranch(t->getLoc(), newDest, args); + br->dropAllReferences(); + br->eraseFromParent(); return; } case TermKind::CondBranchInst: { - auto CondBr = cast(T); - SmallVector TrueArgs; - if (OldDest == CondBr->getFalseBB() || PreserveArgs) { - for (auto Arg : CondBr->getTrueArgs()) - TrueArgs.push_back(Arg); + auto condBr = cast(t); + SmallVector trueArgs; + if (oldDest == condBr->getFalseBB() || preserveArgs) { + for (auto Arg : condBr->getTrueArgs()) + trueArgs.push_back(Arg); } - SmallVector FalseArgs; - if (OldDest == CondBr->getTrueBB() || PreserveArgs) { - for (auto Arg : CondBr->getFalseArgs()) - FalseArgs.push_back(Arg); + SmallVector falseArgs; + if (oldDest == condBr->getTrueBB() || preserveArgs) { + for (auto arg : condBr->getFalseArgs()) + falseArgs.push_back(arg); } - SILBasicBlock *TrueDest = CondBr->getTrueBB(); - SILBasicBlock *FalseDest = CondBr->getFalseBB(); - if (OldDest == CondBr->getTrueBB()) { - TrueDest = NewDest; + SILBasicBlock *trueDest = condBr->getTrueBB(); + SILBasicBlock *falseDest = condBr->getFalseBB(); + if (oldDest == condBr->getTrueBB()) { + trueDest = newDest; } else { - assert(OldDest == CondBr->getFalseBB() && "wrong cond_br target"); - FalseDest = NewDest; + assert(oldDest == condBr->getFalseBB() && "wrong cond_br target"); + falseDest = newDest; } - B.createCondBranch(CondBr->getLoc(), CondBr->getCondition(), TrueDest, - TrueArgs, FalseDest, FalseArgs, CondBr->getTrueBBCount(), - CondBr->getFalseBBCount()); - CondBr->dropAllReferences(); - CondBr->eraseFromParent(); + builder.createCondBranch( + condBr->getLoc(), condBr->getCondition(), trueDest, trueArgs, falseDest, + falseArgs, condBr->getTrueBBCount(), condBr->getFalseBBCount()); + condBr->dropAllReferences(); + condBr->eraseFromParent(); return; } case TermKind::SwitchValueInst: { - auto SII = cast(T); - SmallVector, 8> Cases; - auto *DefaultBB = replaceSwitchDest(SII, Cases, OldDest, NewDest); - B.createSwitchValue(SII->getLoc(), SII->getOperand(), DefaultBB, Cases); - SII->eraseFromParent(); + auto sii = cast(t); + SmallVector, 8> cases; + auto *defaultBB = replaceSwitchDest(sii, cases, oldDest, newDest); + builder.createSwitchValue(sii->getLoc(), sii->getOperand(), defaultBB, + cases); + sii->eraseFromParent(); return; } case TermKind::SwitchEnumInst: { - auto SEI = cast(T); - SmallVector, 8> Cases; - auto *DefaultBB = replaceSwitchDest(SEI, Cases, OldDest, NewDest); - B.createSwitchEnum(SEI->getLoc(), SEI->getOperand(), DefaultBB, Cases); - SEI->eraseFromParent(); + auto sei = cast(t); + SmallVector, 8> cases; + auto *defaultBB = replaceSwitchDest(sei, cases, oldDest, newDest); + builder.createSwitchEnum(sei->getLoc(), sei->getOperand(), defaultBB, + cases); + sei->eraseFromParent(); return; } case TermKind::SwitchEnumAddrInst: { - auto SEI = cast(T); - SmallVector, 8> Cases; - auto *DefaultBB = replaceSwitchDest(SEI, Cases, OldDest, NewDest); - B.createSwitchEnumAddr(SEI->getLoc(), SEI->getOperand(), DefaultBB, Cases); - SEI->eraseFromParent(); + auto sei = cast(t); + SmallVector, 8> cases; + auto *defaultBB = replaceSwitchDest(sei, cases, oldDest, newDest); + builder.createSwitchEnumAddr(sei->getLoc(), sei->getOperand(), defaultBB, + cases); + sei->eraseFromParent(); return; } case TermKind::DynamicMethodBranchInst: { - auto DMBI = cast(T); - assert(OldDest == DMBI->getHasMethodBB() - || OldDest == DMBI->getNoMethodBB() && "Invalid edge index"); - auto HasMethodBB = - OldDest == DMBI->getHasMethodBB() ? NewDest : DMBI->getHasMethodBB(); - auto NoMethodBB = - OldDest == DMBI->getNoMethodBB() ? NewDest : DMBI->getNoMethodBB(); - B.createDynamicMethodBranch(DMBI->getLoc(), DMBI->getOperand(), - DMBI->getMember(), HasMethodBB, NoMethodBB); - DMBI->eraseFromParent(); + auto dmbi = cast(t); + assert(oldDest == dmbi->getHasMethodBB() + || oldDest == dmbi->getNoMethodBB() && "Invalid edge index"); + auto hasMethodBB = + oldDest == dmbi->getHasMethodBB() ? newDest : dmbi->getHasMethodBB(); + auto noMethodBB = + oldDest == dmbi->getNoMethodBB() ? newDest : dmbi->getNoMethodBB(); + builder.createDynamicMethodBranch(dmbi->getLoc(), dmbi->getOperand(), + dmbi->getMember(), hasMethodBB, + noMethodBB); + dmbi->eraseFromParent(); return; } case TermKind::CheckedCastBranchInst: { - auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() - || OldDest == CBI->getFailureBB() && "Invalid edge index"); - auto SuccessBB = - OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); - auto FailureBB = - OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); - B.createCheckedCastBranch(CBI->getLoc(), CBI->isExact(), CBI->getOperand(), - CBI->getCastType(), SuccessBB, FailureBB, - CBI->getTrueBBCount(), CBI->getFalseBBCount()); - CBI->eraseFromParent(); + auto cbi = cast(t); + assert(oldDest == cbi->getSuccessBB() + || oldDest == cbi->getFailureBB() && "Invalid edge index"); + auto successBB = + oldDest == cbi->getSuccessBB() ? newDest : cbi->getSuccessBB(); + auto failureBB = + oldDest == cbi->getFailureBB() ? newDest : cbi->getFailureBB(); + builder.createCheckedCastBranch( + cbi->getLoc(), cbi->isExact(), cbi->getOperand(), cbi->getCastType(), + successBB, failureBB, cbi->getTrueBBCount(), cbi->getFalseBBCount()); + cbi->eraseFromParent(); return; } case TermKind::CheckedCastValueBranchInst: { - auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() - || OldDest == CBI->getFailureBB() && "Invalid edge index"); - auto SuccessBB = - OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); - auto FailureBB = - OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); - B.createCheckedCastValueBranch(CBI->getLoc(), CBI->getOperand(), - CBI->getCastType(), SuccessBB, FailureBB); - CBI->eraseFromParent(); + auto cbi = cast(t); + assert(oldDest == cbi->getSuccessBB() + || oldDest == cbi->getFailureBB() && "Invalid edge index"); + auto successBB = + oldDest == cbi->getSuccessBB() ? newDest : cbi->getSuccessBB(); + auto failureBB = + oldDest == cbi->getFailureBB() ? newDest : cbi->getFailureBB(); + builder.createCheckedCastValueBranch(cbi->getLoc(), cbi->getOperand(), + cbi->getCastType(), successBB, + failureBB); + cbi->eraseFromParent(); return; } case TermKind::CheckedCastAddrBranchInst: { - auto CBI = cast(T); - assert(OldDest == CBI->getSuccessBB() - || OldDest == CBI->getFailureBB() && "Invalid edge index"); - auto SuccessBB = - OldDest == CBI->getSuccessBB() ? NewDest : CBI->getSuccessBB(); - auto FailureBB = - OldDest == CBI->getFailureBB() ? NewDest : CBI->getFailureBB(); - auto TrueCount = CBI->getTrueBBCount(); - auto FalseCount = CBI->getFalseBBCount(); - B.createCheckedCastAddrBranch(CBI->getLoc(), CBI->getConsumptionKind(), - CBI->getSrc(), CBI->getSourceType(), - CBI->getDest(), CBI->getTargetType(), - SuccessBB, FailureBB, TrueCount, FalseCount); - CBI->eraseFromParent(); + auto cbi = cast(t); + assert(oldDest == cbi->getSuccessBB() + || oldDest == cbi->getFailureBB() && "Invalid edge index"); + auto successBB = + oldDest == cbi->getSuccessBB() ? newDest : cbi->getSuccessBB(); + auto failureBB = + oldDest == cbi->getFailureBB() ? newDest : cbi->getFailureBB(); + auto trueCount = cbi->getTrueBBCount(); + auto falseCount = cbi->getFalseBBCount(); + builder.createCheckedCastAddrBranch( + cbi->getLoc(), cbi->getConsumptionKind(), cbi->getSrc(), + cbi->getSourceType(), cbi->getDest(), cbi->getTargetType(), successBB, + failureBB, trueCount, falseCount); + cbi->eraseFromParent(); return; } @@ -422,20 +427,20 @@ void swift::replaceBranchTarget(TermInst *T, SILBasicBlock *OldDest, } /// Check if the edge from the terminator is critical. -bool swift::isCriticalEdge(TermInst *T, unsigned EdgeIdx) { - assert(T->getSuccessors().size() > EdgeIdx && "Not enough successors"); +bool swift::isCriticalEdge(TermInst *t, unsigned edgeIdx) { + assert(t->getSuccessors().size() > edgeIdx && "Not enough successors"); - auto SrcSuccs = T->getSuccessors(); + auto srcSuccs = t->getSuccessors(); - if (SrcSuccs.size() <= 1 && + if (srcSuccs.size() <= 1 && // Also consider non-branch instructions with a single successor for // critical edges, for example: a switch_enum of a single-case enum. - (isa(T) || isa(T))) + (isa(t) || isa(t))) return false; - SILBasicBlock *DestBB = SrcSuccs[EdgeIdx]; - assert(!DestBB->pred_empty() && "There should be a predecessor"); - if (DestBB->getSinglePredecessorBlock()) + SILBasicBlock *destBB = srcSuccs[edgeIdx]; + assert(!destBB->pred_empty() && "There should be a predecessor"); + if (destBB->getSinglePredecessorBlock()) return false; return true; @@ -443,48 +448,48 @@ bool swift::isCriticalEdge(TermInst *T, unsigned EdgeIdx) { /// Splits the basic block at the iterator with an unconditional branch and /// updates the dominator tree and loop info. -SILBasicBlock *swift::splitBasicBlockAndBranch(SILBuilder &B, - SILInstruction *SplitBeforeInst, - DominanceInfo *DT, - SILLoopInfo *LI) { - auto *OrigBB = SplitBeforeInst->getParent(); - auto *NewBB = OrigBB->split(SplitBeforeInst->getIterator()); - B.setInsertionPoint(OrigBB); - B.createBranch(SplitBeforeInst->getLoc(), NewBB); +SILBasicBlock *swift::splitBasicBlockAndBranch(SILBuilder &builder, + SILInstruction *splitBeforeInst, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + auto *origBB = splitBeforeInst->getParent(); + auto *newBB = origBB->split(splitBeforeInst->getIterator()); + builder.setInsertionPoint(origBB); + builder.createBranch(splitBeforeInst->getLoc(), newBB); // Update the dominator tree. - if (DT) { - auto OrigBBDTNode = DT->getNode(OrigBB); - if (OrigBBDTNode) { + if (domInfo) { + auto origBBDTNode = domInfo->getNode(origBB); + if (origBBDTNode) { // Change the immediate dominators of the children of the block we // splitted to the splitted block. - SmallVector Adoptees(OrigBBDTNode->begin(), - OrigBBDTNode->end()); + SmallVector Adoptees(origBBDTNode->begin(), + origBBDTNode->end()); - auto NewBBDTNode = DT->addNewBlock(NewBB, OrigBB); - for (auto *Adoptee : Adoptees) - DT->changeImmediateDominator(Adoptee, NewBBDTNode); + auto newBBDTNode = domInfo->addNewBlock(newBB, origBB); + for (auto *adoptee : Adoptees) + domInfo->changeImmediateDominator(adoptee, newBBDTNode); } } // Update loop info. - if (LI) - if (auto *OrigBBLoop = LI->getLoopFor(OrigBB)) { - OrigBBLoop->addBasicBlockToLoop(NewBB, LI->getBase()); + if (loopInfo) + if (auto *origBBLoop = loopInfo->getLoopFor(origBB)) { + origBBLoop->addBasicBlockToLoop(newBB, loopInfo->getBase()); } - return NewBB; + return newBB; } /// Split every edge between two basic blocks. void swift::splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To, - DominanceInfo *DT, SILLoopInfo *LI) { - for (unsigned EdgeIndex = 0, E = From->getSuccessors().size(); EdgeIndex != E; - ++EdgeIndex) { - SILBasicBlock *SuccBB = From->getSuccessors()[EdgeIndex]; - if (SuccBB != To) + DominanceInfo *domInfo, SILLoopInfo *loopInfo) { + for (unsigned edgeIndex = 0, E = From->getSuccessors().size(); edgeIndex != E; + ++edgeIndex) { + SILBasicBlock *succBB = From->getSuccessors()[edgeIndex]; + if (succBB != To) continue; - splitEdge(From->getTerminator(), EdgeIndex, DT, LI); + splitEdge(From->getTerminator(), edgeIndex, domInfo, loopInfo); } } @@ -492,36 +497,39 @@ void swift::splitEdgesFromTo(SILBasicBlock *From, SILBasicBlock *To, /// loop info if set. /// Returns the newly created basic block on success or nullptr otherwise (if /// the edge was not critical. -SILBasicBlock *swift::splitCriticalEdge(TermInst *T, unsigned EdgeIdx, - DominanceInfo *DT, SILLoopInfo *LI) { - if (!isCriticalEdge(T, EdgeIdx)) +SILBasicBlock *swift::splitCriticalEdge(TermInst *t, unsigned edgeIdx, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + if (!isCriticalEdge(t, edgeIdx)) return nullptr; - return splitEdge(T, EdgeIdx, DT, LI); + return splitEdge(t, edgeIdx, domInfo, loopInfo); } -bool swift::splitCriticalEdgesFrom(SILBasicBlock *fromBB, DominanceInfo *DT, - SILLoopInfo *LI) { - bool Changed = false; +bool swift::splitCriticalEdgesFrom(SILBasicBlock *fromBB, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + bool changed = false; for (unsigned idx = 0, e = fromBB->getSuccessors().size(); idx != e; ++idx) { - auto *NewBB = splitCriticalEdge(fromBB->getTerminator(), idx, DT, LI); - Changed |= (NewBB != nullptr); + auto *newBB = + splitCriticalEdge(fromBB->getTerminator(), idx, domInfo, loopInfo); + changed |= (newBB != nullptr); } - return Changed; + return changed; } -bool swift::hasCriticalEdges(SILFunction &F, bool OnlyNonCondBr) { - for (SILBasicBlock &BB : F) { +bool swift::hasCriticalEdges(SILFunction &f, bool onlyNonCondBr) { + for (SILBasicBlock &bb : f) { // Only consider critical edges for terminators that don't support block // arguments. - if (OnlyNonCondBr && isa(BB.getTerminator())) + if (onlyNonCondBr && isa(bb.getTerminator())) continue; - if (isa(BB.getTerminator())) + if (isa(bb.getTerminator())) continue; - for (unsigned Idx = 0, e = BB.getSuccessors().size(); Idx != e; ++Idx) - if (isCriticalEdge(BB.getTerminator(), Idx)) + for (unsigned idx = 0, e = bb.getSuccessors().size(); idx != e; ++idx) + if (isCriticalEdge(bb.getTerminator(), idx)) return true; } return false; @@ -529,96 +537,99 @@ bool swift::hasCriticalEdges(SILFunction &F, bool OnlyNonCondBr) { /// Split all critical edges in the function updating the dominator tree and /// loop information (if they are not set to null). -bool swift::splitAllCriticalEdges(SILFunction &F, DominanceInfo *DT, - SILLoopInfo *LI) { - bool Changed = false; +bool swift::splitAllCriticalEdges(SILFunction &f, DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + bool changed = false; - for (SILBasicBlock &BB : F) { - if (isa(BB.getTerminator())) + for (SILBasicBlock &bb : f) { + if (isa(bb.getTerminator())) continue; - for (unsigned Idx = 0, e = BB.getSuccessors().size(); Idx != e; ++Idx) { - auto *NewBB = splitCriticalEdge(BB.getTerminator(), Idx, DT, LI); - assert(!NewBB - || isa(BB.getTerminator()) + for (unsigned idx = 0, e = bb.getSuccessors().size(); idx != e; ++idx) { + auto *newBB = + splitCriticalEdge(bb.getTerminator(), idx, domInfo, loopInfo); + assert(!newBB + || isa(bb.getTerminator()) && "Only cond_br may have a critical edge."); - Changed |= (NewBB != nullptr); + changed |= (newBB != nullptr); } } - return Changed; + return changed; } /// Merge the basic block with its successor if possible. If dominance /// information or loop info is non null update it. Return true if block was /// merged. -bool swift::mergeBasicBlockWithSuccessor(SILBasicBlock *BB, DominanceInfo *DT, - SILLoopInfo *LI) { - auto *Branch = dyn_cast(BB->getTerminator()); - if (!Branch) +bool swift::mergeBasicBlockWithSuccessor(SILBasicBlock *bb, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + auto *branch = dyn_cast(bb->getTerminator()); + if (!branch) return false; - auto *SuccBB = Branch->getDestBB(); - if (BB == SuccBB || !SuccBB->getSinglePredecessorBlock()) + auto *succBB = branch->getDestBB(); + if (bb == succBB || !succBB->getSinglePredecessorBlock()) return false; - if (DT) - if (auto *SuccBBNode = DT->getNode(SuccBB)) { + if (domInfo) + if (auto *succBBNode = domInfo->getNode(succBB)) { // Change the immediate dominator for children of the successor to be the // current block. - auto *BBNode = DT->getNode(BB); - SmallVector Children(SuccBBNode->begin(), - SuccBBNode->end()); + auto *bbNode = domInfo->getNode(bb); + SmallVector Children(succBBNode->begin(), + succBBNode->end()); for (auto *ChildNode : Children) - DT->changeImmediateDominator(ChildNode, BBNode); + domInfo->changeImmediateDominator(ChildNode, bbNode); - DT->eraseNode(SuccBB); + domInfo->eraseNode(succBB); } - if (LI) - LI->removeBlock(SuccBB); + if (loopInfo) + loopInfo->removeBlock(succBB); - mergeBasicBlockWithSingleSuccessor(BB, SuccBB); + mergeBasicBlockWithSingleSuccessor(bb, succBB); return true; } -bool swift::mergeBasicBlocks(SILFunction *F) { +bool swift::mergeBasicBlocks(SILFunction *f) { bool merged = false; - for (auto BBIter = F->begin(); BBIter != F->end();) { - if (mergeBasicBlockWithSuccessor(&*BBIter, /*DT*/ nullptr, - /*LI*/ nullptr)) { + for (auto bbIter = f->begin(); bbIter != f->end();) { + if (mergeBasicBlockWithSuccessor(&*bbIter, /*domInfo*/ nullptr, + /*loopInfo*/ nullptr)) { merged = true; // Continue to merge the current block without advancing. continue; } - ++BBIter; + ++bbIter; } return merged; } /// Splits the critical edges between from and to. This code assumes there is /// only one edge between the two basic blocks. -SILBasicBlock *swift::splitIfCriticalEdge(SILBasicBlock *From, - SILBasicBlock *To, DominanceInfo *DT, - SILLoopInfo *LI) { - auto *T = From->getTerminator(); - for (unsigned i = 0, e = T->getSuccessors().size(); i != e; ++i) { - if (T->getSuccessors()[i] == To) - return splitCriticalEdge(T, i, DT, LI); +SILBasicBlock *swift::splitIfCriticalEdge(SILBasicBlock *from, + SILBasicBlock *to, + DominanceInfo *domInfo, + SILLoopInfo *loopInfo) { + auto *t = from->getTerminator(); + for (unsigned i = 0, e = t->getSuccessors().size(); i != e; ++i) { + if (t->getSuccessors()[i] == to) + return splitCriticalEdge(t, i, domInfo, loopInfo); } llvm_unreachable("Destination block not found"); } void swift::completeJointPostDominanceSet( - ArrayRef UserBlocks, ArrayRef DefBlocks, - llvm::SmallVectorImpl &Result) { - assert(!UserBlocks.empty() && "Must have at least 1 user block"); - assert(!DefBlocks.empty() && "Must have at least 1 def block"); + ArrayRef userBlocks, ArrayRef defBlocks, + llvm::SmallVectorImpl &result) { + assert(!userBlocks.empty() && "Must have at least 1 user block"); + assert(!defBlocks.empty() && "Must have at least 1 def block"); // If we have only one def block and one user block and they are the same // block, then just return. - if (DefBlocks.size() == 1 && UserBlocks.size() == 1 - && UserBlocks[0] == DefBlocks[0]) { + if (defBlocks.size() == 1 && userBlocks.size() == 1 + && userBlocks[0] == defBlocks[0]) { return; } @@ -632,106 +643,106 @@ void swift::completeJointPostDominanceSet( // joint post-dominance to be true, no such successors should exist. // Our set of target blocks where we stop walking. - llvm::SmallPtrSet DefBlockSet(DefBlocks.begin(), - DefBlocks.end()); + llvm::SmallPtrSet defBlockSet(defBlocks.begin(), + defBlocks.end()); // The set of successor blocks of blocks that we visit. Any blocks still in // this set at the end of the walk act as a post-dominating closure around our - // UserBlock set. - llvm::SmallSetVector MustVisitSuccessorBlocks; + // userBlock set. + llvm::SmallSetVector mustVisitSuccessorBlocks; - // Add our user and def blocks to the VisitedBlock set. We never want to find + // Add our user and def blocks to the visitedBlock set. We never want to find // these in our worklist. - llvm::SmallPtrSet VisitedBlocks(UserBlocks.begin(), - UserBlocks.end()); + llvm::SmallPtrSet visitedBlocks(userBlocks.begin(), + userBlocks.end()); // Finally setup our worklist by adding our user block predecessors. We only // add the predecessors to the worklist once. - llvm::SmallVector Worklist; - for (auto *Block : UserBlocks) { - llvm::copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist), - [&](SILBasicBlock *PredBlock) -> bool { - return VisitedBlocks.insert(PredBlock).second; + llvm::SmallVector worklist; + for (auto *block : userBlocks) { + llvm::copy_if(block->getPredecessorBlocks(), std::back_inserter(worklist), + [&](SILBasicBlock *predBlock) -> bool { + return visitedBlocks.insert(predBlock).second; }); } // Then until we reach a fix point. - while (!Worklist.empty()) { + while (!worklist.empty()) { // Grab the next block from the worklist. - auto *Block = Worklist.pop_back_val(); - assert(VisitedBlocks.count(Block) + auto *block = worklist.pop_back_val(); + assert(visitedBlocks.count(block) && "All blocks from worklist should be " "in the visited blocks set."); // Since we are visiting this block now, we know that this block can not be // apart of a the post-dominance closure of our UseBlocks. - MustVisitSuccessorBlocks.remove(Block); + mustVisitSuccessorBlocks.remove(block); - // Then add each successor block of Block that has not been visited yet to - // the MustVisitSuccessorBlocks set. - for (auto *SuccBlock : Block->getSuccessorBlocks()) { - if (!VisitedBlocks.count(SuccBlock)) { - MustVisitSuccessorBlocks.insert(SuccBlock); + // Then add each successor block of block that has not been visited yet to + // the mustVisitSuccessorBlocks set. + for (auto *succBlock : block->getSuccessorBlocks()) { + if (!visitedBlocks.count(succBlock)) { + mustVisitSuccessorBlocks.insert(succBlock); } } // If this is a def block, then do not add its predecessors to the // worklist. - if (DefBlockSet.count(Block)) + if (defBlockSet.count(block)) continue; // Otherwise add all unvisited predecessors to the worklist. - llvm::copy_if(Block->getPredecessorBlocks(), std::back_inserter(Worklist), - [&](SILBasicBlock *Block) -> bool { - return VisitedBlocks.insert(Block).second; + llvm::copy_if(block->getPredecessorBlocks(), std::back_inserter(worklist), + [&](SILBasicBlock *block) -> bool { + return visitedBlocks.insert(block).second; }); } // Now that we are done, add all remaining must visit blocks to our result // list. These are the remaining parts of our joint post-dominance closure. - llvm::copy(MustVisitSuccessorBlocks, std::back_inserter(Result)); + llvm::copy(mustVisitSuccessorBlocks, std::back_inserter(result)); } -bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs(SILFunction &Fn, - DominanceInfo *DT, - SILLoopInfo *LI) { +bool swift::splitAllCondBrCriticalEdgesWithNonTrivialArgs( + SILFunction &fn, DominanceInfo *domInfo, SILLoopInfo *loopInfo) { // Find our targets. - llvm::SmallVector, 8> Targets; - for (auto &Block : Fn) { - auto *CBI = dyn_cast(Block.getTerminator()); - if (!CBI) + llvm::SmallVector, 8> targets; + for (auto &block : fn) { + auto *cbi = dyn_cast(block.getTerminator()); + if (!cbi) continue; // See if our true index is a critical edge. If so, add block to the list // and continue. If the false edge is also critical, we will handle it at // the same time. - if (isCriticalEdge(CBI, CondBranchInst::TrueIdx)) { - Targets.emplace_back(&Block, CondBranchInst::TrueIdx); + if (isCriticalEdge(cbi, CondBranchInst::TrueIdx)) { + targets.emplace_back(&block, CondBranchInst::TrueIdx); } - if (!isCriticalEdge(CBI, CondBranchInst::FalseIdx)) { + if (!isCriticalEdge(cbi, CondBranchInst::FalseIdx)) { continue; } - Targets.emplace_back(&Block, CondBranchInst::FalseIdx); + targets.emplace_back(&block, CondBranchInst::FalseIdx); } - if (Targets.empty()) + if (targets.empty()) return false; - for (auto P : Targets) { - SILBasicBlock *Block = P.first; - unsigned Index = P.second; - auto *Result = splitCriticalEdge(Block->getTerminator(), Index, DT, LI); - (void)Result; - assert(Result); + for (auto p : targets) { + SILBasicBlock *block = p.first; + unsigned index = p.second; + auto *result = + splitCriticalEdge(block->getTerminator(), index, domInfo, loopInfo); + (void)result; + assert(result); } return true; } -static bool isSafeNonExitTerminator(TermInst *TI) { - switch (TI->getTermKind()) { +static bool isSafeNonExitTerminator(TermInst *ti) { + switch (ti->getTermKind()) { case TermKind::BranchInst: case TermKind::CondBranchInst: case TermKind::SwitchValueInst: @@ -758,55 +769,55 @@ static bool isSafeNonExitTerminator(TermInst *TI) { llvm_unreachable("Unhandled TermKind in switch."); } -static bool isTrapNoReturnFunction(ApplyInst *AI) { +static bool isTrapNoReturnFunction(ApplyInst *ai) { const char *fatalName = MANGLE_AS_STRING( MANGLE_SYM(s18_fatalErrorMessageyys12StaticStringV_AcCSutF)); - auto *Fn = AI->getReferencedFunctionOrNull(); + auto *fn = ai->getReferencedFunctionOrNull(); // We use endswith here since if we specialize fatal error we will always // prepend the specialization records to fatalName. - if (!Fn || !Fn->getName().endswith(fatalName)) + if (!fn || !fn->getName().endswith(fatalName)) return false; return true; } bool swift::findAllNonFailureExitBBs( - SILFunction *F, llvm::TinyPtrVector &BBs) { - for (SILBasicBlock &BB : *F) { - TermInst *TI = BB.getTerminator(); + SILFunction *f, llvm::TinyPtrVector &bbs) { + for (SILBasicBlock &bb : *f) { + TermInst *ti = bb.getTerminator(); // If we know that this terminator is not an exit terminator, continue. - if (isSafeNonExitTerminator(TI)) + if (isSafeNonExitTerminator(ti)) continue; // A return inst is always a non-failure exit bb. - if (TI->isFunctionExiting()) { - BBs.push_back(&BB); + if (ti->isFunctionExiting()) { + bbs.push_back(&bb); continue; } // If we don't have an unreachable inst at this point, this is a terminator // we don't understand. Be conservative and return false. - if (!isa(TI)) + if (!isa(ti)) return false; // Ok, at this point we know we have a terminator. If it is the only - // instruction in our BB, it is a failure BB. continue... - if (TI == &*BB.begin()) + // instruction in our bb, it is a failure bb. continue... + if (ti == &*bb.begin()) continue; // If the unreachable is preceded by a no-return apply inst, then it is a - // non-failure exit BB. Add it to our list and continue. - auto PrevIter = std::prev(SILBasicBlock::iterator(TI)); - if (auto *AI = dyn_cast(&*PrevIter)) { - if (AI->isCalleeNoReturn() && !isTrapNoReturnFunction(AI)) { - BBs.push_back(&BB); + // non-failure exit bb. Add it to our list and continue. + auto prevIter = std::prev(SILBasicBlock::iterator(ti)); + if (auto *ai = dyn_cast(&*prevIter)) { + if (ai->isCalleeNoReturn() && !isTrapNoReturnFunction(ai)) { + bbs.push_back(&bb); continue; } } - // Otherwise, it must be a failure BB where we leak, continue. + // Otherwise, it must be a failure bb where we leak, continue. continue; } diff --git a/lib/SILOptimizer/Utils/Devirtualize.cpp b/lib/SILOptimizer/Utils/Devirtualize.cpp index 7ebaccf1065..6957266bc76 100644 --- a/lib/SILOptimizer/Utils/Devirtualize.cpp +++ b/lib/SILOptimizer/Utils/Devirtualize.cpp @@ -40,87 +40,83 @@ STATISTIC(NumWitnessDevirt, "Number of witness_method applies devirtualized"); // Class Method Optimization //===----------------------------------------------------------------------===// -void swift::getAllSubclasses(ClassHierarchyAnalysis *CHA, - ClassDecl *CD, - CanType ClassType, - SILModule &M, - ClassHierarchyAnalysis::ClassList &Subs) { +void swift::getAllSubclasses(ClassHierarchyAnalysis *cha, ClassDecl *cd, + CanType classType, SILModule &module, + ClassHierarchyAnalysis::ClassList &subs) { // Collect the direct and indirect subclasses for the class. // Sort these subclasses in the order they should be tested by the // speculative devirtualization. Different strategies could be used, // E.g. breadth-first, depth-first, etc. // Currently, let's use the breadth-first strategy. // The exact static type of the instance should be tested first. - auto &DirectSubs = CHA->getDirectSubClasses(CD); - auto &IndirectSubs = CHA->getIndirectSubClasses(CD); + auto &directSubs = cha->getDirectSubClasses(cd); + auto &indirectSubs = cha->getIndirectSubClasses(cd); - Subs.append(DirectSubs.begin(), DirectSubs.end()); - Subs.append(IndirectSubs.begin(), IndirectSubs.end()); + subs.append(directSubs.begin(), directSubs.end()); + subs.append(indirectSubs.begin(), indirectSubs.end()); // FIXME: This is wrong -- we could have a non-generic class nested // inside a generic class - if (isa(ClassType)) { + if (isa(classType)) { // Filter out any subclasses that do not inherit from this // specific bound class. - auto RemovedIt = std::remove_if(Subs.begin(), Subs.end(), - [&ClassType](ClassDecl *Sub){ + auto removedIt = + std::remove_if(subs.begin(), subs.end(), [&classType](ClassDecl *sub) { // FIXME: Add support for generic subclasses. - if (Sub->isGenericContext()) + if (sub->isGenericContext()) return false; - auto SubCanTy = Sub->getDeclaredInterfaceType()->getCanonicalType(); + auto subCanTy = sub->getDeclaredInterfaceType()->getCanonicalType(); // Handle the usual case here: the class in question // should be a real subclass of a bound generic class. - return !ClassType->isBindableToSuperclassOf( - SubCanTy); + return !classType->isBindableToSuperclassOf(subCanTy); }); - Subs.erase(RemovedIt, Subs.end()); + subs.erase(removedIt, subs.end()); } } /// Returns true, if a method implementation corresponding to -/// the class_method applied to an instance of the class CD is +/// the class_method applied to an instance of the class cd is /// effectively final, i.e. it is statically known to be not overridden -/// by any subclasses of the class CD. +/// by any subclasses of the class cd. /// -/// \p AI invocation instruction -/// \p ClassType type of the instance -/// \p CD static class of the instance whose method is being invoked -/// \p CHA class hierarchy analysis -static bool isEffectivelyFinalMethod(FullApplySite AI, - CanType ClassType, - ClassDecl *CD, - ClassHierarchyAnalysis *CHA) { - if (CD && CD->isFinal()) +/// \p applySite invocation instruction +/// \p classType type of the instance +/// \p cd static class of the instance whose method is being invoked +/// \p cha class hierarchy analysis +static bool isEffectivelyFinalMethod(FullApplySite applySite, CanType classType, + ClassDecl *cd, + ClassHierarchyAnalysis *cha) { + if (cd && cd->isFinal()) return true; - const DeclContext *DC = AI.getModule().getAssociatedContext(); + const DeclContext *dc = applySite.getModule().getAssociatedContext(); // Without an associated context we cannot perform any // access-based optimizations. - if (!DC) + if (!dc) return false; - auto *CMI = cast(AI.getCallee()); + auto *cmi = cast(applySite.getCallee()); - if (!calleesAreStaticallyKnowable(AI.getModule(), CMI->getMember())) + if (!calleesAreStaticallyKnowable(applySite.getModule(), cmi->getMember())) return false; - auto *Method = CMI->getMember().getAbstractFunctionDecl(); - assert(Method && "Expected abstract function decl!"); - assert(!Method->isFinal() && "Unexpected indirect call to final method!"); + auto *method = cmi->getMember().getAbstractFunctionDecl(); + assert(method && "Expected abstract function decl!"); + assert(!method->isFinal() && "Unexpected indirect call to final method!"); // If this method is not overridden in the module, // there is no other implementation. - if (!Method->isOverridden()) + if (!method->isOverridden()) return true; // Class declaration may be nullptr, e.g. for cases like: // func foo(c: C) {}, where C is a class, but // it does not have a class decl. - if (!CD) + if (!cd) return false; - if (!CHA) + if (!cha) return false; // This is a private or a module internal class. @@ -128,18 +124,18 @@ static bool isEffectivelyFinalMethod(FullApplySite AI, // We can analyze the class hierarchy rooted at it and // eventually devirtualize a method call more efficiently. - ClassHierarchyAnalysis::ClassList Subs; - getAllSubclasses(CHA, CD, ClassType, AI.getModule(), Subs); + ClassHierarchyAnalysis::ClassList subs; + getAllSubclasses(cha, cd, classType, applySite.getModule(), subs); // This is the implementation of the method to be used - // if the exact class of the instance would be CD. - auto *ImplMethod = CD->findImplementingMethod(Method); + // if the exact class of the instance would be cd. + auto *ImplMethod = cd->findImplementingMethod(method); // First, analyze all direct subclasses. - for (auto S : Subs) { + for (auto S : subs) { // Check if the subclass overrides a method and provides // a different implementation. - auto *ImplFD = S->findImplementingMethod(Method); + auto *ImplFD = S->findImplementingMethod(method); if (ImplFD != ImplMethod) return false; } @@ -153,32 +149,32 @@ static bool isEffectivelyFinalMethod(FullApplySite AI, /// - or it is private and has not sub-classes /// - or it is an internal class without sub-classes and /// it is a whole-module compilation. -static bool isKnownFinalClass(ClassDecl *CD, SILModule &M, - ClassHierarchyAnalysis *CHA) { - const DeclContext *DC = M.getAssociatedContext(); +static bool isKnownFinalClass(ClassDecl *cd, SILModule &module, + ClassHierarchyAnalysis *cha) { + const DeclContext *dc = module.getAssociatedContext(); - if (CD->isFinal()) + if (cd->isFinal()) return true; // Without an associated context we cannot perform any // access-based optimizations. - if (!DC) + if (!dc) return false; // Only handle classes defined within the SILModule's associated context. - if (!CD->isChildContextOf(DC)) + if (!cd->isChildContextOf(dc)) return false; - if (!CD->hasAccess()) + if (!cd->hasAccess()) return false; // Only consider 'private' members, unless we are in whole-module compilation. - switch (CD->getEffectiveAccess()) { + switch (cd->getEffectiveAccess()) { case AccessLevel::Open: return false; case AccessLevel::Public: case AccessLevel::Internal: - if (!M.isWholeModule()) + if (!module.isWholeModule()) return false; break; case AccessLevel::FilePrivate: @@ -192,14 +188,14 @@ static bool isKnownFinalClass(ClassDecl *CD, SILModule &M, // - or internal and it is a WMO compilation // then this class can be considered final for the purpose // of devirtualization. - if (CHA) { - if (!CHA->hasKnownDirectSubclasses(CD)) { - switch (CD->getEffectiveAccess()) { + if (cha) { + if (!cha->hasKnownDirectSubclasses(cd)) { + switch (cd->getEffectiveAccess()) { case AccessLevel::Open: return false; case AccessLevel::Public: case AccessLevel::Internal: - if (!M.isWholeModule()) + if (!module.isWholeModule()) return false; break; case AccessLevel::FilePrivate: @@ -214,57 +210,56 @@ static bool isKnownFinalClass(ClassDecl *CD, SILModule &M, return false; } - // Attempt to get the instance for S, whose static type is the same as // its exact dynamic type, returning a null SILValue() if we cannot find it. // The information that a static type is the same as the exact dynamic, // can be derived e.g.: // - from a constructor or // - from a successful outcome of a checked_cast_br [exact] instruction. -SILValue swift::getInstanceWithExactDynamicType(SILValue S, - ClassHierarchyAnalysis *CHA) { - auto *F = S->getFunction(); - auto &M = F->getModule(); +SILValue swift::getInstanceWithExactDynamicType(SILValue instance, + ClassHierarchyAnalysis *cha) { + auto *f = instance->getFunction(); + auto &module = f->getModule(); - while (S) { - S = stripCasts(S); + while (instance) { + instance = stripCasts(instance); - if (isa(S) || isa(S)) { - if (S->getType().getASTType()->hasDynamicSelfType()) + if (isa(instance) || isa(instance)) { + if (instance->getType().getASTType()->hasDynamicSelfType()) return SILValue(); - return S; + return instance; } - auto *Arg = dyn_cast(S); - if (!Arg) + auto *arg = dyn_cast(instance); + if (!arg) break; - auto *SinglePred = Arg->getParent()->getSinglePredecessorBlock(); - if (!SinglePred) { - if (!isa(Arg)) + auto *singlePred = arg->getParent()->getSinglePredecessorBlock(); + if (!singlePred) { + if (!isa(arg)) break; - auto *CD = Arg->getType().getClassOrBoundGenericClass(); + auto *cd = arg->getType().getClassOrBoundGenericClass(); // Check if this class is effectively final. - if (!CD || !isKnownFinalClass(CD, M, CHA)) + if (!cd || !isKnownFinalClass(cd, module, cha)) break; - return Arg; + return arg; } // Traverse the chain of predecessors. - if (isa(SinglePred->getTerminator()) || - isa(SinglePred->getTerminator())) { - S = cast(Arg)->getIncomingPhiValue(SinglePred); + if (isa(singlePred->getTerminator()) + || isa(singlePred->getTerminator())) { + instance = cast(arg)->getIncomingPhiValue(singlePred); continue; } // If it is a BB argument received on a success branch // of a checked_cast_br, then we know its exact type. - auto *CCBI = dyn_cast(SinglePred->getTerminator()); - if (!CCBI) + auto *ccbi = dyn_cast(singlePred->getTerminator()); + if (!ccbi) break; - if (!CCBI->isExact() || CCBI->getSuccessBB() != Arg->getParent()) + if (!ccbi->isExact() || ccbi->getSuccessBB() != arg->getParent()) break; - return S; + return instance; } return SILValue(); @@ -273,117 +268,117 @@ SILValue swift::getInstanceWithExactDynamicType(SILValue S, /// Try to determine the exact dynamic type of an object. /// returns the exact dynamic type of the object, or an empty type if the exact /// type could not be determined. -SILType swift::getExactDynamicType(SILValue S, - ClassHierarchyAnalysis *CHA, - bool ForUnderlyingObject) { - auto *F = S->getFunction(); - auto &M = F->getModule(); +SILType swift::getExactDynamicType(SILValue instance, + ClassHierarchyAnalysis *cha, + bool forUnderlyingObject) { + auto *f = instance->getFunction(); + auto &module = f->getModule(); // Set of values to be checked for their exact types. - SmallVector WorkList; + SmallVector worklist; // The detected type of the underlying object. - SILType ResultType; + SILType resultType; // Set of processed values. - llvm::SmallSet Processed; - WorkList.push_back(S); + llvm::SmallSet processed; + worklist.push_back(instance); - while (!WorkList.empty()) { - auto V = WorkList.pop_back_val(); - if (!V) + while (!worklist.empty()) { + auto v = worklist.pop_back_val(); + if (!v) return SILType(); - if (Processed.count(V)) + if (processed.count(v)) continue; - Processed.insert(V); + processed.insert(v); // For underlying object strip casts and projections. // For the object itself, simply strip casts. - V = ForUnderlyingObject ? getUnderlyingObject(V) : stripCasts(V); + v = forUnderlyingObject ? getUnderlyingObject(v) : stripCasts(v); - if (isa(V) || isa(V)) { - if (ResultType && ResultType != V->getType()) + if (isa(v) || isa(v)) { + if (resultType && resultType != v->getType()) return SILType(); - ResultType = V->getType(); + resultType = v->getType(); continue; } - if (isa(V)) { - if (ResultType && ResultType != V->getType()) + if (isa(v)) { + if (resultType && resultType != v->getType()) return SILType(); - ResultType = V->getType(); + resultType = v->getType(); continue; } - if (isa(V) || isa(V) || isa(V)) { - if (ResultType && ResultType != V->getType()) + if (isa(v) || isa(v) || isa(v)) { + if (resultType && resultType != v->getType()) return SILType(); - ResultType = V->getType(); + resultType = v->getType(); continue; } - if (ForUnderlyingObject) { - if (isa(V)) { - if (ResultType && ResultType != V->getType()) + if (forUnderlyingObject) { + if (isa(v)) { + if (resultType && resultType != v->getType()) return SILType(); - ResultType = V->getType(); + resultType = v->getType(); continue; } } - auto Arg = dyn_cast(V); - if (!Arg) { + auto arg = dyn_cast(v); + if (!arg) { // We don't know what it is. return SILType(); } - if (auto *FArg = dyn_cast(Arg)) { + if (auto *fArg = dyn_cast(arg)) { // Bail on metatypes for now. - if (FArg->getType().is()) { + if (fArg->getType().is()) { return SILType(); } - auto *CD = FArg->getType().getClassOrBoundGenericClass(); + auto *cd = fArg->getType().getClassOrBoundGenericClass(); // If it is not class and it is a trivial type, then it // should be the exact type. - if (!CD && FArg->getType().isTrivial(*F)) { - if (ResultType && ResultType != FArg->getType()) + if (!cd && fArg->getType().isTrivial(*f)) { + if (resultType && resultType != fArg->getType()) return SILType(); - ResultType = FArg->getType(); + resultType = fArg->getType(); continue; } - if (!CD) { + if (!cd) { // It is not a class or a trivial type, so we don't know what it is. return SILType(); } // Check if this class is effectively final. - if (!isKnownFinalClass(CD, M, CHA)) { + if (!isKnownFinalClass(cd, module, cha)) { return SILType(); } - if (ResultType && ResultType != FArg->getType()) + if (resultType && resultType != fArg->getType()) return SILType(); - ResultType = FArg->getType(); + resultType = fArg->getType(); continue; } - auto *SinglePred = Arg->getParent()->getSinglePredecessorBlock(); - if (SinglePred) { + auto *singlePred = arg->getParent()->getSinglePredecessorBlock(); + if (singlePred) { // If it is a BB argument received on a success branch // of a checked_cast_br, then we know its exact type. - auto *CCBI = dyn_cast(SinglePred->getTerminator()); - if (CCBI && CCBI->isExact() && CCBI->getSuccessBB() == Arg->getParent()) { - if (ResultType && ResultType != Arg->getType()) + auto *ccbi = dyn_cast(singlePred->getTerminator()); + if (ccbi && ccbi->isExact() && ccbi->getSuccessBB() == arg->getParent()) { + if (resultType && resultType != arg->getType()) return SILType(); - ResultType = Arg->getType(); + resultType = arg->getType(); continue; } } // It is a BB argument, look through incoming values. If they all have the // same exact type, then we consider it to be the type of the BB argument. - SmallVector IncomingValues; - if (Arg->getSingleTerminatorOperands(IncomingValues)) { - for (auto InValue : IncomingValues) { - WorkList.push_back(InValue); + SmallVector incomingValues; + if (arg->getSingleTerminatorOperands(incomingValues)) { + for (auto inValue : incomingValues) { + worklist.push_back(inValue); } continue; } @@ -392,27 +387,24 @@ SILType swift::getExactDynamicType(SILValue S, return SILType(); } - return ResultType; + return resultType; } - /// Try to determine the exact dynamic type of the underlying object. /// returns the exact dynamic type of a value, or an empty type if the exact /// type could not be determined. SILType -swift::getExactDynamicTypeOfUnderlyingObject(SILValue S, - ClassHierarchyAnalysis *CHA) { - return getExactDynamicType(S, CHA, /* ForUnderlyingObject */ true); +swift::getExactDynamicTypeOfUnderlyingObject(SILValue instance, + ClassHierarchyAnalysis *cha) { + return getExactDynamicType(instance, cha, /* forUnderlyingObject */ true); } // Start with the substitutions from the apply. // Try to propagate them to find out the real substitutions required // to invoke the method. static SubstitutionMap -getSubstitutionsForCallee(SILModule &M, - CanSILFunctionType baseCalleeType, - CanType derivedSelfType, - FullApplySite AI) { +getSubstitutionsForCallee(SILModule &module, CanSILFunctionType baseCalleeType, + CanType derivedSelfType, FullApplySite applySite) { // If the base method is not polymorphic, no substitutions are required, // even if we originally had substitutions for calling the derived method. @@ -439,12 +431,13 @@ getSubstitutionsForCallee(SILModule &M, if (auto metatypeType = derivedClass->getAs()) derivedClass = metatypeType->getInstanceType(); baseSubMap = derivedClass->getContextSubstitutionMap( - M.getSwiftModule(), baseClassDecl); + module.getSwiftModule(), baseClassDecl); } - SubstitutionMap origSubMap = AI.getSubstitutionMap(); + SubstitutionMap origSubMap = applySite.getSubstitutionMap(); - Type calleeSelfType = AI.getOrigCalleeType()->getSelfParameter().getType(); + Type calleeSelfType = + applySite.getOrigCalleeType()->getSelfParameter().getType(); if (auto metatypeType = calleeSelfType->getAs()) calleeSelfType = metatypeType->getInstanceType(); auto *calleeClassDecl = calleeSelfType->getClassOrBoundGenericClass(); @@ -467,264 +460,260 @@ getSubstitutionsForCallee(SILModule &M, baseCalleeSig); } -static ApplyInst *replaceApplyInst(SILBuilder &B, SILLocation Loc, - ApplyInst *OldAI, - SILValue NewFn, - SubstitutionMap NewSubs, - ArrayRef NewArgs, - ArrayRef NewArgBorrows) { - auto *NewAI = B.createApply(Loc, NewFn, NewSubs, NewArgs, - OldAI->isNonThrowing()); +static ApplyInst *replaceApplyInst(SILBuilder &builder, SILLocation loc, + ApplyInst *oldAI, SILValue newFn, + SubstitutionMap newSubs, + ArrayRef newArgs, + ArrayRef newArgBorrows) { + auto *newAI = + builder.createApply(loc, newFn, newSubs, newArgs, oldAI->isNonThrowing()); - if (!NewArgBorrows.empty()) { - for (SILValue Arg : NewArgBorrows) { - B.createEndBorrow(Loc, Arg); + if (!newArgBorrows.empty()) { + for (SILValue arg : newArgBorrows) { + builder.createEndBorrow(loc, arg); } } // Check if any casting is required for the return value. - SILValue ResultValue = - castValueToABICompatibleType(&B, Loc, NewAI, NewAI->getType(), - OldAI->getType()); + SILValue resultValue = castValueToABICompatibleType( + &builder, loc, newAI, newAI->getType(), oldAI->getType()); - OldAI->replaceAllUsesWith(ResultValue); - return NewAI; + oldAI->replaceAllUsesWith(resultValue); + return newAI; } -static TryApplyInst *replaceTryApplyInst(SILBuilder &B, SILLocation Loc, - TryApplyInst *OldTAI, SILValue NewFn, - SubstitutionMap NewSubs, - ArrayRef NewArgs, - SILFunctionConventions Conv, - ArrayRef NewArgBorrows) { - SILBasicBlock *NormalBB = OldTAI->getNormalBB(); - SILBasicBlock *ResultBB = nullptr; +static TryApplyInst *replaceTryApplyInst(SILBuilder &builder, SILLocation loc, + TryApplyInst *oldTAI, SILValue newFn, + SubstitutionMap newSubs, + ArrayRef newArgs, + SILFunctionConventions conv, + ArrayRef newArgBorrows) { + SILBasicBlock *normalBB = oldTAI->getNormalBB(); + SILBasicBlock *resultBB = nullptr; - SILType NewResultTy = Conv.getSILResultType(); + SILType newResultTy = conv.getSILResultType(); // Does the result value need to be casted? - auto OldResultTy = NormalBB->getArgument(0)->getType(); - bool ResultCastRequired = NewResultTy != OldResultTy; + auto oldResultTy = normalBB->getArgument(0)->getType(); + bool resultCastRequired = newResultTy != oldResultTy; // Create a new normal BB only if the result of the new apply differs // in type from the argument of the original normal BB. - if (!ResultCastRequired) { - ResultBB = NormalBB; + if (!resultCastRequired) { + resultBB = normalBB; } else { - ResultBB = B.getFunction().createBasicBlockBefore(NormalBB); - ResultBB->createPhiArgument(NewResultTy, ValueOwnershipKind::Owned); + resultBB = builder.getFunction().createBasicBlockBefore(normalBB); + resultBB->createPhiArgument(newResultTy, ValueOwnershipKind::Owned); } // We can always just use the original error BB because we'll be // deleting the edge to it from the old TAI. - SILBasicBlock *ErrorBB = OldTAI->getErrorBB(); + SILBasicBlock *errorBB = oldTAI->getErrorBB(); // Insert a try_apply here. // Note that this makes this block temporarily double-terminated! // We won't fix that until deleteDevirtualizedApply. - auto NewTAI = B.createTryApply(Loc, NewFn, NewSubs, NewArgs, - ResultBB, ErrorBB); + auto newTAI = + builder.createTryApply(loc, newFn, newSubs, newArgs, resultBB, errorBB); - if (!NewArgBorrows.empty()) { - B.setInsertionPoint(NormalBB->begin()); - for (SILValue Arg : NewArgBorrows) { - B.createEndBorrow(Loc, Arg); + if (!newArgBorrows.empty()) { + builder.setInsertionPoint(normalBB->begin()); + for (SILValue arg : newArgBorrows) { + builder.createEndBorrow(loc, arg); } - B.setInsertionPoint(ErrorBB->begin()); - for (SILValue Arg : NewArgBorrows) { - B.createEndBorrow(Loc, Arg); + builder.setInsertionPoint(errorBB->begin()); + for (SILValue arg : newArgBorrows) { + builder.createEndBorrow(loc, arg); } } - if (ResultCastRequired) { - B.setInsertionPoint(ResultBB); + if (resultCastRequired) { + builder.setInsertionPoint(resultBB); - SILValue ResultValue = ResultBB->getArgument(0); - ResultValue = castValueToABICompatibleType(&B, Loc, ResultValue, - NewResultTy, OldResultTy); - B.createBranch(Loc, NormalBB, { ResultValue }); + SILValue resultValue = resultBB->getArgument(0); + resultValue = castValueToABICompatibleType(&builder, loc, resultValue, + newResultTy, oldResultTy); + builder.createBranch(loc, normalBB, {resultValue}); } - B.setInsertionPoint(NormalBB->begin()); - return NewTAI; + builder.setInsertionPoint(normalBB->begin()); + return newTAI; } -static BeginApplyInst *replaceBeginApplyInst(SILBuilder &B, SILLocation Loc, - BeginApplyInst *OldBAI, - SILValue NewFn, - SubstitutionMap NewSubs, - ArrayRef NewArgs, - ArrayRef NewArgBorrows) { - auto *NewBAI = - B.createBeginApply(Loc, NewFn, NewSubs, NewArgs, OldBAI->isNonThrowing()); +static BeginApplyInst * +replaceBeginApplyInst(SILBuilder &builder, SILLocation loc, + BeginApplyInst *oldBAI, SILValue newFn, + SubstitutionMap newSubs, ArrayRef newArgs, + ArrayRef newArgBorrows) { + auto *newBAI = builder.createBeginApply(loc, newFn, newSubs, newArgs, + oldBAI->isNonThrowing()); // Forward the token. - OldBAI->getTokenResult()->replaceAllUsesWith(NewBAI->getTokenResult()); + oldBAI->getTokenResult()->replaceAllUsesWith(newBAI->getTokenResult()); - auto OldYields = OldBAI->getYieldedValues(); - auto NewYields = NewBAI->getYieldedValues(); - assert(OldYields.size() == NewYields.size()); + auto oldYields = oldBAI->getYieldedValues(); + auto newYields = newBAI->getYieldedValues(); + assert(oldYields.size() == newYields.size()); - for (auto i : indices(OldYields)) { - auto OldYield = OldYields[i]; - auto NewYield = NewYields[i]; - NewYield = castValueToABICompatibleType(&B, Loc, NewYield, - NewYield->getType(), - OldYield->getType()); - OldYield->replaceAllUsesWith(NewYield); + for (auto i : indices(oldYields)) { + auto oldYield = oldYields[i]; + auto newYield = newYields[i]; + newYield = castValueToABICompatibleType( + &builder, loc, newYield, newYield->getType(), oldYield->getType()); + oldYield->replaceAllUsesWith(newYield); } - if (NewArgBorrows.empty()) - return NewBAI; + if (newArgBorrows.empty()) + return newBAI; - SILValue token = NewBAI->getTokenResult(); + SILValue token = newBAI->getTokenResult(); // The token will only be used by end_apply and abort_apply. Use that to // insert the end_borrows we need. for (auto *use : token->getUses()) { - SILBuilderWithScope builder(use->getUser(), B.getBuilderContext()); - for (SILValue borrow : NewArgBorrows) { - builder.createEndBorrow(Loc, borrow); + SILBuilderWithScope borrowBuilder(use->getUser(), + builder.getBuilderContext()); + for (SILValue borrow : newArgBorrows) { + borrowBuilder.createEndBorrow(loc, borrow); } } - return NewBAI; + return newBAI; } -static PartialApplyInst *replacePartialApplyInst(SILBuilder &B, SILLocation Loc, - PartialApplyInst *OldPAI, - SILValue NewFn, - SubstitutionMap NewSubs, - ArrayRef NewArgs) { - auto Convention = - OldPAI->getType().getAs()->getCalleeConvention(); - auto *NewPAI = B.createPartialApply(Loc, NewFn, NewSubs, NewArgs, - Convention); +static PartialApplyInst * +replacePartialApplyInst(SILBuilder &builder, SILLocation loc, + PartialApplyInst *oldPAI, SILValue newFn, + SubstitutionMap newSubs, ArrayRef newArgs) { + auto convention = + oldPAI->getType().getAs()->getCalleeConvention(); + auto *newPAI = + builder.createPartialApply(loc, newFn, newSubs, newArgs, convention); // Check if any casting is required for the partially-applied function. - SILValue ResultValue = castValueToABICompatibleType( - &B, Loc, NewPAI, NewPAI->getType(), OldPAI->getType()); - OldPAI->replaceAllUsesWith(ResultValue); + SILValue resultValue = castValueToABICompatibleType( + &builder, loc, newPAI, newPAI->getType(), oldPAI->getType()); + oldPAI->replaceAllUsesWith(resultValue); - return NewPAI; + return newPAI; } -static ApplySite replaceApplySite(SILBuilder &B, SILLocation Loc, - ApplySite OldAS, SILValue NewFn, - SubstitutionMap NewSubs, - ArrayRef NewArgs, - SILFunctionConventions Conv, - ArrayRef NewArgBorrows) { - switch (OldAS.getKind()) { +static ApplySite replaceApplySite(SILBuilder &builder, SILLocation loc, + ApplySite oldAS, SILValue newFn, + SubstitutionMap newSubs, + ArrayRef newArgs, + SILFunctionConventions conv, + ArrayRef newArgBorrows) { + switch (oldAS.getKind()) { case ApplySiteKind::ApplyInst: { - auto *OldAI = cast(OldAS); - return replaceApplyInst(B, Loc, OldAI, NewFn, NewSubs, NewArgs, NewArgBorrows); + auto *oldAI = cast(oldAS); + return replaceApplyInst(builder, loc, oldAI, newFn, newSubs, newArgs, + newArgBorrows); } case ApplySiteKind::TryApplyInst: { - auto *OldTAI = cast(OldAS); - return replaceTryApplyInst(B, Loc, OldTAI, NewFn, NewSubs, NewArgs, Conv, - NewArgBorrows); + auto *oldTAI = cast(oldAS); + return replaceTryApplyInst(builder, loc, oldTAI, newFn, newSubs, newArgs, + conv, newArgBorrows); } case ApplySiteKind::BeginApplyInst: { - auto *OldBAI = dyn_cast(OldAS); - return replaceBeginApplyInst(B, Loc, OldBAI, NewFn, NewSubs, NewArgs, - NewArgBorrows); + auto *oldBAI = dyn_cast(oldAS); + return replaceBeginApplyInst(builder, loc, oldBAI, newFn, newSubs, newArgs, + newArgBorrows); } case ApplySiteKind::PartialApplyInst: { - assert(NewArgBorrows.empty()); - auto *OldPAI = cast(OldAS); - return replacePartialApplyInst(B, Loc, OldPAI, NewFn, NewSubs, NewArgs); + assert(newArgBorrows.empty()); + auto *oldPAI = cast(oldAS); + return replacePartialApplyInst(builder, loc, oldPAI, newFn, newSubs, + newArgs); } } llvm_unreachable("covered switch"); } /// Delete an apply site that's been successfully devirtualized. -void swift::deleteDevirtualizedApply(ApplySite Old) { - auto *OldApply = Old.getInstruction(); - recursivelyDeleteTriviallyDeadInstructions(OldApply, true); +void swift::deleteDevirtualizedApply(ApplySite old) { + auto *oldApply = old.getInstruction(); + recursivelyDeleteTriviallyDeadInstructions(oldApply, true); } -SILFunction *swift::getTargetClassMethod(SILModule &M, - ClassDecl *CD, - MethodInst *MI) { - assert((isa(MI) || isa(MI)) && - "Only class_method and super_method instructions are supported"); +SILFunction *swift::getTargetClassMethod(SILModule &module, ClassDecl *cd, + MethodInst *mi) { + assert((isa(mi) || isa(mi)) + && "Only class_method and super_method instructions are supported"); - SILDeclRef Member = MI->getMember(); - return M.lookUpFunctionInVTable(CD, Member); + SILDeclRef member = mi->getMember(); + return module.lookUpFunctionInVTable(cd, member); } -CanType swift::getSelfInstanceType(CanType ClassOrMetatypeType) { - if (auto MetaType = dyn_cast(ClassOrMetatypeType)) - ClassOrMetatypeType = MetaType.getInstanceType(); +CanType swift::getSelfInstanceType(CanType classOrMetatypeType) { + if (auto metaType = dyn_cast(classOrMetatypeType)) + classOrMetatypeType = metaType.getInstanceType(); - if (auto SelfType = dyn_cast(ClassOrMetatypeType)) - ClassOrMetatypeType = SelfType.getSelfType(); - - return ClassOrMetatypeType; + if (auto selfType = dyn_cast(classOrMetatypeType)) + classOrMetatypeType = selfType.getSelfType(); + + return classOrMetatypeType; } /// Check if it is possible to devirtualize an Apply instruction /// and a class member obtained using the class_method instruction into /// a direct call to a specific member of a specific class. /// -/// \p AI is the apply to devirtualize. -/// \p CD is the class declaration we are devirtualizing for. +/// \p applySite is the apply to devirtualize. +/// \p cd is the class declaration we are devirtualizing for. /// return true if it is possible to devirtualize, false - otherwise. -bool swift::canDevirtualizeClassMethod(FullApplySite AI, - ClassDecl *CD, - OptRemark::Emitter *ORE, +bool swift::canDevirtualizeClassMethod(FullApplySite applySite, ClassDecl *cd, + OptRemark::Emitter *ore, bool isEffectivelyFinalMethod) { LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize : " - << *AI.getInstruction()); + << *applySite.getInstruction()); - SILModule &Mod = AI.getModule(); + SILModule &module = applySite.getModule(); - auto *MI = cast(AI.getCallee()); + auto *mi = cast(applySite.getCallee()); // Find the implementation of the member which should be invoked. - auto *F = getTargetClassMethod(Mod, CD, MI); + auto *f = getTargetClassMethod(module, cd, mi); // If we do not find any such function, we have no function to devirtualize // to... so bail. - if (!F) { + if (!f) { LLVM_DEBUG(llvm::dbgs() << " FAIL: Could not find matching VTable " "or vtable method for this class.\n"); return false; } // We need to disable the “effectively final” opt if a function is inlinable - if (isEffectivelyFinalMethod && AI.getFunction()->isSerialized()) { + if (isEffectivelyFinalMethod && applySite.getFunction()->isSerialized()) { LLVM_DEBUG(llvm::dbgs() << " FAIL: Could not optimize function " "because it is an effectively-final inlinable: " - << AI.getFunction()->getName() << "\n"); + << applySite.getFunction()->getName() << "\n"); return false; } // Mandatory inlining does class method devirtualization. I'm not sure if this // is really needed, but some test rely on this. // So even for Onone functions we have to do it if the SILStage is raw. - if (F->getModule().getStage() != SILStage::Raw && !F->shouldOptimize()) { + if (f->getModule().getStage() != SILStage::Raw && !f->shouldOptimize()) { // Do not consider functions that should not be optimized. - LLVM_DEBUG(llvm::dbgs() << " FAIL: Could not optimize function " - << " because it is marked no-opt: " << F->getName() - << "\n"); + LLVM_DEBUG(llvm::dbgs() + << " FAIL: Could not optimize function " + << " because it is marked no-opt: " << f->getName() << "\n"); return false; } - if (AI.getFunction()->isSerialized()) { + if (applySite.getFunction()->isSerialized()) { // function_ref inside fragile function cannot reference a private or // hidden symbol. - if (!F->hasValidLinkageForFragileRef()) + if (!f->hasValidLinkageForFragileRef()) return false; } // devirtualizeClassMethod below does not support this case. It currently // assumes it can try_apply call the target. - if (!F->getLoweredFunctionType()->hasErrorResult() && - isa(AI.getInstruction())) { + if (!f->getLoweredFunctionType()->hasErrorResult() + && isa(applySite.getInstruction())) { LLVM_DEBUG(llvm::dbgs() << " FAIL: Trying to devirtualize a " "try_apply but vtable entry has no error result.\n"); return false; @@ -735,102 +724,100 @@ bool swift::canDevirtualizeClassMethod(FullApplySite AI, /// Devirtualize an apply of a class method. /// -/// \p AI is the apply to devirtualize. +/// \p applySite is the apply to devirtualize. /// \p ClassOrMetatype is a class value or metatype value that is the /// self argument of the apply we will devirtualize. /// return the result value of the new ApplyInst if created one or null. -FullApplySite swift::devirtualizeClassMethod(FullApplySite AI, - SILValue ClassOrMetatype, - ClassDecl *CD, - OptRemark::Emitter *ORE) { +FullApplySite swift::devirtualizeClassMethod(FullApplySite applySite, + SILValue classOrMetatype, + ClassDecl *cd, + OptRemark::Emitter *ore) { LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize : " - << *AI.getInstruction()); + << *applySite.getInstruction()); - SILModule &Mod = AI.getModule(); - auto *MI = cast(AI.getCallee()); + SILModule &module = applySite.getModule(); + auto *mi = cast(applySite.getCallee()); - auto *F = getTargetClassMethod(Mod, CD, MI); + auto *f = getTargetClassMethod(module, cd, mi); - CanSILFunctionType GenCalleeType = F->getLoweredFunctionType(); + CanSILFunctionType genCalleeType = f->getLoweredFunctionType(); - SubstitutionMap Subs = - getSubstitutionsForCallee(Mod, GenCalleeType, - ClassOrMetatype->getType().getASTType(), - AI); - CanSILFunctionType SubstCalleeType = GenCalleeType; - if (GenCalleeType->isPolymorphic()) - SubstCalleeType = GenCalleeType->substGenericArgs(Mod, Subs); - SILFunctionConventions substConv(SubstCalleeType, Mod); + SubstitutionMap subs = getSubstitutionsForCallee( + module, genCalleeType, classOrMetatype->getType().getASTType(), + applySite); + CanSILFunctionType substCalleeType = genCalleeType; + if (genCalleeType->isPolymorphic()) + substCalleeType = genCalleeType->substGenericArgs(module, subs); + SILFunctionConventions substConv(substCalleeType, module); - SILBuilderWithScope B(AI.getInstruction()); - SILLocation Loc = AI.getLoc(); - auto *FRI = B.createFunctionRefFor(Loc, F); + SILBuilderWithScope builder(applySite.getInstruction()); + SILLocation loc = applySite.getLoc(); + auto *fri = builder.createFunctionRefFor(loc, f); // Create the argument list for the new apply, casting when needed // in order to handle covariant indirect return types and // contravariant argument types. - SmallVector NewArgs; + SmallVector newArgs; // If we have a value that is owned, but that we are going to use in as a // guaranteed argument, we need to borrow/unborrow the argument. Otherwise, we // will introduce new consuming uses. In contrast, if we have an owned value, // we are ok due to the forwarding nature of upcasts. - SmallVector NewArgBorrows; + SmallVector newArgBorrows; - auto IndirectResultArgIter = AI.getIndirectSILResults().begin(); - for (auto ResultTy : substConv.getIndirectSILResultTypes()) { - NewArgs.push_back( - castValueToABICompatibleType(&B, Loc, *IndirectResultArgIter, - IndirectResultArgIter->getType(), ResultTy)); - ++IndirectResultArgIter; + auto indirectResultArgIter = applySite.getIndirectSILResults().begin(); + for (auto resultTy : substConv.getIndirectSILResultTypes()) { + newArgs.push_back(castValueToABICompatibleType( + &builder, loc, *indirectResultArgIter, indirectResultArgIter->getType(), + resultTy)); + ++indirectResultArgIter; } - auto ParamArgIter = AI.getArgumentsWithoutIndirectResults().begin(); + auto paramArgIter = applySite.getArgumentsWithoutIndirectResults().begin(); // Skip the last parameter, which is `self`. Add it below. for (auto param : substConv.getParameters()) { auto paramType = substConv.getSILType(param); - SILValue arg = *ParamArgIter; - if (B.hasOwnership() - && arg->getType().isObject() + SILValue arg = *paramArgIter; + if (builder.hasOwnership() && arg->getType().isObject() && arg.getOwnershipKind() == ValueOwnershipKind::Owned && param.isGuaranteed()) { - SILBuilderWithScope builder(AI.getInstruction(), B); - arg = builder.createBeginBorrow(Loc, arg); - NewArgBorrows.push_back(arg); + SILBuilderWithScope borrowBuilder(applySite.getInstruction(), builder); + arg = borrowBuilder.createBeginBorrow(loc, arg); + newArgBorrows.push_back(arg); } - arg = castValueToABICompatibleType(&B, Loc, arg, ParamArgIter->getType(), - paramType); - NewArgs.push_back(arg); - ++ParamArgIter; + arg = castValueToABICompatibleType(&builder, loc, arg, + paramArgIter->getType(), paramType); + newArgs.push_back(arg); + ++paramArgIter; } - ApplySite NewAS = replaceApplySite(B, Loc, AI, FRI, Subs, NewArgs, substConv, - NewArgBorrows); - FullApplySite NewAI = FullApplySite::isa(NewAS.getInstruction()); - assert(NewAI); + ApplySite newAS = replaceApplySite(builder, loc, applySite, fri, subs, + newArgs, substConv, newArgBorrows); + FullApplySite newAI = FullApplySite::isa(newAS.getInstruction()); + assert(newAI); - LLVM_DEBUG(llvm::dbgs() << " SUCCESS: " << F->getName() << "\n"); - if (ORE) - ORE->emit([&]() { - using namespace OptRemark; - return RemarkPassed("ClassMethodDevirtualized", *AI.getInstruction()) - << "Devirtualized call to class method " << NV("Method", F); - }); + LLVM_DEBUG(llvm::dbgs() << " SUCCESS: " << f->getName() << "\n"); + if (ore) + ore->emit([&]() { + using namespace OptRemark; + return RemarkPassed("ClassMethodDevirtualized", + *applySite.getInstruction()) + << "Devirtualized call to class method " << NV("Method", f); + }); NumClassDevirt++; - return NewAI; + return newAI; } -FullApplySite -swift::tryDevirtualizeClassMethod(FullApplySite AI, SILValue ClassInstance, - ClassDecl *CD, - OptRemark::Emitter *ORE, - bool isEffectivelyFinalMethod) { - if (!canDevirtualizeClassMethod(AI, CD, ORE, isEffectivelyFinalMethod)) +FullApplySite swift::tryDevirtualizeClassMethod(FullApplySite applySite, + SILValue classInstance, + ClassDecl *cd, + OptRemark::Emitter *ore, + bool isEffectivelyFinalMethod) { + if (!canDevirtualizeClassMethod(applySite, cd, ore, isEffectivelyFinalMethod)) return FullApplySite(); - return devirtualizeClassMethod(AI, ClassInstance, CD, ORE); + return devirtualizeClassMethod(applySite, classInstance, cd, ore); } - //===----------------------------------------------------------------------===// // Witness Method Optimization //===----------------------------------------------------------------------===// @@ -944,24 +931,24 @@ getWitnessMethodSubstitutions( } SubstitutionMap -swift::getWitnessMethodSubstitutions(SILModule &Module, ApplySite AI, - SILFunction *F, - ProtocolConformanceRef CRef) { - auto witnessFnTy = F->getLoweredFunctionType(); +swift::getWitnessMethodSubstitutions(SILModule &module, ApplySite applySite, + SILFunction *f, + ProtocolConformanceRef cRef) { + auto witnessFnTy = f->getLoweredFunctionType(); assert(witnessFnTy->getRepresentation() == SILFunctionTypeRepresentation::WitnessMethod); - auto requirementSig = AI.getOrigCalleeType()->getGenericSignature(); + auto requirementSig = applySite.getOrigCalleeType()->getGenericSignature(); auto witnessThunkSig = witnessFnTy->getGenericSignature(); - SubstitutionMap origSubs = AI.getSubstitutionMap(); + SubstitutionMap origSubs = applySite.getSubstitutionMap(); - auto *mod = Module.getSwiftModule(); + auto *mod = module.getSwiftModule(); bool isSelfAbstract = witnessFnTy->getSelfInstanceType()->is(); auto *classWitness = witnessFnTy->getWitnessMethodClass(); - return ::getWitnessMethodSubstitutions(mod, CRef, requirementSig, + return ::getWitnessMethodSubstitutions(mod, cRef, requirementSig, witnessThunkSig, origSubs, isSelfAbstract, classWitness); } @@ -969,97 +956,99 @@ swift::getWitnessMethodSubstitutions(SILModule &Module, ApplySite AI, /// Generate a new apply of a function_ref to replace an apply of a /// witness_method when we've determined the actual function we'll end /// up calling. -static ApplySite -devirtualizeWitnessMethod(ApplySite AI, SILFunction *F, - ProtocolConformanceRef C, OptRemark::Emitter *ORE) { +static ApplySite devirtualizeWitnessMethod(ApplySite applySite, SILFunction *f, + ProtocolConformanceRef cRef, + OptRemark::Emitter *ore) { // We know the witness thunk and the corresponding set of substitutions // required to invoke the protocol method at this point. - auto &Module = AI.getModule(); + auto &module = applySite.getModule(); // Collect all the required substitutions. // // The complete set of substitutions may be different, e.g. because the found - // witness thunk F may have been created by a specialization pass and have + // witness thunk f may have been created by a specialization pass and have // additional generic parameters. - auto SubMap = getWitnessMethodSubstitutions(Module, AI, F, C); + auto subMap = getWitnessMethodSubstitutions(module, applySite, f, cRef); // Figure out the exact bound type of the function to be called by // applying all substitutions. - auto CalleeCanType = F->getLoweredFunctionType(); - auto SubstCalleeCanType = CalleeCanType->substGenericArgs(Module, SubMap); + auto calleeCanType = f->getLoweredFunctionType(); + auto substCalleeCanType = calleeCanType->substGenericArgs(module, subMap); // Collect arguments from the apply instruction. - SmallVector Arguments; - SmallVector BorrowedArgs; + SmallVector arguments; + SmallVector borrowedArgs; // Iterate over the non self arguments and add them to the // new argument list, upcasting when required. - SILBuilderWithScope B(AI.getInstruction()); - SILFunctionConventions substConv(SubstCalleeCanType, Module); - unsigned substArgIdx = AI.getCalleeArgIndexOfFirstAppliedArg(); - for (auto arg : AI.getArguments()) { + SILBuilderWithScope argBuilder(applySite.getInstruction()); + SILFunctionConventions substConv(substCalleeCanType, module); + unsigned substArgIdx = applySite.getCalleeArgIndexOfFirstAppliedArg(); + for (auto arg : applySite.getArguments()) { auto paramInfo = substConv.getSILArgumentConvention(substArgIdx); auto paramType = substConv.getSILArgumentType(substArgIdx++); if (arg->getType() != paramType) { - if (B.hasOwnership() - && AI.getKind() != ApplySiteKind::PartialApplyInst + if (argBuilder.hasOwnership() + && applySite.getKind() != ApplySiteKind::PartialApplyInst && arg->getType().isObject() && arg.getOwnershipKind() == ValueOwnershipKind::Owned && paramInfo.isGuaranteedConvention()) { - SILBuilderWithScope builder(AI.getInstruction(), B); - arg = builder.createBeginBorrow(AI.getLoc(), arg); - BorrowedArgs.push_back(arg); + SILBuilderWithScope borrowBuilder(applySite.getInstruction(), + argBuilder); + arg = borrowBuilder.createBeginBorrow(applySite.getLoc(), arg); + borrowedArgs.push_back(arg); } - arg = castValueToABICompatibleType(&B, AI.getLoc(), arg, + arg = castValueToABICompatibleType(&argBuilder, applySite.getLoc(), arg, arg->getType(), paramType); } - Arguments.push_back(arg); + arguments.push_back(arg); } assert(substArgIdx == substConv.getNumSILArguments()); // Replace old apply instruction by a new apply instruction that invokes // the witness thunk. - SILBuilderWithScope Builder(AI.getInstruction()); - SILLocation Loc = AI.getLoc(); - auto *FRI = Builder.createFunctionRefFor(Loc, F); + SILBuilderWithScope applyBuilder(applySite.getInstruction()); + SILLocation loc = applySite.getLoc(); + auto *fri = applyBuilder.createFunctionRefFor(loc, f); - ApplySite SAI = replaceApplySite(Builder, Loc, AI, FRI, SubMap, Arguments, - substConv, BorrowedArgs); + ApplySite newApplySite = + replaceApplySite(applyBuilder, loc, applySite, fri, subMap, arguments, + substConv, borrowedArgs); - if (ORE) - ORE->emit([&]() { - using namespace OptRemark; - return RemarkPassed("WitnessMethodDevirtualized", *AI.getInstruction()) - << "Devirtualized call to " << NV("Method", F); - }); + if (ore) + ore->emit([&]() { + using namespace OptRemark; + return RemarkPassed("WitnessMethodDevirtualized", + *applySite.getInstruction()) + << "Devirtualized call to " << NV("Method", f); + }); NumWitnessDevirt++; - return SAI; + return newApplySite; } -static bool canDevirtualizeWitnessMethod(ApplySite AI) { - SILFunction *F; - SILWitnessTable *WT; +static bool canDevirtualizeWitnessMethod(ApplySite applySite) { + SILFunction *f; + SILWitnessTable *wt; - auto *WMI = cast(AI.getCallee()); + auto *wmi = cast(applySite.getCallee()); - std::tie(F, WT) = - AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(), - WMI->getMember()); + std::tie(f, wt) = applySite.getModule().lookUpFunctionInWitnessTable( + wmi->getConformance(), wmi->getMember()); - if (!F) + if (!f) return false; - if (AI.getFunction()->isSerialized()) { + if (applySite.getFunction()->isSerialized()) { // function_ref inside fragile function cannot reference a private or // hidden symbol. - if (!F->hasValidLinkageForFragileRef()) + if (!f->hasValidLinkageForFragileRef()) return false; } // devirtualizeWitnessMethod below does not support this case. It currently // assumes it can try_apply call the target. - if (!F->getLoweredFunctionType()->hasErrorResult() && - isa(AI.getInstruction())) { + if (!f->getLoweredFunctionType()->hasErrorResult() + && isa(applySite.getInstruction())) { LLVM_DEBUG(llvm::dbgs() << " FAIL: Trying to devirtualize a " "try_apply but wtable entry has no error result.\n"); return false; @@ -1071,21 +1060,20 @@ static bool canDevirtualizeWitnessMethod(ApplySite AI) { /// In the cases where we can statically determine the function that /// we'll call to, replace an apply of a witness_method with an apply /// of a function_ref, returning the new apply. -ApplySite -swift::tryDevirtualizeWitnessMethod(ApplySite AI, OptRemark::Emitter *ORE) { - if (!canDevirtualizeWitnessMethod(AI)) +ApplySite swift::tryDevirtualizeWitnessMethod(ApplySite applySite, + OptRemark::Emitter *ore) { + if (!canDevirtualizeWitnessMethod(applySite)) return ApplySite(); - SILFunction *F; - SILWitnessTable *WT; + SILFunction *f; + SILWitnessTable *wt; - auto *WMI = cast(AI.getCallee()); + auto *wmi = cast(applySite.getCallee()); - std::tie(F, WT) = - AI.getModule().lookUpFunctionInWitnessTable(WMI->getConformance(), - WMI->getMember()); + std::tie(f, wt) = applySite.getModule().lookUpFunctionInWitnessTable( + wmi->getConformance(), wmi->getMember()); - return devirtualizeWitnessMethod(AI, F, WMI->getConformance(), ORE); + return devirtualizeWitnessMethod(applySite, f, wmi->getConformance(), ore); } //===----------------------------------------------------------------------===// @@ -1094,23 +1082,23 @@ swift::tryDevirtualizeWitnessMethod(ApplySite AI, OptRemark::Emitter *ORE) { /// Attempt to devirtualize the given apply if possible, and return a /// new instruction in that case, or nullptr otherwise. -ApplySite swift::tryDevirtualizeApply(ApplySite AI, - ClassHierarchyAnalysis *CHA, - OptRemark::Emitter *ORE) { +ApplySite swift::tryDevirtualizeApply(ApplySite applySite, + ClassHierarchyAnalysis *cha, + OptRemark::Emitter *ore) { LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize: " - << *AI.getInstruction()); + << *applySite.getInstruction()); // Devirtualize apply instructions that call witness_method instructions: // // %8 = witness_method $Optional, #LogicValue.boolValue!getter.1 // %9 = apply %8(%6#1) : ... // - if (isa(AI.getCallee())) - return tryDevirtualizeWitnessMethod(AI, ORE); + if (isa(applySite.getCallee())) + return tryDevirtualizeWitnessMethod(applySite, ore); // TODO: check if we can also de-virtualize partial applies of class methods. - FullApplySite FAS = FullApplySite::isa(AI.getInstruction()); - if (!FAS) + FullApplySite fas = FullApplySite::isa(applySite.getInstruction()); + if (!fas) return ApplySite(); /// Optimize a class_method and alloc_ref pair into a direct function @@ -1129,48 +1117,49 @@ ApplySite swift::tryDevirtualizeApply(ApplySite AI, /// into /// /// %YY = function_ref @... - if (auto *CMI = dyn_cast(FAS.getCallee())) { - auto Instance = stripUpCasts(CMI->getOperand()); - auto ClassType = getSelfInstanceType(Instance->getType().getASTType()); - auto *CD = ClassType.getClassOrBoundGenericClass(); + if (auto *cmi = dyn_cast(fas.getCallee())) { + auto instance = stripUpCasts(cmi->getOperand()); + auto classType = getSelfInstanceType(instance->getType().getASTType()); + auto *cd = classType.getClassOrBoundGenericClass(); - if (isEffectivelyFinalMethod(FAS, ClassType, CD, CHA)) - return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE, + if (isEffectivelyFinalMethod(fas, classType, cd, cha)) + return tryDevirtualizeClassMethod(fas, instance, cd, ore, true /*isEffectivelyFinalMethod*/); // Try to check if the exact dynamic type of the instance is statically // known. - if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CHA)) - return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE); + if (auto instance = getInstanceWithExactDynamicType(cmi->getOperand(), cha)) + return tryDevirtualizeClassMethod(fas, instance, cd, ore); - if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CHA)) { - if (ExactTy == CMI->getOperand()->getType()) - return tryDevirtualizeClassMethod(FAS, CMI->getOperand(), CD, ORE); + if (auto exactTy = getExactDynamicType(cmi->getOperand(), cha)) { + if (exactTy == cmi->getOperand()->getType()) + return tryDevirtualizeClassMethod(fas, cmi->getOperand(), cd, ore); } } - if (isa(FAS.getCallee())) { - auto Instance = FAS.getArguments().back(); - auto ClassType = getSelfInstanceType(Instance->getType().getASTType()); - auto *CD = ClassType.getClassOrBoundGenericClass(); + if (isa(fas.getCallee())) { + auto instance = fas.getArguments().back(); + auto classType = getSelfInstanceType(instance->getType().getASTType()); + auto *cd = classType.getClassOrBoundGenericClass(); - return tryDevirtualizeClassMethod(FAS, Instance, CD, ORE); + return tryDevirtualizeClassMethod(fas, instance, cd, ore); } return ApplySite(); } -bool swift::canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA) { +bool swift::canDevirtualizeApply(FullApplySite applySite, + ClassHierarchyAnalysis *cha) { LLVM_DEBUG(llvm::dbgs() << " Trying to devirtualize: " - << *AI.getInstruction()); + << *applySite.getInstruction()); // Devirtualize apply instructions that call witness_method instructions: // // %8 = witness_method $Optional, #LogicValue.boolValue!getter.1 // %9 = apply %8(%6#1) : ... // - if (isa(AI.getCallee())) - return canDevirtualizeWitnessMethod(AI); + if (isa(applySite.getCallee())) + return canDevirtualizeWitnessMethod(applySite); /// Optimize a class_method and alloc_ref pair into a direct function /// reference: @@ -1188,33 +1177,32 @@ bool swift::canDevirtualizeApply(FullApplySite AI, ClassHierarchyAnalysis *CHA) /// into /// /// %YY = function_ref @... - if (auto *CMI = dyn_cast(AI.getCallee())) { - auto Instance = stripUpCasts(CMI->getOperand()); - auto ClassType = getSelfInstanceType(Instance->getType().getASTType()); - auto *CD = ClassType.getClassOrBoundGenericClass(); + if (auto *cmi = dyn_cast(applySite.getCallee())) { + auto instance = stripUpCasts(cmi->getOperand()); + auto classType = getSelfInstanceType(instance->getType().getASTType()); + auto *cd = classType.getClassOrBoundGenericClass(); - if (isEffectivelyFinalMethod(AI, ClassType, CD, CHA)) - return canDevirtualizeClassMethod(AI, CD, - nullptr /*ORE*/, + if (isEffectivelyFinalMethod(applySite, classType, cd, cha)) + return canDevirtualizeClassMethod(applySite, cd, nullptr /*ore*/, true /*isEffectivelyFinalMethod*/); // Try to check if the exact dynamic type of the instance is statically // known. - if (auto Instance = getInstanceWithExactDynamicType(CMI->getOperand(), CHA)) - return canDevirtualizeClassMethod(AI, CD); + if (auto instance = getInstanceWithExactDynamicType(cmi->getOperand(), cha)) + return canDevirtualizeClassMethod(applySite, cd); - if (auto ExactTy = getExactDynamicType(CMI->getOperand(), CHA)) { - if (ExactTy == CMI->getOperand()->getType()) - return canDevirtualizeClassMethod(AI, CD); + if (auto exactTy = getExactDynamicType(cmi->getOperand(), cha)) { + if (exactTy == cmi->getOperand()->getType()) + return canDevirtualizeClassMethod(applySite, cd); } } - if (isa(AI.getCallee())) { - auto Instance = AI.getArguments().back(); - auto ClassType = getSelfInstanceType(Instance->getType().getASTType()); - auto *CD = ClassType.getClassOrBoundGenericClass(); + if (isa(applySite.getCallee())) { + auto instance = applySite.getArguments().back(); + auto classType = getSelfInstanceType(instance->getType().getASTType()); + auto *cd = classType.getClassOrBoundGenericClass(); - return canDevirtualizeClassMethod(AI, CD); + return canDevirtualizeClassMethod(applySite, cd); } return false; diff --git a/lib/SILOptimizer/Utils/InstOptUtils.cpp b/lib/SILOptimizer/Utils/InstOptUtils.cpp index c5677537e07..7d6e490078d 100644 --- a/lib/SILOptimizer/Utils/InstOptUtils.cpp +++ b/lib/SILOptimizer/Utils/InstOptUtils.cpp @@ -43,94 +43,98 @@ static llvm::cl::opt EnableExpandAll("enable-expand-all", /// creates a strong_retain if \p Ptr has reference semantics itself or a /// retain_value if \p Ptr is a non-trivial value without reference-semantics. NullablePtr -swift::createIncrementBefore(SILValue Ptr, SILInstruction *InsertPt) { +swift::createIncrementBefore(SILValue ptr, SILInstruction *insertPt) { // Set up the builder we use to insert at our insertion point. - SILBuilder B(InsertPt); - auto Loc = RegularLocation::getAutoGeneratedLocation(); + SILBuilder builder(insertPt); + auto loc = RegularLocation::getAutoGeneratedLocation(); // If we have a trivial type, just bail, there is no work to do. - if (Ptr->getType().isTrivial(B.getFunction())) + if (ptr->getType().isTrivial(builder.getFunction())) return nullptr; // If Ptr is refcounted itself, create the strong_retain and // return. - if (Ptr->getType().isReferenceCounted(B.getModule())) { - if (Ptr->getType().is()) - return B.createUnownedRetain(Loc, Ptr, B.getDefaultAtomicity()); + if (ptr->getType().isReferenceCounted(builder.getModule())) { + if (ptr->getType().is()) + return builder.createUnownedRetain(loc, ptr, + builder.getDefaultAtomicity()); else - return B.createStrongRetain(Loc, Ptr, B.getDefaultAtomicity()); + return builder.createStrongRetain(loc, ptr, + builder.getDefaultAtomicity()); } // Otherwise, create the retain_value. - return B.createRetainValue(Loc, Ptr, B.getDefaultAtomicity()); + return builder.createRetainValue(loc, ptr, builder.getDefaultAtomicity()); } -/// Creates a decrement on \p Ptr before insertion point \p InsertPt that -/// creates a strong_release if \p Ptr has reference semantics itself or -/// a release_value if \p Ptr is a non-trivial value without +/// Creates a decrement on \p ptr before insertion point \p InsertPt that +/// creates a strong_release if \p ptr has reference semantics itself or +/// a release_value if \p ptr is a non-trivial value without /// reference-semantics. NullablePtr -swift::createDecrementBefore(SILValue Ptr, SILInstruction *InsertPt) { +swift::createDecrementBefore(SILValue ptr, SILInstruction *insertPt) { // Setup the builder we will use to insert at our insertion point. - SILBuilder B(InsertPt); - auto Loc = RegularLocation::getAutoGeneratedLocation(); + SILBuilder builder(insertPt); + auto loc = RegularLocation::getAutoGeneratedLocation(); - if (Ptr->getType().isTrivial(B.getFunction())) + if (ptr->getType().isTrivial(builder.getFunction())) return nullptr; - // If Ptr has reference semantics itself, create a strong_release. - if (Ptr->getType().isReferenceCounted(B.getModule())) { - if (Ptr->getType().is()) - return B.createUnownedRelease(Loc, Ptr, B.getDefaultAtomicity()); + // If ptr has reference semantics itself, create a strong_release. + if (ptr->getType().isReferenceCounted(builder.getModule())) { + if (ptr->getType().is()) + return builder.createUnownedRelease(loc, ptr, + builder.getDefaultAtomicity()); else - return B.createStrongRelease(Loc, Ptr, B.getDefaultAtomicity()); + return builder.createStrongRelease(loc, ptr, + builder.getDefaultAtomicity()); } // Otherwise create a release value. - return B.createReleaseValue(Loc, Ptr, B.getDefaultAtomicity()); + return builder.createReleaseValue(loc, ptr, builder.getDefaultAtomicity()); } /// Perform a fast local check to see if the instruction is dead. /// /// This routine only examines the state of the instruction at hand. -bool swift::isInstructionTriviallyDead(SILInstruction *I) { +bool swift::isInstructionTriviallyDead(SILInstruction *inst) { // At Onone, consider all uses, including the debug_info. // This way, debug_info is preserved at Onone. - if (I->hasUsesOfAnyResult() - && I->getFunction()->getEffectiveOptimizationMode() + if (inst->hasUsesOfAnyResult() + && inst->getFunction()->getEffectiveOptimizationMode() <= OptimizationMode::NoOptimization) return false; - if (!onlyHaveDebugUsesOfAllResults(I) || isa(I)) + if (!onlyHaveDebugUsesOfAllResults(inst) || isa(inst)) return false; - if (auto *BI = dyn_cast(I)) { + if (auto *bi = dyn_cast(inst)) { // Although the onFastPath builtin has no side-effects we don't want to // remove it. - if (BI->getBuiltinInfo().ID == BuiltinValueKind::OnFastPath) + if (bi->getBuiltinInfo().ID == BuiltinValueKind::OnFastPath) return false; - return !BI->mayHaveSideEffects(); + return !bi->mayHaveSideEffects(); } // condfail instructions that obviously can't fail are dead. - if (auto *CFI = dyn_cast(I)) - if (auto *ILI = dyn_cast(CFI->getOperand())) - if (!ILI->getValue()) + if (auto *cfi = dyn_cast(inst)) + if (auto *ili = dyn_cast(cfi->getOperand())) + if (!ili->getValue()) return true; // mark_uninitialized is never dead. - if (isa(I)) + if (isa(inst)) return false; - if (isa(I) || isa(I)) + if (isa(inst) || isa(inst)) return false; // These invalidate enums so "write" memory, but that is not an essential // operation so we can remove these if they are trivially dead. - if (isa(I)) + if (isa(inst)) return true; - if (!I->mayHaveSideEffects()) + if (!inst->mayHaveSideEffects()) return true; return false; @@ -138,28 +142,28 @@ bool swift::isInstructionTriviallyDead(SILInstruction *I) { /// Return true if this is a release instruction and the released value /// is a part of a guaranteed parameter. -bool swift::isIntermediateRelease(SILInstruction *I, - EpilogueARCFunctionInfo *EAFI) { +bool swift::isIntermediateRelease(SILInstruction *inst, + EpilogueARCFunctionInfo *eafi) { // Check whether this is a release instruction. - if (!isa(I) && !isa(I)) + if (!isa(inst) && !isa(inst)) return false; // OK. we have a release instruction. // Check whether this is a release on part of a guaranteed function argument. - SILValue Op = stripValueProjections(I->getOperand(0)); - auto *Arg = dyn_cast(Op); - if (!Arg) + SILValue Op = stripValueProjections(inst->getOperand(0)); + auto *arg = dyn_cast(Op); + if (!arg) return false; // This is a release on a guaranteed parameter. Its not the final release. - if (Arg->hasConvention(SILArgumentConvention::Direct_Guaranteed)) + if (arg->hasConvention(SILArgumentConvention::Direct_Guaranteed)) return true; // This is a release on an owned parameter and its not the epilogue release. // Its not the final release. - auto Rel = EAFI->computeEpilogueARCInstructions( - EpilogueARCContext::EpilogueARCKind::Release, Arg); - if (Rel.size() && !Rel.count(I)) + auto rel = eafi->computeEpilogueARCInstructions( + EpilogueARCContext::EpilogueARCKind::Release, arg); + if (rel.size() && !rel.count(inst)) return true; // Failed to prove anything. @@ -171,146 +175,147 @@ using CallbackTy = llvm::function_ref; } // end anonymous namespace void swift::recursivelyDeleteTriviallyDeadInstructions( - ArrayRef IA, bool Force, CallbackTy Callback) { + ArrayRef ia, bool force, CallbackTy callback) { // Delete these instruction and others that become dead after it's deleted. - llvm::SmallPtrSet DeadInsts; - for (auto I : IA) { + llvm::SmallPtrSet deadInsts; + for (auto *inst : ia) { // If the instruction is not dead and force is false, do nothing. - if (Force || isInstructionTriviallyDead(I)) - DeadInsts.insert(I); + if (force || isInstructionTriviallyDead(inst)) + deadInsts.insert(inst); } - llvm::SmallPtrSet NextInsts; - while (!DeadInsts.empty()) { - for (auto I : DeadInsts) { + llvm::SmallPtrSet nextInsts; + while (!deadInsts.empty()) { + for (auto inst : deadInsts) { // Call the callback before we mutate the to be deleted instruction in any // way. - Callback(I); + callback(inst); // Check if any of the operands will become dead as well. - MutableArrayRef Ops = I->getAllOperands(); - for (Operand &Op : Ops) { - SILValue OpVal = Op.get(); - if (!OpVal) + MutableArrayRef operands = inst->getAllOperands(); + for (Operand &operand : operands) { + SILValue operandVal = operand.get(); + if (!operandVal) continue; // Remove the reference from the instruction being deleted to this // operand. - Op.drop(); + operand.drop(); // If the operand is an instruction that is only used by the instruction // being deleted, delete it. - if (auto *OpValInst = OpVal->getDefiningInstruction()) - if (!DeadInsts.count(OpValInst) - && isInstructionTriviallyDead(OpValInst)) - NextInsts.insert(OpValInst); + if (auto *operandValInst = operandVal->getDefiningInstruction()) + if (!deadInsts.count(operandValInst) + && isInstructionTriviallyDead(operandValInst)) + nextInsts.insert(operandValInst); } // If we have a function ref inst, we need to especially drop its function // argument so that it gets a proper ref decrement. - auto *FRI = dyn_cast(I); - if (FRI && FRI->getInitiallyReferencedFunction()) - FRI->dropReferencedFunction(); + auto *fri = dyn_cast(inst); + if (fri && fri->getInitiallyReferencedFunction()) + fri->dropReferencedFunction(); - auto *DFRI = dyn_cast(I); - if (DFRI && DFRI->getInitiallyReferencedFunction()) - DFRI->dropReferencedFunction(); + auto *dfri = dyn_cast(inst); + if (dfri && dfri->getInitiallyReferencedFunction()) + dfri->dropReferencedFunction(); - auto *PFRI = dyn_cast(I); - if (PFRI && PFRI->getInitiallyReferencedFunction()) - PFRI->dropReferencedFunction(); + auto *pfri = dyn_cast(inst); + if (pfri && pfri->getInitiallyReferencedFunction()) + pfri->dropReferencedFunction(); } - for (auto I : DeadInsts) { + for (auto inst : deadInsts) { // This will remove this instruction and all its uses. - eraseFromParentWithDebugInsts(I, Callback); + eraseFromParentWithDebugInsts(inst, callback); } - NextInsts.swap(DeadInsts); - NextInsts.clear(); + nextInsts.swap(deadInsts); + nextInsts.clear(); } } /// If the given instruction is dead, delete it along with its dead /// operands. /// -/// \param I The instruction to be deleted. -/// \param Force If Force is set, don't check if the top level instruction is +/// \param inst The instruction to be deleted. +/// \param force If force is set, don't check if the top level instruction is /// considered dead - delete it regardless. -void swift::recursivelyDeleteTriviallyDeadInstructions(SILInstruction *I, - bool Force, - CallbackTy Callback) { - ArrayRef AI = ArrayRef(I); - recursivelyDeleteTriviallyDeadInstructions(AI, Force, Callback); +void swift::recursivelyDeleteTriviallyDeadInstructions(SILInstruction *inst, + bool force, + CallbackTy callback) { + ArrayRef ai = ArrayRef(inst); + recursivelyDeleteTriviallyDeadInstructions(ai, force, callback); } -void swift::eraseUsesOfInstruction(SILInstruction *Inst, CallbackTy Callback) { - for (auto result : Inst->getResults()) { +void swift::eraseUsesOfInstruction(SILInstruction *inst, CallbackTy callback) { + for (auto result : inst->getResults()) { while (!result->use_empty()) { - auto UI = result->use_begin(); - auto *User = UI->getUser(); - assert(User && "User should never be NULL!"); + auto ui = result->use_begin(); + auto *user = ui->getUser(); + assert(user && "User should never be NULL!"); // If the instruction itself has any uses, recursively zap them so that // nothing uses this instruction. - eraseUsesOfInstruction(User, Callback); + eraseUsesOfInstruction(user, callback); // Walk through the operand list and delete any random instructions that // will become trivially dead when this instruction is removed. - for (auto &Op : User->getAllOperands()) { - if (auto *OpI = Op.get()->getDefiningInstruction()) { + for (auto &operand : user->getAllOperands()) { + if (auto *operandI = operand.get()->getDefiningInstruction()) { // Don't recursively delete the instruction we're working on. // FIXME: what if we're being recursively invoked? - if (OpI != Inst) { - Op.drop(); - recursivelyDeleteTriviallyDeadInstructions(OpI, false, Callback); + if (operandI != inst) { + operand.drop(); + recursivelyDeleteTriviallyDeadInstructions(operandI, false, + callback); } } } - Callback(User); - User->eraseFromParent(); + callback(user); + user->eraseFromParent(); } } } -void swift::collectUsesOfValue(SILValue V, - llvm::SmallPtrSetImpl &Insts) { - for (auto UI = V->use_begin(), E = V->use_end(); UI != E; UI++) { - auto *User = UI->getUser(); +void swift::collectUsesOfValue(SILValue v, + llvm::SmallPtrSetImpl &insts) { + for (auto ui = v->use_begin(), E = v->use_end(); ui != E; ui++) { + auto *user = ui->getUser(); // Instruction has been processed. - if (!Insts.insert(User).second) + if (!insts.insert(user).second) continue; // Collect the users of this instruction. - for (auto result : User->getResults()) - collectUsesOfValue(result, Insts); + for (auto result : user->getResults()) + collectUsesOfValue(result, insts); } } -void swift::eraseUsesOfValue(SILValue V) { - llvm::SmallPtrSet Insts; +void swift::eraseUsesOfValue(SILValue v) { + llvm::SmallPtrSet insts; // Collect the uses. - collectUsesOfValue(V, Insts); + collectUsesOfValue(v, insts); // Erase the uses, we can have instructions that become dead because // of the removal of these instructions, leave to DCE to cleanup. // Its not safe to do recursively delete here as some of the SILInstruction // maybe tracked by this set. - for (auto I : Insts) { - I->replaceAllUsesOfAllResultsWithUndef(); - I->eraseFromParent(); + for (auto inst : insts) { + inst->replaceAllUsesOfAllResultsWithUndef(); + inst->eraseFromParent(); } } // Devirtualization of functions with covariant return types produces // a result that is not an apply, but takes an apply as an // argument. Attempt to dig the apply out from this result. -FullApplySite swift::findApplyFromDevirtualizedResult(SILValue V) { - if (auto Apply = FullApplySite::isa(V)) +FullApplySite swift::findApplyFromDevirtualizedResult(SILValue v) { + if (auto Apply = FullApplySite::isa(v)) return Apply; - if (isa(V) || isa(V) || isa(V)) + if (isa(v) || isa(v) || isa(v)) return findApplyFromDevirtualizedResult( - cast(V)->getOperand(0)); + cast(v)->getOperand(0)); return FullApplySite(); } @@ -319,29 +324,29 @@ bool swift::mayBindDynamicSelf(SILFunction *F) { if (!F->hasSelfMetadataParam()) return false; - SILValue MDArg = F->getSelfMetadataArgument(); + SILValue mdArg = F->getSelfMetadataArgument(); - for (Operand *MDUse : F->getSelfMetadataArgument()->getUses()) { - SILInstruction *MDUser = MDUse->getUser(); - for (Operand &TypeDepOp : MDUser->getTypeDependentOperands()) { - if (TypeDepOp.get() == MDArg) + for (Operand *mdUse : F->getSelfMetadataArgument()->getUses()) { + SILInstruction *mdUser = mdUse->getUser(); + for (Operand &typeDepOp : mdUser->getTypeDependentOperands()) { + if (typeDepOp.get() == mdArg) return true; } } return false; } -static SILValue skipAddrProjections(SILValue V) { +static SILValue skipAddrProjections(SILValue v) { for (;;) { - switch (V->getKind()) { + switch (v->getKind()) { case ValueKind::IndexAddrInst: case ValueKind::IndexRawPointerInst: case ValueKind::StructElementAddrInst: case ValueKind::TupleElementAddrInst: - V = cast(V)->getOperand(0); + v = cast(v)->getOperand(0); break; default: - return V; + return v; } } llvm_unreachable("there is no escape from an infinite loop"); @@ -350,14 +355,14 @@ static SILValue skipAddrProjections(SILValue V) { /// Check whether the \p addr is an address of a tail-allocated array element. bool swift::isAddressOfArrayElement(SILValue addr) { addr = stripAddressProjections(addr); - if (auto *MD = dyn_cast(addr)) - addr = stripAddressProjections(MD->getValue()); + if (auto *md = dyn_cast(addr)) + addr = stripAddressProjections(md->getValue()); // High-level SIL: check for an get_element_address array semantics call. - if (auto *PtrToAddr = dyn_cast(addr)) - if (auto *SEI = dyn_cast(PtrToAddr->getOperand())) { - ArraySemanticsCall Call(SEI->getOperand()); - if (Call && Call.getKind() == ArrayCallKind::kGetElementAddress) + if (auto *ptrToAddr = dyn_cast(addr)) + if (auto *sei = dyn_cast(ptrToAddr->getOperand())) { + ArraySemanticsCall call(sei->getOperand()); + if (call && call.getKind() == ArrayCallKind::kGetElementAddress) return true; } @@ -370,66 +375,66 @@ bool swift::isAddressOfArrayElement(SILValue addr) { /// Find a new position for an ApplyInst's FuncRef so that it dominates its /// use. Not that FunctionRefInsts may be shared by multiple ApplyInsts. -void swift::placeFuncRef(ApplyInst *AI, DominanceInfo *DT) { - FunctionRefInst *FuncRef = cast(AI->getCallee()); - SILBasicBlock *DomBB = - DT->findNearestCommonDominator(AI->getParent(), FuncRef->getParent()); - if (DomBB == AI->getParent() && DomBB != FuncRef->getParent()) +void swift::placeFuncRef(ApplyInst *ai, DominanceInfo *domInfo) { + FunctionRefInst *funcRef = cast(ai->getCallee()); + SILBasicBlock *domBB = domInfo->findNearestCommonDominator( + ai->getParent(), funcRef->getParent()); + if (domBB == ai->getParent() && domBB != funcRef->getParent()) // Prefer to place the FuncRef immediately before the call. Since we're // moving FuncRef up, this must be the only call to it in the block. - FuncRef->moveBefore(AI); + funcRef->moveBefore(ai); else // Otherwise, conservatively stick it at the beginning of the block. - FuncRef->moveBefore(&*DomBB->begin()); + funcRef->moveBefore(&*domBB->begin()); } /// Add an argument, \p val, to the branch-edge that is pointing into /// block \p Dest. Return a new instruction and do not erase the old /// instruction. -TermInst *swift::addArgumentToBranch(SILValue Val, SILBasicBlock *Dest, - TermInst *Branch) { - SILBuilderWithScope Builder(Branch); +TermInst *swift::addArgumentToBranch(SILValue val, SILBasicBlock *dest, + TermInst *branch) { + SILBuilderWithScope builder(branch); - if (auto *CBI = dyn_cast(Branch)) { - SmallVector TrueArgs; - SmallVector FalseArgs; + if (auto *cbi = dyn_cast(branch)) { + SmallVector trueArgs; + SmallVector falseArgs; - for (auto A : CBI->getTrueArgs()) - TrueArgs.push_back(A); + for (auto arg : cbi->getTrueArgs()) + trueArgs.push_back(arg); - for (auto A : CBI->getFalseArgs()) - FalseArgs.push_back(A); + for (auto arg : cbi->getFalseArgs()) + falseArgs.push_back(arg); - if (Dest == CBI->getTrueBB()) { - TrueArgs.push_back(Val); - assert(TrueArgs.size() == Dest->getNumArguments()); + if (dest == cbi->getTrueBB()) { + trueArgs.push_back(val); + assert(trueArgs.size() == dest->getNumArguments()); } else { - FalseArgs.push_back(Val); - assert(FalseArgs.size() == Dest->getNumArguments()); + falseArgs.push_back(val); + assert(falseArgs.size() == dest->getNumArguments()); } - return Builder.createCondBranch( - CBI->getLoc(), CBI->getCondition(), CBI->getTrueBB(), TrueArgs, - CBI->getFalseBB(), FalseArgs, CBI->getTrueBBCount(), - CBI->getFalseBBCount()); + return builder.createCondBranch( + cbi->getLoc(), cbi->getCondition(), cbi->getTrueBB(), trueArgs, + cbi->getFalseBB(), falseArgs, cbi->getTrueBBCount(), + cbi->getFalseBBCount()); } - if (auto *BI = dyn_cast(Branch)) { - SmallVector Args; + if (auto *bi = dyn_cast(branch)) { + SmallVector args; - for (auto A : BI->getArgs()) - Args.push_back(A); + for (auto arg : bi->getArgs()) + args.push_back(arg); - Args.push_back(Val); - assert(Args.size() == Dest->getNumArguments()); - return Builder.createBranch(BI->getLoc(), BI->getDestBB(), Args); + args.push_back(val); + assert(args.size() == dest->getNumArguments()); + return builder.createBranch(bi->getLoc(), bi->getDestBB(), args); } llvm_unreachable("unsupported terminator"); } -SILLinkage swift::getSpecializedLinkage(SILFunction *F, SILLinkage L) { - if (hasPrivateVisibility(L) && !F->isSerialized()) { +SILLinkage swift::getSpecializedLinkage(SILFunction *f, SILLinkage linkage) { + if (hasPrivateVisibility(linkage) && !f->isSerialized()) { // Specializations of private symbols should remain so, unless // they were serialized, which can only happen when specializing // definitions from a standard library built with -sil-serialize-all. @@ -459,160 +464,162 @@ SILLinkage swift::getSpecializedLinkage(SILFunction *F, SILLinkage L) { /// /// NOTE: The implementation of this function is very closely related to the /// rules checked by SILVerifier::requireABICompatibleFunctionTypes. -SILValue swift::castValueToABICompatibleType(SILBuilder *B, SILLocation Loc, - SILValue Value, SILType SrcTy, - SILType DestTy) { +SILValue swift::castValueToABICompatibleType(SILBuilder *builder, + SILLocation loc, SILValue value, + SILType srcTy, SILType destTy) { // No cast is required if types are the same. - if (SrcTy == DestTy) - return Value; + if (srcTy == destTy) + return value; - assert(SrcTy.isAddress() == DestTy.isAddress() + assert(srcTy.isAddress() == destTy.isAddress() && "Addresses aren't compatible with values"); - if (SrcTy.isAddress() && DestTy.isAddress()) { + if (srcTy.isAddress() && destTy.isAddress()) { // Cast between two addresses and that's it. - return B->createUncheckedAddrCast(Loc, Value, DestTy); + return builder->createUncheckedAddrCast(loc, value, destTy); } // If both types are classes and dest is the superclass of src, // simply perform an upcast. - if (DestTy.isExactSuperclassOf(SrcTy)) { - return B->createUpcast(Loc, Value, DestTy); + if (destTy.isExactSuperclassOf(srcTy)) { + return builder->createUpcast(loc, value, destTy); } - if (SrcTy.isHeapObjectReferenceType() && DestTy.isHeapObjectReferenceType()) { - return B->createUncheckedRefCast(Loc, Value, DestTy); + if (srcTy.isHeapObjectReferenceType() && destTy.isHeapObjectReferenceType()) { + return builder->createUncheckedRefCast(loc, value, destTy); } - if (auto mt1 = SrcTy.getAs()) { - if (auto mt2 = DestTy.getAs()) { + if (auto mt1 = srcTy.getAs()) { + if (auto mt2 = destTy.getAs()) { if (mt1->getRepresentation() == mt2->getRepresentation()) { - // If B.Type needs to be casted to A.Type and - // A is a superclass of B, then it can be done by means + // If builder.Type needs to be casted to A.Type and + // A is a superclass of builder, then it can be done by means // of a simple upcast. if (mt2.getInstanceType()->isExactSuperclassOf(mt1.getInstanceType())) { - return B->createUpcast(Loc, Value, DestTy); + return builder->createUpcast(loc, value, destTy); } // Cast between two metatypes and that's it. - return B->createUncheckedBitCast(Loc, Value, DestTy); + return builder->createUncheckedBitCast(loc, value, destTy); } } } // Check if src and dest types are optional. - auto OptionalSrcTy = SrcTy.getOptionalObjectType(); - auto OptionalDestTy = DestTy.getOptionalObjectType(); + auto optionalSrcTy = srcTy.getOptionalObjectType(); + auto optionalDestTy = destTy.getOptionalObjectType(); // Both types are optional. - if (OptionalDestTy && OptionalSrcTy) { + if (optionalDestTy && optionalSrcTy) { // If both wrapped types are classes and dest is the superclass of src, // simply perform an upcast. - if (OptionalDestTy.isExactSuperclassOf(OptionalSrcTy)) { + if (optionalDestTy.isExactSuperclassOf(optionalSrcTy)) { // Insert upcast. - return B->createUpcast(Loc, Value, DestTy); + return builder->createUpcast(loc, value, destTy); } // Unwrap the original optional value. - auto *SomeDecl = B->getASTContext().getOptionalSomeDecl(); - auto *NoneBB = B->getFunction().createBasicBlock(); - auto *SomeBB = B->getFunction().createBasicBlock(); - auto *CurBB = B->getInsertionPoint()->getParent(); + auto *someDecl = builder->getASTContext().getOptionalSomeDecl(); + auto *noneBB = builder->getFunction().createBasicBlock(); + auto *someBB = builder->getFunction().createBasicBlock(); + auto *curBB = builder->getInsertionPoint()->getParent(); - auto *ContBB = CurBB->split(B->getInsertionPoint()); - ContBB->createPhiArgument(DestTy, ValueOwnershipKind::Owned); + auto *contBB = curBB->split(builder->getInsertionPoint()); + contBB->createPhiArgument(destTy, ValueOwnershipKind::Owned); - SmallVector, 1> CaseBBs; - CaseBBs.push_back(std::make_pair(SomeDecl, SomeBB)); - B->setInsertionPoint(CurBB); - B->createSwitchEnum(Loc, Value, NoneBB, CaseBBs); + SmallVector, 1> caseBBs; + caseBBs.push_back(std::make_pair(someDecl, someBB)); + builder->setInsertionPoint(curBB); + builder->createSwitchEnum(loc, value, noneBB, caseBBs); // Handle the Some case. - B->setInsertionPoint(SomeBB); - SILValue UnwrappedValue = B->createUncheckedEnumData(Loc, Value, SomeDecl); + builder->setInsertionPoint(someBB); + SILValue unwrappedValue = + builder->createUncheckedEnumData(loc, value, someDecl); // Cast the unwrapped value. - auto CastedUnwrappedValue = castValueToABICompatibleType( - B, Loc, UnwrappedValue, OptionalSrcTy, OptionalDestTy); + auto castedUnwrappedValue = castValueToABICompatibleType( + builder, loc, unwrappedValue, optionalSrcTy, optionalDestTy); // Wrap into optional. - auto CastedValue = B->createOptionalSome(Loc, CastedUnwrappedValue, DestTy); - B->createBranch(Loc, ContBB, {CastedValue}); + auto castedValue = + builder->createOptionalSome(loc, castedUnwrappedValue, destTy); + builder->createBranch(loc, contBB, {castedValue}); // Handle the None case. - B->setInsertionPoint(NoneBB); - CastedValue = B->createOptionalNone(Loc, DestTy); - B->createBranch(Loc, ContBB, {CastedValue}); - B->setInsertionPoint(ContBB->begin()); + builder->setInsertionPoint(noneBB); + castedValue = builder->createOptionalNone(loc, destTy); + builder->createBranch(loc, contBB, {castedValue}); + builder->setInsertionPoint(contBB->begin()); - return ContBB->getArgument(0); + return contBB->getArgument(0); } // Src is not optional, but dest is optional. - if (!OptionalSrcTy && OptionalDestTy) { - auto OptionalSrcCanTy = - OptionalType::get(SrcTy.getASTType())->getCanonicalType(); - auto LoweredOptionalSrcType = - SILType::getPrimitiveObjectType(OptionalSrcCanTy); + if (!optionalSrcTy && optionalDestTy) { + auto optionalSrcCanTy = + OptionalType::get(srcTy.getASTType())->getCanonicalType(); + auto loweredOptionalSrcType = + SILType::getPrimitiveObjectType(optionalSrcCanTy); // Wrap the source value into an optional first. - SILValue WrappedValue = - B->createOptionalSome(Loc, Value, LoweredOptionalSrcType); + SILValue wrappedValue = + builder->createOptionalSome(loc, value, loweredOptionalSrcType); // Cast the wrapped value. - return castValueToABICompatibleType(B, Loc, WrappedValue, - WrappedValue->getType(), DestTy); + return castValueToABICompatibleType(builder, loc, wrappedValue, + wrappedValue->getType(), destTy); } // Handle tuple types. // Extract elements, cast each of them, create a new tuple. - if (auto SrcTupleTy = SrcTy.getAs()) { - SmallVector ExpectedTuple; - for (unsigned i = 0, e = SrcTupleTy->getNumElements(); i < e; i++) { - SILValue Element = B->createTupleExtract(Loc, Value, i); + if (auto srcTupleTy = srcTy.getAs()) { + SmallVector expectedTuple; + for (unsigned i = 0, e = srcTupleTy->getNumElements(); i < e; i++) { + SILValue element = builder->createTupleExtract(loc, value, i); // Cast the value if necessary. - Element = castValueToABICompatibleType(B, Loc, Element, - SrcTy.getTupleElementType(i), - DestTy.getTupleElementType(i)); - ExpectedTuple.push_back(Element); + element = castValueToABICompatibleType(builder, loc, element, + srcTy.getTupleElementType(i), + destTy.getTupleElementType(i)); + expectedTuple.push_back(element); } - return B->createTuple(Loc, DestTy, ExpectedTuple); + return builder->createTuple(loc, destTy, expectedTuple); } // Function types are interchangeable if they're also ABI-compatible. - if (SrcTy.is()) { - if (DestTy.is()) { - assert(SrcTy.getAs()->isNoEscape() - == DestTy.getAs()->isNoEscape() - || SrcTy.getAs()->getRepresentation() + if (srcTy.is()) { + if (destTy.is()) { + assert(srcTy.getAs()->isNoEscape() + == destTy.getAs()->isNoEscape() + || srcTy.getAs()->getRepresentation() != SILFunctionType::Representation::Thick && "Swift thick functions that differ in escapeness are " "not ABI " "compatible"); // Insert convert_function. - return B->createConvertFunction(Loc, Value, DestTy, - /*WithoutActuallyEscaping=*/false); + return builder->createConvertFunction(loc, value, destTy, + /*WithoutActuallyEscaping=*/false); } } - llvm::errs() << "Source type: " << SrcTy << "\n"; - llvm::errs() << "Destination type: " << DestTy << "\n"; + llvm::errs() << "Source type: " << srcTy << "\n"; + llvm::errs() << "Destination type: " << destTy << "\n"; llvm_unreachable("Unknown combination of types for casting"); } -ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *ABI, - unsigned Index) { - SILBasicBlock::iterator Iter(ABI); - Iter++; - assert(Iter != ABI->getParent()->end() +ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *abi, + unsigned index) { + SILBasicBlock::iterator iter(abi); + iter++; + assert(iter != abi->getParent()->end() && "alloc_box cannot be the last instruction of a block"); - SILInstruction *NextInst = &*Iter; - if (auto *PBI = dyn_cast(NextInst)) { - if (PBI->getOperand() == ABI && PBI->getFieldIndex() == Index) - return PBI; + SILInstruction *nextInst = &*iter; + if (auto *pbi = dyn_cast(nextInst)) { + if (pbi->getOperand() == abi && pbi->getFieldIndex() == index) + return pbi; } - SILBuilder B(NextInst); - return B.createProjectBox(ABI->getLoc(), ABI, Index); + SILBuilder builder(nextInst); + return builder.createProjectBox(abi->getLoc(), abi, index); } // Peek through trivial Enum initialization, typically for pointless @@ -629,15 +636,15 @@ ProjectBoxInst *swift::getOrCreateProjectBox(AllocBoxInst *ABI, // dealloc_stack %stack_adr // (No other uses of %stack_adr.) InitEnumDataAddrInst * -swift::findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *UTEDAI) { - auto *ASI = dyn_cast(UTEDAI->getOperand()); - if (!ASI) +swift::findInitAddressForTrivialEnum(UncheckedTakeEnumDataAddrInst *utedai) { + auto *asi = dyn_cast(utedai->getOperand()); + if (!asi) return nullptr; SILInstruction *singleUser = nullptr; - for (auto use : ASI->getUses()) { + for (auto use : asi->getUses()) { auto *user = use->getUser(); - if (user == UTEDAI) + if (user == utedai) continue; // As long as there's only one UncheckedTakeEnumDataAddrInst and one @@ -669,25 +676,25 @@ namespace { /// concatenation. class StringConcatenationOptimizer { /// Apply instruction being optimized. - ApplyInst *AI; + ApplyInst *ai; /// Builder to be used for creation of new instructions. - SILBuilder &Builder; + SILBuilder &builder; /// Left string literal operand of a string concatenation. - StringLiteralInst *SLILeft = nullptr; + StringLiteralInst *sliLeft = nullptr; /// Right string literal operand of a string concatenation. - StringLiteralInst *SLIRight = nullptr; + StringLiteralInst *sliRight = nullptr; /// Function used to construct the left string literal. - FunctionRefInst *FRILeft = nullptr; + FunctionRefInst *friLeft = nullptr; /// Function used to construct the right string literal. - FunctionRefInst *FRIRight = nullptr; + FunctionRefInst *friRight = nullptr; /// Apply instructions used to construct left string literal. - ApplyInst *AILeft = nullptr; + ApplyInst *aiLeft = nullptr; /// Apply instructions used to construct right string literal. - ApplyInst *AIRight = nullptr; + ApplyInst *aiRight = nullptr; /// String literal conversion function to be used. - FunctionRefInst *FRIConvertFromBuiltin = nullptr; + FunctionRefInst *friConvertFromBuiltin = nullptr; /// Result type of a function producing the concatenated string literal. - SILValue FuncResultType; + SILValue funcResultType; /// Internal helper methods bool extractStringConcatOperands(); @@ -696,8 +703,8 @@ class StringConcatenationOptimizer { bool isAscii() const; public: - StringConcatenationOptimizer(ApplyInst *AI, SILBuilder &Builder) - : AI(AI), Builder(Builder) {} + StringConcatenationOptimizer(ApplyInst *ai, SILBuilder &builder) + : ai(ai), builder(builder) {} /// Tries to optimize a given apply instruction if it is a /// concatenation of string literals. @@ -714,61 +721,61 @@ public: /// Returns false if optimization is not possible. /// Returns true and initializes internal fields if optimization is possible. bool StringConcatenationOptimizer::extractStringConcatOperands() { - auto *Fn = AI->getReferencedFunctionOrNull(); + auto *Fn = ai->getReferencedFunctionOrNull(); if (!Fn) return false; - if (AI->getNumArguments() != 3 || !Fn->hasSemanticsAttr("string.concat")) + if (ai->getNumArguments() != 3 || !Fn->hasSemanticsAttr("string.concat")) return false; // Left and right operands of a string concatenation operation. - AILeft = dyn_cast(AI->getOperand(1)); - AIRight = dyn_cast(AI->getOperand(2)); + aiLeft = dyn_cast(ai->getOperand(1)); + aiRight = dyn_cast(ai->getOperand(2)); - if (!AILeft || !AIRight) + if (!aiLeft || !aiRight) return false; - FRILeft = dyn_cast(AILeft->getCallee()); - FRIRight = dyn_cast(AIRight->getCallee()); + friLeft = dyn_cast(aiLeft->getCallee()); + friRight = dyn_cast(aiRight->getCallee()); - if (!FRILeft || !FRIRight) + if (!friLeft || !friRight) return false; - auto *FRILeftFun = FRILeft->getReferencedFunctionOrNull(); - auto *FRIRightFun = FRIRight->getReferencedFunctionOrNull(); + auto *friLeftFun = friLeft->getReferencedFunctionOrNull(); + auto *friRightFun = friRight->getReferencedFunctionOrNull(); - if (FRILeftFun->getEffectsKind() >= EffectsKind::ReleaseNone - || FRIRightFun->getEffectsKind() >= EffectsKind::ReleaseNone) + if (friLeftFun->getEffectsKind() >= EffectsKind::ReleaseNone + || friRightFun->getEffectsKind() >= EffectsKind::ReleaseNone) return false; - if (!FRILeftFun->hasSemanticsAttrs() || !FRIRightFun->hasSemanticsAttrs()) + if (!friLeftFun->hasSemanticsAttrs() || !friRightFun->hasSemanticsAttrs()) return false; - auto AILeftOperandsNum = AILeft->getNumOperands(); - auto AIRightOperandsNum = AIRight->getNumOperands(); + auto aiLeftOperandsNum = aiLeft->getNumOperands(); + auto aiRightOperandsNum = aiRight->getNumOperands(); // makeUTF8 should have following parameters: // (start: RawPointer, utf8CodeUnitCount: Word, isASCII: Int1) - if (!((FRILeftFun->hasSemanticsAttr("string.makeUTF8") - && AILeftOperandsNum == 5) - || (FRIRightFun->hasSemanticsAttr("string.makeUTF8") - && AIRightOperandsNum == 5))) + if (!((friLeftFun->hasSemanticsAttr("string.makeUTF8") + && aiLeftOperandsNum == 5) + || (friRightFun->hasSemanticsAttr("string.makeUTF8") + && aiRightOperandsNum == 5))) return false; - SLILeft = dyn_cast(AILeft->getOperand(1)); - SLIRight = dyn_cast(AIRight->getOperand(1)); + sliLeft = dyn_cast(aiLeft->getOperand(1)); + sliRight = dyn_cast(aiRight->getOperand(1)); - if (!SLILeft || !SLIRight) + if (!sliLeft || !sliRight) return false; // Only UTF-8 and UTF-16 encoded string literals are supported by this // optimization. - if (SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF8 - && SLILeft->getEncoding() != StringLiteralInst::Encoding::UTF16) + if (sliLeft->getEncoding() != StringLiteralInst::Encoding::UTF8 + && sliLeft->getEncoding() != StringLiteralInst::Encoding::UTF16) return false; - if (SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF8 - && SLIRight->getEncoding() != StringLiteralInst::Encoding::UTF16) + if (sliRight->getEncoding() != StringLiteralInst::Encoding::UTF8 + && sliRight->getEncoding() != StringLiteralInst::Encoding::UTF16) return false; return true; @@ -777,42 +784,42 @@ bool StringConcatenationOptimizer::extractStringConcatOperands() { /// Ensures that both string literals to be concatenated use the same /// UTF encoding. Converts UTF-8 into UTF-16 if required. void StringConcatenationOptimizer::adjustEncodings() { - if (SLILeft->getEncoding() == SLIRight->getEncoding()) { - FRIConvertFromBuiltin = FRILeft; - if (SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF8) { - FuncResultType = AILeft->getOperand(4); + if (sliLeft->getEncoding() == sliRight->getEncoding()) { + friConvertFromBuiltin = friLeft; + if (sliLeft->getEncoding() == StringLiteralInst::Encoding::UTF8) { + funcResultType = aiLeft->getOperand(4); } else { - FuncResultType = AILeft->getOperand(3); + funcResultType = aiLeft->getOperand(3); } return; } - Builder.setCurrentDebugScope(AI->getDebugScope()); + builder.setCurrentDebugScope(ai->getDebugScope()); // If one of the string literals is UTF8 and another one is UTF16, // convert the UTF8-encoded string literal into UTF16-encoding first. - if (SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF8 - && SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF16) { - FuncResultType = AIRight->getOperand(3); - FRIConvertFromBuiltin = FRIRight; + if (sliLeft->getEncoding() == StringLiteralInst::Encoding::UTF8 + && sliRight->getEncoding() == StringLiteralInst::Encoding::UTF16) { + funcResultType = aiRight->getOperand(3); + friConvertFromBuiltin = friRight; // Convert UTF8 representation into UTF16. - SLILeft = Builder.createStringLiteral(AI->getLoc(), SLILeft->getValue(), + sliLeft = builder.createStringLiteral(ai->getLoc(), sliLeft->getValue(), StringLiteralInst::Encoding::UTF16); } - if (SLIRight->getEncoding() == StringLiteralInst::Encoding::UTF8 - && SLILeft->getEncoding() == StringLiteralInst::Encoding::UTF16) { - FuncResultType = AILeft->getOperand(3); - FRIConvertFromBuiltin = FRILeft; + if (sliRight->getEncoding() == StringLiteralInst::Encoding::UTF8 + && sliLeft->getEncoding() == StringLiteralInst::Encoding::UTF16) { + funcResultType = aiLeft->getOperand(3); + friConvertFromBuiltin = friLeft; // Convert UTF8 representation into UTF16. - SLIRight = Builder.createStringLiteral(AI->getLoc(), SLIRight->getValue(), + sliRight = builder.createStringLiteral(ai->getLoc(), sliRight->getValue(), StringLiteralInst::Encoding::UTF16); } // It should be impossible to have two operands with different // encodings at this point. assert( - SLILeft->getEncoding() == SLIRight->getEncoding() + sliLeft->getEncoding() == sliRight->getEncoding() && "Both operands of string concatenation should have the same encoding"); } @@ -820,35 +827,35 @@ void StringConcatenationOptimizer::adjustEncodings() { APInt StringConcatenationOptimizer::getConcatenatedLength() { // Real length of string literals computed based on its contents. // Length is in code units. - auto SLILenLeft = SLILeft->getCodeUnitCount(); - (void)SLILenLeft; - auto SLILenRight = SLIRight->getCodeUnitCount(); - (void)SLILenRight; + auto sliLenLeft = sliLeft->getCodeUnitCount(); + (void)sliLenLeft; + auto sliLenRight = sliRight->getCodeUnitCount(); + (void)sliLenRight; // Length of string literals as reported by string.make functions. - auto *LenLeft = dyn_cast(AILeft->getOperand(2)); - auto *LenRight = dyn_cast(AIRight->getOperand(2)); + auto *lenLeft = dyn_cast(aiLeft->getOperand(2)); + auto *lenRight = dyn_cast(aiRight->getOperand(2)); // Real and reported length should be the same. - assert(SLILenLeft == LenLeft->getValue() + assert(sliLenLeft == lenLeft->getValue() && "Size of string literal in @_semantics(string.make) is wrong"); - assert(SLILenRight == LenRight->getValue() + assert(sliLenRight == lenRight->getValue() && "Size of string literal in @_semantics(string.make) is wrong"); // Compute length of the concatenated literal. - return LenLeft->getValue() + LenRight->getValue(); + return lenLeft->getValue() + lenRight->getValue(); } /// Computes the isAscii flag of a concatenated UTF8-encoded string literal. bool StringConcatenationOptimizer::isAscii() const { // Add the isASCII argument in case of UTF8. // IsASCII is true only if IsASCII of both literals is true. - auto *AsciiLeft = dyn_cast(AILeft->getOperand(3)); - auto *AsciiRight = dyn_cast(AIRight->getOperand(3)); - auto IsAsciiLeft = AsciiLeft->getValue() == 1; - auto IsAsciiRight = AsciiRight->getValue() == 1; - return IsAsciiLeft && IsAsciiRight; + auto *asciiLeft = dyn_cast(aiLeft->getOperand(3)); + auto *asciiRight = dyn_cast(aiRight->getOperand(3)); + auto isAsciiLeft = asciiLeft->getValue() == 1; + auto isAsciiRight = asciiRight->getValue() == 1; + return isAsciiLeft && isAsciiRight; } SingleValueInstruction *StringConcatenationOptimizer::optimize() { @@ -861,44 +868,44 @@ SingleValueInstruction *StringConcatenationOptimizer::optimize() { adjustEncodings(); // Arguments of the new StringLiteralInst to be created. - SmallVector Arguments; + SmallVector arguments; // Encoding to be used for the concatenated string literal. - auto Encoding = SLILeft->getEncoding(); + auto encoding = sliLeft->getEncoding(); // Create a concatenated string literal. - Builder.setCurrentDebugScope(AI->getDebugScope()); - auto LV = SLILeft->getValue(); - auto RV = SLIRight->getValue(); - auto *NewSLI = - Builder.createStringLiteral(AI->getLoc(), LV + Twine(RV), Encoding); - Arguments.push_back(NewSLI); + builder.setCurrentDebugScope(ai->getDebugScope()); + auto lv = sliLeft->getValue(); + auto rv = sliRight->getValue(); + auto *newSLI = + builder.createStringLiteral(ai->getLoc(), lv + Twine(rv), encoding); + arguments.push_back(newSLI); // Length of the concatenated literal according to its encoding. - auto *Len = Builder.createIntegerLiteral( - AI->getLoc(), AILeft->getOperand(2)->getType(), getConcatenatedLength()); - Arguments.push_back(Len); + auto *len = builder.createIntegerLiteral( + ai->getLoc(), aiLeft->getOperand(2)->getType(), getConcatenatedLength()); + arguments.push_back(len); // isAscii flag for UTF8-encoded string literals. - if (Encoding == StringLiteralInst::Encoding::UTF8) { - bool IsAscii = isAscii(); - auto ILType = AILeft->getOperand(3)->getType(); - auto *Ascii = - Builder.createIntegerLiteral(AI->getLoc(), ILType, intmax_t(IsAscii)); - Arguments.push_back(Ascii); + if (encoding == StringLiteralInst::Encoding::UTF8) { + bool ascii = isAscii(); + auto ilType = aiLeft->getOperand(3)->getType(); + auto *asciiLiteral = + builder.createIntegerLiteral(ai->getLoc(), ilType, intmax_t(ascii)); + arguments.push_back(asciiLiteral); } // Type. - Arguments.push_back(FuncResultType); + arguments.push_back(funcResultType); - return Builder.createApply(AI->getLoc(), FRIConvertFromBuiltin, - SubstitutionMap(), Arguments); + return builder.createApply(ai->getLoc(), friConvertFromBuiltin, + SubstitutionMap(), arguments); } /// Top level entry point -SingleValueInstruction *swift::tryToConcatenateStrings(ApplyInst *AI, - SILBuilder &B) { - return StringConcatenationOptimizer(AI, B).optimize(); +SingleValueInstruction *swift::tryToConcatenateStrings(ApplyInst *ai, + SILBuilder &builder) { + return StringConcatenationOptimizer(ai, builder).optimize(); } //===----------------------------------------------------------------------===// @@ -908,8 +915,8 @@ SingleValueInstruction *swift::tryToConcatenateStrings(ApplyInst *AI, /// NOTE: Instructions with transitive ownership kind are assumed to not keep /// the underlying closure alive as well. This is meant for instructions only /// with non-transitive users. -static bool useDoesNotKeepClosureAlive(const SILInstruction *I) { - switch (I->getKind()) { +static bool useDoesNotKeepClosureAlive(const SILInstruction *inst) { + switch (inst->getKind()) { case SILInstructionKind::StrongRetainInst: case SILInstructionKind::StrongReleaseInst: case SILInstructionKind::DestroyValueInst: @@ -923,60 +930,60 @@ static bool useDoesNotKeepClosureAlive(const SILInstruction *I) { } } -static bool useHasTransitiveOwnership(const SILInstruction *I) { +static bool useHasTransitiveOwnership(const SILInstruction *inst) { // convert_escape_to_noescape is used to convert to a @noescape function type. // It does not change ownership of the function value. - if (isa(I)) + if (isa(inst)) return true; // Look through copy_value, begin_borrow. They are inert for our purposes, but // we need to look through it. - return isa(I) || isa(I); + return isa(inst) || isa(inst); } static SILValue createLifetimeExtendedAllocStack( - SILBuilder &Builder, SILLocation Loc, SILValue Arg, - ArrayRef ExitingBlocks, InstModCallbacks Callbacks) { - AllocStackInst *ASI = nullptr; + SILBuilder &builder, SILLocation loc, SILValue arg, + ArrayRef exitingBlocks, InstModCallbacks callbacks) { + AllocStackInst *asi = nullptr; { // Save our insert point and create a new alloc_stack in the initial BB and // dealloc_stack in all exit blocks. - auto *OldInsertPt = &*Builder.getInsertionPoint(); - Builder.setInsertionPoint(Builder.getFunction().begin()->begin()); - ASI = Builder.createAllocStack(Loc, Arg->getType()); - Callbacks.CreatedNewInst(ASI); + auto *oldInsertPt = &*builder.getInsertionPoint(); + builder.setInsertionPoint(builder.getFunction().begin()->begin()); + asi = builder.createAllocStack(loc, arg->getType()); + callbacks.createdNewInst(asi); - for (auto *BB : ExitingBlocks) { - Builder.setInsertionPoint(BB->getTerminator()); - Callbacks.CreatedNewInst(Builder.createDeallocStack(Loc, ASI)); + for (auto *BB : exitingBlocks) { + builder.setInsertionPoint(BB->getTerminator()); + callbacks.createdNewInst(builder.createDeallocStack(loc, asi)); } - Builder.setInsertionPoint(OldInsertPt); + builder.setInsertionPoint(oldInsertPt); } - assert(ASI != nullptr); + assert(asi != nullptr); // Then perform a copy_addr [take] [init] right after the partial_apply from // the original address argument to the new alloc_stack that we have // created. - Callbacks.CreatedNewInst( - Builder.createCopyAddr(Loc, Arg, ASI, IsTake, IsInitialization)); + callbacks.createdNewInst( + builder.createCopyAddr(loc, arg, asi, IsTake, IsInitialization)); // Return the new alloc_stack inst that has the appropriate live range to // destroy said values. - return ASI; + return asi; } -static bool shouldDestroyPartialApplyCapturedArg(SILValue Arg, - SILParameterInfo PInfo, +static bool shouldDestroyPartialApplyCapturedArg(SILValue arg, + SILParameterInfo paramInfo, const SILFunction &F) { // If we have a non-trivial type and the argument is passed in @inout, we do // not need to destroy it here. This is something that is implicit in the // partial_apply design that will be revisited when partial_apply is // redesigned. - if (PInfo.isIndirectMutating()) + if (paramInfo.isIndirectMutating()) return false; // If we have a trivial type, we do not need to put in any extra releases. - if (Arg->getType().isTrivial(F)) + if (arg->getType().isTrivial(F)) return false; // We handle all other cases. @@ -990,19 +997,21 @@ static bool shouldDestroyPartialApplyCapturedArg(SILValue Arg, // the closed over function. This is because the partial apply is building up a // boxed aggregate to send off to the closed over function. Of course when you // call the function, the proper conventions will be used. -void swift::releasePartialApplyCapturedArg(SILBuilder &Builder, SILLocation Loc, - SILValue Arg, SILParameterInfo PInfo, - InstModCallbacks Callbacks) { - if (!shouldDestroyPartialApplyCapturedArg(Arg, PInfo, Builder.getFunction())) +void swift::releasePartialApplyCapturedArg(SILBuilder &builder, SILLocation loc, + SILValue arg, + SILParameterInfo paramInfo, + InstModCallbacks callbacks) { + if (!shouldDestroyPartialApplyCapturedArg(arg, paramInfo, + builder.getFunction())) return; // Otherwise, we need to destroy the argument. If we have an address, we // insert a destroy_addr and return. Any live range issues must have been // dealt with by our caller. - if (Arg->getType().isAddress()) { + if (arg->getType().isAddress()) { // Then emit the destroy_addr for this arg - SILInstruction *NewInst = Builder.emitDestroyAddrAndFold(Loc, Arg); - Callbacks.CreatedNewInst(NewInst); + SILInstruction *newInst = builder.emitDestroyAddrAndFold(loc, arg); + callbacks.createdNewInst(newInst); return; } @@ -1010,101 +1019,101 @@ void swift::releasePartialApplyCapturedArg(SILBuilder &Builder, SILLocation Loc, // possible for that value. // If we have qualified ownership, we should just emit a destroy value. - if (Arg->getFunction()->hasOwnership()) { - Callbacks.CreatedNewInst(Builder.createDestroyValue(Loc, Arg)); + if (arg->getFunction()->hasOwnership()) { + callbacks.createdNewInst(builder.createDestroyValue(loc, arg)); return; } - if (Arg->getType().hasReferenceSemantics()) { - auto U = Builder.emitStrongRelease(Loc, Arg); - if (U.isNull()) + if (arg->getType().hasReferenceSemantics()) { + auto u = builder.emitStrongRelease(loc, arg); + if (u.isNull()) return; - if (auto *SRI = U.dyn_cast()) { - Callbacks.DeleteInst(SRI); + if (auto *SRI = u.dyn_cast()) { + callbacks.deleteInst(SRI); return; } - Callbacks.CreatedNewInst(U.get()); + callbacks.createdNewInst(u.get()); return; } - auto U = Builder.emitReleaseValue(Loc, Arg); - if (U.isNull()) + auto u = builder.emitReleaseValue(loc, arg); + if (u.isNull()) return; - if (auto *RVI = U.dyn_cast()) { - Callbacks.DeleteInst(RVI); + if (auto *rvi = u.dyn_cast()) { + callbacks.deleteInst(rvi); return; } - Callbacks.CreatedNewInst(U.get()); + callbacks.createdNewInst(u.get()); } -/// For each captured argument of PAI, decrement the ref count of the captured +/// For each captured argument of pai, decrement the ref count of the captured /// argument as appropriate at each of the post dominated release locations -/// found by Tracker. -static bool releaseCapturedArgsOfDeadPartialApply(PartialApplyInst *PAI, - ReleaseTracker &Tracker, - InstModCallbacks Callbacks) { - SILBuilderWithScope Builder(PAI); - SILLocation Loc = PAI->getLoc(); - CanSILFunctionType PAITy = - PAI->getCallee()->getType().getAs(); +/// found by tracker. +static bool releaseCapturedArgsOfDeadPartialApply(PartialApplyInst *pai, + ReleaseTracker &tracker, + InstModCallbacks callbacks) { + SILBuilderWithScope builder(pai); + SILLocation loc = pai->getLoc(); + CanSILFunctionType paiTy = + pai->getCallee()->getType().getAs(); - ArrayRef Params = PAITy->getParameters(); - llvm::SmallVector Args; - for (SILValue v : PAI->getArguments()) { + ArrayRef params = paiTy->getParameters(); + llvm::SmallVector args; + for (SILValue v : pai->getArguments()) { // If any of our arguments contain open existentials, bail. We do not // support this for now so that we can avoid having to re-order stack // locations (a larger change). if (v->getType().hasOpenedExistential()) return false; - Args.emplace_back(v); + args.emplace_back(v); } - unsigned Delta = Params.size() - Args.size(); - assert(Delta <= Params.size() - && "Error, more Args to partial apply than " + unsigned delta = params.size() - args.size(); + assert(delta <= params.size() + && "Error, more args to partial apply than " "params in its interface."); - Params = Params.drop_front(Delta); + params = params.drop_front(delta); - llvm::SmallVector ExitingBlocks; - PAI->getFunction()->findExitingBlocks(ExitingBlocks); + llvm::SmallVector exitingBlocks; + pai->getFunction()->findExitingBlocks(exitingBlocks); // Go through our argument list and create new alloc_stacks for each // non-trivial address value. This ensures that the memory location that we // are cleaning up has the same live range as the partial_apply. Otherwise, we // may be inserting destroy_addr of alloc_stack that have already been passed // to a dealloc_stack. - for (unsigned i : reversed(indices(Args))) { - SILValue Arg = Args[i]; - SILParameterInfo PInfo = Params[i]; + for (unsigned i : reversed(indices(args))) { + SILValue arg = args[i]; + SILParameterInfo paramInfo = params[i]; // If we are not going to destroy this partial_apply, continue. - if (!shouldDestroyPartialApplyCapturedArg(Arg, PInfo, - Builder.getFunction())) + if (!shouldDestroyPartialApplyCapturedArg(arg, paramInfo, + builder.getFunction())) continue; // If we have an object, we will not have live range issues, just continue. - if (Arg->getType().isObject()) + if (arg->getType().isObject()) continue; // Now that we know that we have a non-argument address, perform a take-init - // of Arg into a lifetime extended alloc_stack - Args[i] = createLifetimeExtendedAllocStack(Builder, Loc, Arg, ExitingBlocks, - Callbacks); + // of arg into a lifetime extended alloc_stack + args[i] = createLifetimeExtendedAllocStack(builder, loc, arg, exitingBlocks, + callbacks); } // Emit a destroy for each captured closure argument at each final release // point. - for (auto *FinalRelease : Tracker.getFinalReleases()) { - Builder.setInsertionPoint(FinalRelease); - Builder.setCurrentDebugScope(FinalRelease->getDebugScope()); - for (unsigned i : indices(Args)) { - SILValue Arg = Args[i]; - SILParameterInfo Param = Params[i]; + for (auto *finalRelease : tracker.getFinalReleases()) { + builder.setInsertionPoint(finalRelease); + builder.setCurrentDebugScope(finalRelease->getDebugScope()); + for (unsigned i : indices(args)) { + SILValue arg = args[i]; + SILParameterInfo param = params[i]; - releasePartialApplyCapturedArg(Builder, Loc, Arg, Param, Callbacks); + releasePartialApplyCapturedArg(builder, loc, arg, param, callbacks); } } @@ -1112,42 +1121,42 @@ static bool releaseCapturedArgsOfDeadPartialApply(PartialApplyInst *PAI, } static bool -deadMarkDependenceUser(SILInstruction *Inst, - SmallVectorImpl &DeleteInsts) { - if (!isa(Inst)) +deadMarkDependenceUser(SILInstruction *inst, + SmallVectorImpl &deleteInsts) { + if (!isa(inst)) return false; - DeleteInsts.push_back(Inst); - for (auto *Use : cast(Inst)->getUses()) { - if (!deadMarkDependenceUser(Use->getUser(), DeleteInsts)) + deleteInsts.push_back(inst); + for (auto *use : cast(inst)->getUses()) { + if (!deadMarkDependenceUser(use->getUser(), deleteInsts)) return false; } return true; } /// TODO: Generalize this to general objects. -bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure, - InstModCallbacks Callbacks) { - auto *PA = dyn_cast(Closure); +bool swift::tryDeleteDeadClosure(SingleValueInstruction *closure, + InstModCallbacks callbacks) { + auto *pa = dyn_cast(closure); // We currently only handle locally identified values that do not escape. We // also assume that the partial apply does not capture any addresses. - if (!PA && !isa(Closure)) + if (!pa && !isa(closure)) return false; // A stack allocated partial apply does not have any release users. Delete it // if the only users are the dealloc_stack and mark_dependence instructions. - if (PA && PA->isOnStack()) { - SmallVector DeleteInsts; - for (auto *Use : PA->getUses()) { - if (isa(Use->getUser()) - || isa(Use->getUser())) - DeleteInsts.push_back(Use->getUser()); - else if (!deadMarkDependenceUser(Use->getUser(), DeleteInsts)) + if (pa && pa->isOnStack()) { + SmallVector deleteInsts; + for (auto *use : pa->getUses()) { + if (isa(use->getUser()) + || isa(use->getUser())) + deleteInsts.push_back(use->getUser()); + else if (!deadMarkDependenceUser(use->getUser(), deleteInsts)) return false; } - for (auto *Inst : reverse(DeleteInsts)) - Callbacks.DeleteInst(Inst); - Callbacks.DeleteInst(PA); + for (auto *inst : reverse(deleteInsts)) + callbacks.deleteInst(inst); + callbacks.deleteInst(pa); // Note: the lifetime of the captured arguments is managed outside of the // trivial closure value i.e: there will already be releases for the @@ -1159,73 +1168,73 @@ bool swift::tryDeleteDeadClosure(SingleValueInstruction *Closure, // object is dead. This should be expanded in the future. This also ensures // that we are locally identified and non-escaping since we only allow for // specific ARC users. - ReleaseTracker Tracker(useDoesNotKeepClosureAlive, useHasTransitiveOwnership); + ReleaseTracker tracker(useDoesNotKeepClosureAlive, useHasTransitiveOwnership); - // Find the ARC Users and the final retain, release. - if (!getFinalReleasesForValue(SILValue(Closure), Tracker)) + // Find the ARC users and the final retain, release. + if (!getFinalReleasesForValue(SILValue(closure), tracker)) return false; // If we have a partial_apply, release each captured argument at each one of // the final release locations of the partial apply. - if (auto *PAI = dyn_cast(Closure)) { + if (auto *pai = dyn_cast(closure)) { // If we can not decrement the ref counts of the dead partial apply for any // reason, bail. - if (!releaseCapturedArgsOfDeadPartialApply(PAI, Tracker, Callbacks)) + if (!releaseCapturedArgsOfDeadPartialApply(pai, tracker, callbacks)) return false; } // Then delete all user instructions in reverse so that leaf uses are deleted // first. - for (auto *User : reverse(Tracker.getTrackedUsers())) { - assert(User->getResults().empty() - || useHasTransitiveOwnership(User) + for (auto *user : reverse(tracker.getTrackedUsers())) { + assert(user->getResults().empty() + || useHasTransitiveOwnership(user) && "We expect only ARC operations without " "results or a cast from escape to noescape without users"); - Callbacks.DeleteInst(User); + callbacks.deleteInst(user); } // Finally delete the closure. - Callbacks.DeleteInst(Closure); + callbacks.deleteInst(closure); return true; } -bool swift::simplifyUsers(SingleValueInstruction *I) { - bool Changed = false; +bool swift::simplifyUsers(SingleValueInstruction *inst) { + bool changed = false; - for (auto UI = I->use_begin(), UE = I->use_end(); UI != UE;) { - SILInstruction *User = UI->getUser(); - ++UI; + for (auto ui = inst->use_begin(), ue = inst->use_end(); ui != ue;) { + SILInstruction *user = ui->getUser(); + ++ui; - auto SVI = dyn_cast(User); - if (!SVI) + auto svi = dyn_cast(user); + if (!svi) continue; - SILValue S = simplifyInstruction(SVI); + SILValue S = simplifyInstruction(svi); if (!S) continue; - replaceAllSimplifiedUsesAndErase(SVI, S); - Changed = true; + replaceAllSimplifiedUsesAndErase(svi, S); + changed = true; } - return Changed; + return changed; } /// True if a type can be expanded without a significant increase to code size. -bool swift::shouldExpand(SILModule &Module, SILType Ty) { +bool swift::shouldExpand(SILModule &module, SILType ty) { // FIXME: Expansion - auto Expansion = ResilienceExpansion::Minimal; + auto expansion = ResilienceExpansion::Minimal; - if (Module.Types.getTypeLowering(Ty, Expansion).isAddressOnly()) { + if (module.Types.getTypeLowering(ty, expansion).isAddressOnly()) { return false; } if (EnableExpandAll) { return true; } - unsigned NumFields = Module.Types.countNumberOfFields(Ty, Expansion); - return (NumFields <= 6); + unsigned numFields = module.Types.countNumberOfFields(ty, expansion); + return (numFields <= 6); } /// Some support functions for the global-opt and let-properties-opts @@ -1250,13 +1259,13 @@ public: // values in the `visited` set in preorder. Insert values in // `postOrderInstructions` in postorder so that the instructions are // topologically def-use ordered (in execution order). - bool analyze(SILValue RootValue) { - return recursivelyAnalyzeOperand(RootValue); + bool analyze(SILValue rootValue) { + return recursivelyAnalyzeOperand(rootValue); } protected: - bool recursivelyAnalyzeOperand(SILValue V) { - if (!visited.insert(V).second) + bool recursivelyAnalyzeOperand(SILValue v) { + if (!visited.insert(v).second) return true; if (++recursionLevel > 50) @@ -1264,90 +1273,90 @@ protected: // TODO: For multi-result instructions, we could simply insert all result // values in the visited set here. - auto *I = dyn_cast(V); - if (!I) + auto *inst = dyn_cast(v); + if (!inst) return false; - if (!recursivelyAnalyzeInstruction(I)) + if (!recursivelyAnalyzeInstruction(inst)) return false; - postOrderInstructions.push_back(I); + postOrderInstructions.push_back(inst); --recursionLevel; return true; } - bool recursivelyAnalyzeInstruction(SILInstruction *I) { - if (auto *SI = dyn_cast(I)) { + bool recursivelyAnalyzeInstruction(SILInstruction *inst) { + if (auto *si = dyn_cast(inst)) { // If it is not a struct which is a simple type, bail. - if (!SI->getType().isTrivial(*SI->getFunction())) + if (!si->getType().isTrivial(*si->getFunction())) return false; - return llvm::all_of(SI->getAllOperands(), [&](Operand &Op) -> bool { - return recursivelyAnalyzeOperand(Op.get()); + return llvm::all_of(si->getAllOperands(), [&](Operand &operand) -> bool { + return recursivelyAnalyzeOperand(operand.get()); }); } - if (auto *TI = dyn_cast(I)) { + if (auto *ti = dyn_cast(inst)) { // If it is not a tuple which is a simple type, bail. - if (!TI->getType().isTrivial(*TI->getFunction())) + if (!ti->getType().isTrivial(*ti->getFunction())) return false; - return llvm::all_of(TI->getAllOperands(), [&](Operand &Op) -> bool { - return recursivelyAnalyzeOperand(Op.get()); + return llvm::all_of(ti->getAllOperands(), [&](Operand &operand) -> bool { + return recursivelyAnalyzeOperand(operand.get()); }); } - if (auto *bi = dyn_cast(I)) { + if (auto *bi = dyn_cast(inst)) { switch (bi->getBuiltinInfo().ID) { case BuiltinValueKind::FPTrunc: - if (auto *LI = dyn_cast(bi->getArguments()[0])) { - return recursivelyAnalyzeOperand(LI); + if (auto *li = dyn_cast(bi->getArguments()[0])) { + return recursivelyAnalyzeOperand(li); } return false; default: return false; } } - return isa(I) || isa(I) - || isa(I); + return isa(inst) || isa(inst) + || isa(inst); } }; -/// Check if the value of V is computed by means of a simple initialization. +/// Check if the value of v is computed by means of a simple initialization. /// Populate `forwardInstructions` with references to all the instructions /// that participate in the use-def graph required to compute `V`. The /// instructions will be in def-use topological order. bool swift::analyzeStaticInitializer( - SILValue V, SmallVectorImpl &forwardInstructions) { - return StaticInitializerAnalysis(forwardInstructions).analyze(V); + SILValue v, SmallVectorImpl &forwardInstructions) { + return StaticInitializerAnalysis(forwardInstructions).analyze(v); } /// FIXME: This must be kept in sync with replaceLoadSequence() /// below. What a horrible design. -bool swift::canReplaceLoadSequence(SILInstruction *I) { - if (auto *CAI = dyn_cast(I)) +bool swift::canReplaceLoadSequence(SILInstruction *inst) { + if (auto *cai = dyn_cast(inst)) return true; - if (auto *LI = dyn_cast(I)) + if (auto *li = dyn_cast(inst)) return true; - if (auto *SEAI = dyn_cast(I)) { - for (auto SEAIUse : SEAI->getUses()) { - if (!canReplaceLoadSequence(SEAIUse->getUser())) + if (auto *seai = dyn_cast(inst)) { + for (auto seaiUse : seai->getUses()) { + if (!canReplaceLoadSequence(seaiUse->getUser())) return false; } return true; } - if (auto *TEAI = dyn_cast(I)) { - for (auto TEAIUse : TEAI->getUses()) { - if (!canReplaceLoadSequence(TEAIUse->getUser())) + if (auto *teai = dyn_cast(inst)) { + for (auto teaiUse : teai->getUses()) { + if (!canReplaceLoadSequence(teaiUse->getUser())) return false; } return true; } - if (auto *BA = dyn_cast(I)) { - for (auto Use : BA->getUses()) { - if (!canReplaceLoadSequence(Use->getUser())) + if (auto *ba = dyn_cast(inst)) { + for (auto use : ba->getUses()) { + if (!canReplaceLoadSequence(use->getUser())) return false; } return true; @@ -1355,7 +1364,7 @@ bool swift::canReplaceLoadSequence(SILInstruction *I) { // Incidental uses of an address are meaningless with regard to the loaded // value. - if (isIncidentalUse(I) || isa(I)) + if (isIncidentalUse(inst) || isa(inst)) return true; return false; @@ -1370,47 +1379,49 @@ bool swift::canReplaceLoadSequence(SILInstruction *I) { /// FIXME: this utility does not make sense as an API. How can the caller /// guarantee that the only uses of `I` are struct_element_addr and /// tuple_element_addr? -void swift::replaceLoadSequence(SILInstruction *I, SILValue Value) { - if (auto *CAI = dyn_cast(I)) { - SILBuilder B(CAI); - B.createStore(CAI->getLoc(), Value, CAI->getDest(), - StoreOwnershipQualifier::Unqualified); +void swift::replaceLoadSequence(SILInstruction *inst, SILValue value) { + if (auto *cai = dyn_cast(inst)) { + SILBuilder builder(cai); + builder.createStore(cai->getLoc(), value, cai->getDest(), + StoreOwnershipQualifier::Unqualified); return; } - if (auto *LI = dyn_cast(I)) { - LI->replaceAllUsesWith(Value); + if (auto *li = dyn_cast(inst)) { + li->replaceAllUsesWith(value); return; } - if (auto *SEAI = dyn_cast(I)) { - SILBuilder B(SEAI); - auto *SEI = B.createStructExtract(SEAI->getLoc(), Value, SEAI->getField()); - for (auto SEAIUse : SEAI->getUses()) { - replaceLoadSequence(SEAIUse->getUser(), SEI); + if (auto *seai = dyn_cast(inst)) { + SILBuilder builder(seai); + auto *sei = + builder.createStructExtract(seai->getLoc(), value, seai->getField()); + for (auto seaiUse : seai->getUses()) { + replaceLoadSequence(seaiUse->getUser(), sei); } return; } - if (auto *TEAI = dyn_cast(I)) { - SILBuilder B(TEAI); - auto *TEI = B.createTupleExtract(TEAI->getLoc(), Value, TEAI->getFieldNo()); - for (auto TEAIUse : TEAI->getUses()) { - replaceLoadSequence(TEAIUse->getUser(), TEI); + if (auto *teai = dyn_cast(inst)) { + SILBuilder builder(teai); + auto *tei = + builder.createTupleExtract(teai->getLoc(), value, teai->getFieldNo()); + for (auto teaiUse : teai->getUses()) { + replaceLoadSequence(teaiUse->getUser(), tei); } return; } - if (auto *BA = dyn_cast(I)) { - for (auto Use : BA->getUses()) { - replaceLoadSequence(Use->getUser(), Value); + if (auto *ba = dyn_cast(inst)) { + for (auto use : ba->getUses()) { + replaceLoadSequence(use->getUser(), value); } return; } // Incidental uses of an addres are meaningless with regard to the loaded // value. - if (isIncidentalUse(I) || isa(I)) + if (isIncidentalUse(inst) || isa(inst)) return; llvm_unreachable("Unknown instruction sequence for reading from a global"); @@ -1418,44 +1429,44 @@ void swift::replaceLoadSequence(SILInstruction *I, SILValue Value) { /// Are the callees that could be called through Decl statically /// knowable based on the Decl and the compilation mode? -bool swift::calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl) { - if (Decl.isForeign) +bool swift::calleesAreStaticallyKnowable(SILModule &module, SILDeclRef decl) { + if (decl.isForeign) return false; - const DeclContext *AssocDC = M.getAssociatedContext(); - if (!AssocDC) + const DeclContext *assocDC = module.getAssociatedContext(); + if (!assocDC) return false; - auto *AFD = Decl.getAbstractFunctionDecl(); - assert(AFD && "Expected abstract function decl!"); + auto *afd = decl.getAbstractFunctionDecl(); + assert(afd && "Expected abstract function decl!"); // Only handle members defined within the SILModule's associated context. - if (!AFD->isChildContextOf(AssocDC)) + if (!afd->isChildContextOf(assocDC)) return false; - if (AFD->isDynamic()) { + if (afd->isDynamic()) { return false; } - if (!AFD->hasAccess()) + if (!afd->hasAccess()) return false; // Only consider 'private' members, unless we are in whole-module compilation. - switch (AFD->getEffectiveAccess()) { + switch (afd->getEffectiveAccess()) { case AccessLevel::Open: return false; case AccessLevel::Public: - if (isa(AFD)) { + if (isa(afd)) { // Constructors are special: a derived class in another module can // "override" a constructor if its class is "open", although the // constructor itself is not open. - auto *ND = AFD->getDeclContext()->getSelfNominalTypeDecl(); - if (ND->getEffectiveAccess() == AccessLevel::Open) + auto *nd = afd->getDeclContext()->getSelfNominalTypeDecl(); + if (nd->getEffectiveAccess() == AccessLevel::Open) return false; } LLVM_FALLTHROUGH; case AccessLevel::Internal: - return M.isWholeModule(); + return module.isWholeModule(); case AccessLevel::FilePrivate: case AccessLevel::Private: return true; @@ -1465,8 +1476,8 @@ bool swift::calleesAreStaticallyKnowable(SILModule &M, SILDeclRef Decl) { } Optional -swift::findLocalApplySites(FunctionRefBaseInst *FRI) { - SmallVector worklist(FRI->use_begin(), FRI->use_end()); +swift::findLocalApplySites(FunctionRefBaseInst *fri) { + SmallVector worklist(fri->use_begin(), fri->use_end()); Optional f; f.emplace(); @@ -1547,20 +1558,20 @@ swift::findLocalApplySites(FunctionRefBaseInst *FRI) { /// Insert destroys of captured arguments of partial_apply [stack]. void swift::insertDestroyOfCapturedArguments( - PartialApplyInst *PAI, SILBuilder &B, + PartialApplyInst *pai, SILBuilder &builder, llvm::function_ref shouldInsertDestroy) { - assert(PAI->isOnStack()); + assert(pai->isOnStack()); - ApplySite site(PAI); + ApplySite site(pai); SILFunctionConventions calleeConv(site.getSubstCalleeType(), - PAI->getModule()); + pai->getModule()); auto loc = RegularLocation::getAutoGeneratedLocation(); - for (auto &arg : PAI->getArgumentOperands()) { + for (auto &arg : pai->getArgumentOperands()) { if (!shouldInsertDestroy(arg.get())) continue; unsigned calleeArgumentIndex = site.getCalleeArgIndex(arg); assert(calleeArgumentIndex >= calleeConv.getSILArgIndexOfFirstParam()); auto paramInfo = calleeConv.getParamInfoForSILArg(calleeArgumentIndex); - releasePartialApplyCapturedArg(B, loc, arg.get(), paramInfo); + releasePartialApplyCapturedArg(builder, loc, arg.get(), paramInfo); } } diff --git a/lib/SILOptimizer/Utils/ValueLifetime.cpp b/lib/SILOptimizer/Utils/ValueLifetime.cpp index b4ef78b7d78..8e18a9da9ad 100644 --- a/lib/SILOptimizer/Utils/ValueLifetime.cpp +++ b/lib/SILOptimizer/Utils/ValueLifetime.cpp @@ -17,125 +17,125 @@ using namespace swift; void ValueLifetimeAnalysis::propagateLiveness() { - assert(LiveBlocks.empty() && "frontier computed twice"); + assert(liveBlocks.empty() && "frontier computed twice"); - auto DefBB = DefValue->getParentBlock(); - llvm::SmallVector Worklist; - int NumUsersBeforeDef = 0; + auto defBB = defValue->getParentBlock(); + llvm::SmallVector worklist; + int numUsersBeforeDef = 0; // Find the initial set of blocks where the value is live, because // it is used in those blocks. - for (SILInstruction *User : UserSet) { - SILBasicBlock *UserBlock = User->getParent(); - if (LiveBlocks.insert(UserBlock)) - Worklist.push_back(UserBlock); + for (SILInstruction *user : userSet) { + SILBasicBlock *userBlock = user->getParent(); + if (liveBlocks.insert(userBlock)) + worklist.push_back(userBlock); - // A user in the DefBB could potentially be located before the DefValue. - if (UserBlock == DefBB) - NumUsersBeforeDef++; + // A user in the defBB could potentially be located before the defValue. + if (userBlock == defBB) + numUsersBeforeDef++; } - // Don't count any users in the DefBB which are actually located _after_ - // the DefValue. - auto InstIter = DefValue->getIterator(); - while (NumUsersBeforeDef > 0 && ++InstIter != DefBB->end()) { - if (UserSet.count(&*InstIter)) - NumUsersBeforeDef--; + // Don't count any users in the defBB which are actually located _after_ + // the defValue. + auto instIter = defValue->getIterator(); + while (numUsersBeforeDef > 0 && ++instIter != defBB->end()) { + if (userSet.count(&*instIter)) + numUsersBeforeDef--; } // Now propagate liveness backwards until we hit the block that defines the // value. - while (!Worklist.empty()) { - auto *BB = Worklist.pop_back_val(); + while (!worklist.empty()) { + auto *bb = worklist.pop_back_val(); // Don't go beyond the definition. - if (BB == DefBB && NumUsersBeforeDef == 0) + if (bb == defBB && numUsersBeforeDef == 0) continue; - for (SILBasicBlock *Pred : BB->getPredecessorBlocks()) { + for (SILBasicBlock *Pred : bb->getPredecessorBlocks()) { // If it's already in the set, then we've already queued and/or // processed the predecessors. - if (LiveBlocks.insert(Pred)) - Worklist.push_back(Pred); + if (liveBlocks.insert(Pred)) + worklist.push_back(Pred); } } } -SILInstruction *ValueLifetimeAnalysis:: findLastUserInBlock(SILBasicBlock *BB) { - // Walk backwards in BB looking for last use of the value. - for (auto II = BB->rbegin(); II != BB->rend(); ++II) { - assert(DefValue != &*II && "Found def before finding use!"); +SILInstruction *ValueLifetimeAnalysis::findLastUserInBlock(SILBasicBlock *bb) { + // Walk backwards in bb looking for last use of the value. + for (auto ii = bb->rbegin(); ii != bb->rend(); ++ii) { + assert(defValue != &*ii && "Found def before finding use!"); - if (UserSet.count(&*II)) - return &*II; + if (userSet.count(&*ii)) + return &*ii; } llvm_unreachable("Expected to find use of value in block!"); } -bool ValueLifetimeAnalysis::computeFrontier(Frontier &Fr, Mode mode, - DeadEndBlocks *DEBlocks) { - assert(!isAliveAtBeginOfBlock(DefValue->getFunction()->getEntryBlock()) && - "Can't compute frontier for def which does not dominate all uses"); +bool ValueLifetimeAnalysis::computeFrontier(Frontier &frontier, Mode mode, + DeadEndBlocks *deBlocks) { + assert(!isAliveAtBeginOfBlock(defValue->getFunction()->getEntryBlock()) + && "Can't compute frontier for def which does not dominate all uses"); - bool NoCriticalEdges = true; + bool noCriticalEdges = true; // Exit-blocks from the lifetime region. The value is live at the end of // a predecessor block but not in the frontier block itself. - llvm::SmallSetVector FrontierBlocks; + llvm::SmallSetVector frontierBlocks; // Blocks where the value is live at the end of the block and which have // a frontier block as successor. - llvm::SmallSetVector LiveOutBlocks; + llvm::SmallSetVector liveOutBlocks; /// The lifetime ends if we have a live block and a not-live successor. - for (SILBasicBlock *BB : LiveBlocks) { - if (DEBlocks && DEBlocks->isDeadEnd(BB)) + for (SILBasicBlock *bb : liveBlocks) { + if (deBlocks && deBlocks->isDeadEnd(bb)) continue; - bool LiveInSucc = false; - bool DeadInSucc = false; - for (const SILSuccessor &Succ : BB->getSuccessors()) { - if (isAliveAtBeginOfBlock(Succ)) { - LiveInSucc = true; - } else if (!DEBlocks || !DEBlocks->isDeadEnd(Succ)) { - DeadInSucc = true; + bool liveInSucc = false; + bool deadInSucc = false; + for (const SILSuccessor &succ : bb->getSuccessors()) { + if (isAliveAtBeginOfBlock(succ)) { + liveInSucc = true; + } else if (!deBlocks || !deBlocks->isDeadEnd(succ)) { + deadInSucc = true; } } - if (!LiveInSucc) { + if (!liveInSucc) { // The value is not live in any of the successor blocks. This means the // block contains a last use of the value. The next instruction after // the last use is part of the frontier. - SILInstruction *LastUser = findLastUserInBlock(BB); - if (!isa(LastUser)) { - Fr.push_back(&*std::next(LastUser->getIterator())); + SILInstruction *lastUser = findLastUserInBlock(bb); + if (!isa(lastUser)) { + frontier.push_back(&*std::next(lastUser->getIterator())); continue; } // In case the last user is a TermInst we add all successor blocks to the // frontier (see below). - assert(DeadInSucc && "The final using TermInst must have successors"); + assert(deadInSucc && "The final using TermInst must have successors"); } - if (DeadInSucc) { + if (deadInSucc) { if (mode == UsersMustPostDomDef) return false; // The value is not live in some of the successor blocks. - LiveOutBlocks.insert(BB); - for (const SILSuccessor &Succ : BB->getSuccessors()) { - if (!isAliveAtBeginOfBlock(Succ)) { + liveOutBlocks.insert(bb); + for (const SILSuccessor &succ : bb->getSuccessors()) { + if (!isAliveAtBeginOfBlock(succ)) { // It's an "exit" edge from the lifetime region. - FrontierBlocks.insert(Succ); + frontierBlocks.insert(succ); } } } } // Handle "exit" edges from the lifetime region. - llvm::SmallPtrSet UnhandledFrontierBlocks; - for (SILBasicBlock *FrontierBB: FrontierBlocks) { + llvm::SmallPtrSet unhandledFrontierBlocks; + for (SILBasicBlock *frontierBB : frontierBlocks) { assert(mode != UsersMustPostDomDef); bool needSplit = false; // If the value is live only in part of the predecessor blocks we have to // split those predecessor edges. - for (SILBasicBlock *Pred : FrontierBB->getPredecessorBlocks()) { - if (!LiveOutBlocks.count(Pred)) { + for (SILBasicBlock *Pred : frontierBB->getPredecessorBlocks()) { + if (!liveOutBlocks.count(Pred)) { needSplit = true; break; } @@ -144,94 +144,94 @@ bool ValueLifetimeAnalysis::computeFrontier(Frontier &Fr, Mode mode, if (mode == DontModifyCFG) return false; // We need to split the critical edge to create a frontier instruction. - UnhandledFrontierBlocks.insert(FrontierBB); + unhandledFrontierBlocks.insert(frontierBB); } else { // The first instruction of the exit-block is part of the frontier. - Fr.push_back(&*FrontierBB->begin()); + frontier.push_back(&*frontierBB->begin()); } } // Split critical edges from the lifetime region to not yet handled frontier // blocks. - for (SILBasicBlock *FrontierPred : LiveOutBlocks) { + for (SILBasicBlock *frontierPred : liveOutBlocks) { assert(mode != UsersMustPostDomDef); - auto *T = FrontierPred->getTerminator(); + auto *term = frontierPred->getTerminator(); // Cache the successor blocks because splitting critical edges invalidates // the successor list iterator of T. - llvm::SmallVector SuccBlocks; - for (const SILSuccessor &Succ : T->getSuccessors()) - SuccBlocks.push_back(Succ); + llvm::SmallVector succBlocks; + for (const SILSuccessor &succ : term->getSuccessors()) + succBlocks.push_back(succ); - for (unsigned i = 0, e = SuccBlocks.size(); i != e; ++i) { - if (UnhandledFrontierBlocks.count(SuccBlocks[i])) { + for (unsigned i = 0, e = succBlocks.size(); i != e; ++i) { + if (unhandledFrontierBlocks.count(succBlocks[i])) { assert(mode == AllowToModifyCFG); - assert(isCriticalEdge(T, i) && "actually not a critical edge?"); - SILBasicBlock *NewBlock = splitEdge(T, i); + assert(isCriticalEdge(term, i) && "actually not a critical edge?"); + SILBasicBlock *newBlock = splitEdge(term, i); // The single terminator instruction is part of the frontier. - Fr.push_back(&*NewBlock->begin()); - NoCriticalEdges = false; + frontier.push_back(&*newBlock->begin()); + noCriticalEdges = false; } } } - return NoCriticalEdges; + return noCriticalEdges; } -bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *Inst) { - SILBasicBlock *BB = Inst->getParent(); - // Check if the value is not live anywhere in Inst's block. - if (!LiveBlocks.count(BB)) +bool ValueLifetimeAnalysis::isWithinLifetime(SILInstruction *inst) { + SILBasicBlock *bb = inst->getParent(); + // Check if the value is not live anywhere in inst's block. + if (!liveBlocks.count(bb)) return false; - for (const SILSuccessor &Succ : BB->getSuccessors()) { + for (const SILSuccessor &succ : bb->getSuccessors()) { // If the value is live at the beginning of any successor block it is also - // live at the end of BB and therefore Inst is definitely in the lifetime + // live at the end of bb and therefore inst is definitely in the lifetime // region (Note that we don't check in upward direction against the value's // definition). - if (isAliveAtBeginOfBlock(Succ)) + if (isAliveAtBeginOfBlock(succ)) return true; } // The value is live in the block but not at the end of the block. Check if - // Inst is located before (or at) the last use. - for (auto II = BB->rbegin(); II != BB->rend(); ++II) { - if (UserSet.count(&*II)) { + // inst is located before (or at) the last use. + for (auto ii = bb->rbegin(); ii != bb->rend(); ++ii) { + if (userSet.count(&*ii)) { return true; } - if (Inst == &*II) + if (inst == &*ii) return false; } llvm_unreachable("Expected to find use of value in block!"); } -// Searches \p BB backwards from the instruction before \p FrontierInst +// Searches \p bb backwards from the instruction before \p frontierInst // to the beginning of the list and returns true if we find a dealloc_ref -// /before/ we find \p DefValue (the instruction that defines our target value). -static bool blockContainsDeallocRef(SILBasicBlock *BB, SILInstruction *DefValue, - SILInstruction *FrontierInst) { - SILBasicBlock::reverse_iterator End = BB->rend(); - SILBasicBlock::reverse_iterator Iter = FrontierInst->getReverseIterator(); - for (++Iter; Iter != End; ++Iter) { - SILInstruction *I = &*Iter; - if (isa(I)) +// /before/ we find \p defValue (the instruction that defines our target value). +static bool blockContainsDeallocRef(SILBasicBlock *bb, SILInstruction *defValue, + SILInstruction *frontierInst) { + SILBasicBlock::reverse_iterator End = bb->rend(); + SILBasicBlock::reverse_iterator iter = frontierInst->getReverseIterator(); + for (++iter; iter != End; ++iter) { + SILInstruction *inst = &*iter; + if (isa(inst)) return true; - if (I == DefValue) + if (inst == defValue) return false; } return false; } -bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &Frontier) { - SmallPtrSet FrontierBlocks; +bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &frontier) { + SmallPtrSet frontierBlocks; // Search in live blocks where the value is not alive until the end of the // block, i.e. the live range is terminated by a frontier instruction. - for (SILInstruction *FrontierInst : Frontier) { - SILBasicBlock *BB = FrontierInst->getParent(); - if (blockContainsDeallocRef(BB, DefValue, FrontierInst)) + for (SILInstruction *frontierInst : frontier) { + SILBasicBlock *bb = frontierInst->getParent(); + if (blockContainsDeallocRef(bb, defValue, frontierInst)) return true; - FrontierBlocks.insert(BB); + frontierBlocks.insert(bb); } // Search in all other live blocks where the value is alive until the end of // the block. - for (SILBasicBlock *BB : LiveBlocks) { - if (FrontierBlocks.count(BB) == 0) { - if (blockContainsDeallocRef(BB, DefValue, BB->getTerminator())) + for (SILBasicBlock *bb : liveBlocks) { + if (frontierBlocks.count(bb) == 0) { + if (blockContainsDeallocRef(bb, defValue, bb->getTerminator())) return true; } } @@ -239,13 +239,13 @@ bool ValueLifetimeAnalysis::containsDeallocRef(const Frontier &Frontier) { } void ValueLifetimeAnalysis::dump() const { - llvm::errs() << "lifetime of def: " << *DefValue; - for (SILInstruction *Use : UserSet) { + llvm::errs() << "lifetime of def: " << *defValue; + for (SILInstruction *Use : userSet) { llvm::errs() << " use: " << *Use; } llvm::errs() << " live blocks:"; - for (SILBasicBlock *BB : LiveBlocks) { - llvm::errs() << ' ' << BB->getDebugID(); + for (SILBasicBlock *bb : liveBlocks) { + llvm::errs() << ' ' << bb->getDebugID(); } llvm::errs() << '\n'; } From 7f24c992e0c2fedf467e44021ff903cea83fa839 Mon Sep 17 00:00:00 2001 From: Michael Gottesman Date: Wed, 2 Oct 2019 11:44:21 -0700 Subject: [PATCH 3/4] [gardening] Eliminate unneeded include of . --- include/swift/SIL/SILGlobalVariable.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/swift/SIL/SILGlobalVariable.h b/include/swift/SIL/SILGlobalVariable.h index 0684c4832f2..eedc850458e 100644 --- a/include/swift/SIL/SILGlobalVariable.h +++ b/include/swift/SIL/SILGlobalVariable.h @@ -17,7 +17,6 @@ #ifndef SWIFT_SIL_SILGLOBALVARIABLE_H #define SWIFT_SIL_SILGLOBALVARIABLE_H -#include #include "swift/SIL/SILLinkage.h" #include "swift/SIL/SILLocation.h" #include "swift/SIL/SILBasicBlock.h" From 351c4cc73609fc0cfb6d055ae56a66ffb3752158 Mon Sep 17 00:00:00 2001 From: Mishal Shah Date: Wed, 2 Oct 2019 13:22:55 -0700 Subject: [PATCH 4/4] [XFAIL] Disable Sanitizers/tsan-norace-deinit-run-time.swift (55880585) --- test/Sanitizers/tsan-norace-deinit-run-time.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Sanitizers/tsan-norace-deinit-run-time.swift b/test/Sanitizers/tsan-norace-deinit-run-time.swift index 584448ad319..7fae7a6692e 100644 --- a/test/Sanitizers/tsan-norace-deinit-run-time.swift +++ b/test/Sanitizers/tsan-norace-deinit-run-time.swift @@ -1,6 +1,7 @@ // RUN: %target-swiftc_driver %s -g -sanitize=thread %import-libdispatch -target %sanitizers-target-triple -o %t_tsan-binary // RUN: %target-codesign %t_tsan-binary // RUN: env %env-TSAN_OPTIONS=abort_on_error=0 %target-run %t_tsan-binary 2>&1 | %FileCheck %s --dump-input=fail --implicit-check-not='ThreadSanitizer' +// REQUIRES: rdar55880585 // REQUIRES: executable_test // REQUIRES: tsan_runtime