Files
swift-mirror/lib/SILOptimizer/ARC/GlobalLoopARCSequenceDataflow.h
Michael Gottesman f718111a4f [arc] Integrate ImmutablePointerSet{,Factory} into ARC Sequence Opts.
This speeds and reduces memory consumption of test cases with large
CFGs. The specific test case that spawned this fix was a large function
with many dictionary assignments:

public func func_0(dictIn : [String : MyClass]) -> [String : MyClass] {
  var dictOut : [String : MyClass] = [:]
  dictOut["key5000"] = dictIn["key500"]
  dictOut["key5010"] = dictIn["key501"]
  dictOut["key5020"] = dictIn["key502"]
  dictOut["key5030"] = dictIn["key503"]
  dictOut["key5040"] = dictIn["key504"]
  ...
}

This continued for 10k - 20k values.

This commit reduces the compile time by 2.5x and reduces the amount of
memory allocated by ARC by 2.6x (the memory allocation number includes
memory that is subsequently freed).

rdar://24350646
2016-02-14 15:26:59 -08:00

139 lines
5.2 KiB
C++

//===--- GlobalLoopARCSequenceDataflow.h ------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See http://swift.org/LICENSE.txt for license information
// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_GLOBALLOOPARCSEQUENCEDATAFLOW_H
#define SWIFT_SILOPTIMIZER_PASSMANAGER_ARC_GLOBALLOOPARCSEQUENCEDATAFLOW_H
#include "RefCountState.h"
#include "swift/SILOptimizer/Analysis/LoopRegionAnalysis.h"
#include "swift/SILOptimizer/Analysis/ProgramTerminationAnalysis.h"
#include "swift/Basic/BlotMapVector.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/Basic/ImmutablePointerSet.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/Optional.h"
namespace swift {
class SILFunction;
class AliasAnalysis;
} // end swift namespace
namespace swift {
// Forward declaration of private classes that are opaque in this header.
class ARCRegionState;
/// A class that implements the ARC sequence data flow.
class LoopARCSequenceDataflowEvaluator {
/// The bump ptr allocator that is used to allocate memory in the allocator.
llvm::BumpPtrAllocator Allocator;
/// The factory that we use to generate immutable pointer sets.
ImmutablePointerSetFactory<SILInstruction> SetFactory;
/// The SILFunction that we are applying the dataflow to.
SILFunction &F;
/// The alias analysis that we are using for alias queries.
AliasAnalysis *AA;
/// Loop region information that we use to perform dataflow up and down the
/// loop nest.
LoopRegionFunctionInfo *LRFI;
/// The loop info we use for convenience to seed our traversals.
SILLoopInfo *SLI;
/// An analysis which computes the identity root of a SILValue(), i.e. the
/// dominating origin SILValue of the reference count that by retaining or
/// releasing this value one is affecting.
RCIdentityFunctionInfo *RCFI;
/// The map from dataflow terminating decrements -> increment dataflow state.
BlotMapVector<SILInstruction *, TopDownRefCountState> &DecToIncStateMap;
/// The map from dataflow terminating increment -> decrement dataflow state.
BlotMapVector<SILInstruction *, BottomUpRefCountState> &IncToDecStateMap;
/// Stashed information for each region.
llvm::DenseMap<const LoopRegion *, ARCRegionState *> RegionStateInfo;
/// This is meant to find releases matched to consumed arguments. This is
/// really less interesting than keeping a stash of all of the reference
/// counted values that we have seen and computing their last post dominating
/// consumed argument. But I am going to leave this in for now.
ConsumedArgToEpilogueReleaseMatcher ConsumedArgToReleaseMap;
public:
LoopARCSequenceDataflowEvaluator(
SILFunction &F, AliasAnalysis *AA, LoopRegionFunctionInfo *LRFI,
SILLoopInfo *SLI, RCIdentityFunctionInfo *RCIA,
ProgramTerminationFunctionInfo *PTFI,
BlotMapVector<SILInstruction *, TopDownRefCountState> &DecToIncStateMap,
BlotMapVector<SILInstruction *, BottomUpRefCountState> &IncToDecStateMap);
~LoopARCSequenceDataflowEvaluator();
SILFunction *getFunction() const { return &F; }
/// Clear all of the state associated with the given loop.
void clearLoopState(const LoopRegion *R);
/// Perform the sequence dataflow, bottom up and top down on the loop region
/// \p R.
bool runOnLoop(const LoopRegion *R, bool FreezeOwnedArgEpilogueReleases,
bool RecomputePostDomReleases);
/// Summarize the subregions of \p R that are blocks.
///
/// We assume that all subregions that are loops have already been summarized
/// since we are processing bottom up through the loop nest hierarchy.
void summarizeSubregionBlocks(const LoopRegion *R);
/// Summarize the contents of the loop so that loops further up the loop tree
/// can reason about the loop.
void summarizeLoop(const LoopRegion *R);
/// Add \p I to the interesting instruction list of its parent block.
void addInterestingInst(SILInstruction *I);
/// Remove \p I from the interesting instruction list of its parent block.
void removeInterestingInst(SILInstruction *I);
private:
/// Merge in the BottomUp state of any successors of DataHandle.getBB() into
/// DataHandle.getState().
void mergeSuccessors(const LoopRegion *R, ARCRegionState &State);
/// Merge in the TopDown state of any predecessors of DataHandle.getBB() into
/// DataHandle.getState().
void mergePredecessors(const LoopRegion *R, ARCRegionState &State);
void computePostDominatingConsumedArgMap();
ARCRegionState &getARCState(const LoopRegion *L) {
auto Iter = RegionStateInfo.find(L);
assert(Iter != RegionStateInfo.end() && "Should have created state for "
"each region");
return *Iter->second;
}
bool processLoopTopDown(const LoopRegion *R);
bool processLoopBottomUp(const LoopRegion *R,
bool FreezeOwnedArgEpilogueReleases);
};
} // end swift namespace
#endif