Skip to content

Commit

Permalink
[loop-arc] Remove the opaque ARC pairing interfaces.
Browse files Browse the repository at this point in the history
Now ARCSequenceOpts accesses the ARCPairingContexts directly. This enables us to
avoid a malloc/free and should simplify the whole interface.
  • Loading branch information
gottesmm committed Nov 27, 2015
1 parent 9b211d4 commit a768dc2
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 195 deletions.
52 changes: 7 additions & 45 deletions lib/SILPasses/ARC/ARCSequenceOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ void CodeMotionOrDeleteCallback::processMatchingSet(ARCMatchingSet &MatchSet) {
//===----------------------------------------------------------------------===//

static bool processFunctionWithoutLoopSupport(SILFunction &F,
bool FreezePostDomRelease,
bool FreezePostDomReleases,
AliasAnalysis *AA,
PostOrderAnalysis *POTA,
RCIdentityFunctionInfo *RCIA) {
Expand All @@ -174,21 +174,7 @@ static bool processFunctionWithoutLoopSupport(SILFunction &F,
DEBUG(llvm::dbgs() << "***** Processing " << F.getName() << " *****\n");

bool Changed = false;

// Construct our context once. A context contains the RPOT as well as maps
// that contain state for each BB in F. This is a major place where the
// optimizer allocates memory in one large chunk.
auto *Ctx = createARCMatchingSetComputationContext(F, AA, POTA, nullptr,
nullptr, RCIA, false);

// If Ctx is null, we failed to initialize and can not do anything so just
// return false.
if (!Ctx) {
DEBUG(llvm::dbgs() << " Failed to initialize matching set computation "
"context! Bailing!\n");
return false;
}

BlockARCPairingContext Context(F, AA, POTA, RCIA);
CodeMotionOrDeleteCallback Callback;
// Until we do not remove any instructions or have nested increments,
// decrements...
Expand All @@ -199,8 +185,7 @@ static bool processFunctionWithoutLoopSupport(SILFunction &F,
// We need to blot pointers we remove after processing an individual pointer
// so we don't process pairs after we have paired them up. Thus we pass in a
// lambda that performs the work for us.
bool ShouldRunAgain =
computeARCMatchingSet(Ctx, FreezePostDomRelease, Callback);
bool ShouldRunAgain = Context.run(FreezePostDomReleases, Callback);

Changed |= Callback.madeChange();

Expand All @@ -213,10 +198,6 @@ static bool processFunctionWithoutLoopSupport(SILFunction &F,
DEBUG(llvm::dbgs() << "\n<<< Made a Change! Reprocessing Function! >>>\n");
}

// Now that we have finished our computation, destroy the matching set
// computation context.
destroyARCMatchingSetComputationContext(Ctx);

DEBUG(llvm::dbgs() << "\n");

// Return true if we moved or deleted any instructions.
Expand All @@ -228,10 +209,10 @@ static bool processFunctionWithoutLoopSupport(SILFunction &F,
//===----------------------------------------------------------------------===//

static bool
processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomRelease,
processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomReleases,
AliasAnalysis *AA, PostOrderAnalysis *POTA,
LoopRegionFunctionInfo *LRFI, SILLoopInfo *LI,
RCIdentityFunctionInfo *RCIA) {
RCIdentityFunctionInfo *RCFI) {
// GlobalARCOpts seems to be taking up a lot of compile time when running on
// globalinit_func. Since that is not *that* interesting from an ARC
// perspective (i.e. no ref count operations in a loop), disable it on such
Expand All @@ -242,21 +223,7 @@ processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomRelease,
DEBUG(llvm::dbgs() << "***** Processing " << F.getName() << " *****\n");

bool Changed = false;

// Construct our context once. A context contains the RPOT as well as maps
// that contain state for each BB in F. This is a major place where the
// optimizer allocates memory in one large chunk.
auto *Ctx =
createARCMatchingSetComputationContext(F, AA, POTA, LRFI, LI, RCIA, true);

// If Ctx is null, we failed to initialize and can not do anything so just
// return false.
if (!Ctx) {
DEBUG(llvm::dbgs() << " Failed to initialize matching set computation "
"context! Bailing!\n");
return false;
}

LoopARCPairingContext Context(F, AA, LRFI, LI, RCFI);
CodeMotionOrDeleteCallback Callback;
// Until we do not remove any instructions or have nested increments,
// decrements...
Expand All @@ -267,8 +234,7 @@ processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomRelease,
// We need to blot pointers we remove after processing an individual pointer
// so we don't process pairs after we have paired them up. Thus we pass in a
// lambda that performs the work for us.
bool ShouldRunAgain =
computeARCMatchingSet(Ctx, FreezePostDomRelease, Callback);
bool ShouldRunAgain = Context.run(FreezePostDomReleases, Callback);

Changed |= Callback.madeChange();

Expand All @@ -281,10 +247,6 @@ processFunctionWithLoopSupport(SILFunction &F, bool FreezePostDomRelease,
DEBUG(llvm::dbgs() << "\n<<< Made a Change! Reprocessing Function! >>>\n");
}

// Now that we have finished our computation, destroy the matching set
// computation context.
destroyARCMatchingSetComputationContext(Ctx);

DEBUG(llvm::dbgs() << "\n");

// Return true if we moved or deleted any instructions.
Expand Down
137 changes: 13 additions & 124 deletions lib/SILPasses/ARC/GlobalARCPairingAnalysis.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -357,29 +357,10 @@ bool ARCMatchingSetBuilder::matchUpIncDecSetsForPtr() {
}

//===----------------------------------------------------------------------===//
// ARC Matching Set Computation Context
// ARC Pairing Context
//===----------------------------------------------------------------------===//

namespace swift {

struct ARCMatchingSetComputationContext {
SILFunction &F;
BlotMapVector<SILInstruction *, TopDownRefCountState> DecToIncStateMap;
BlotMapVector<SILInstruction *, BottomUpRefCountState> IncToDecStateMap;
RCIdentityFunctionInfo *RCIA;

ARCMatchingSetComputationContext(SILFunction &F, RCIdentityFunctionInfo *RCIA)
: F(F), DecToIncStateMap(), IncToDecStateMap(), RCIA(RCIA) {}
virtual ~ARCMatchingSetComputationContext() {}
virtual bool run(bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) = 0;
bool performMatching(ARCMatchingSetCallback &Callback);
};

} // end swift namespace

bool ARCMatchingSetComputationContext::performMatching(
ARCMatchingSetCallback &Callback) {
bool ARCPairingContext::performMatching(ARCMatchingSetCallback &Callback) {
bool MatchedPair = false;

DEBUG(llvm::dbgs() << "**** Computing ARC Matching Sets for " << F.getName()
Expand Down Expand Up @@ -419,85 +400,31 @@ bool ARCMatchingSetComputationContext::performMatching(
return MatchedPair;
}

//===----------------------------------------------------------------------===//
// Block ARC
//===----------------------------------------------------------------------===//

namespace {

struct BlockARCMatchingSetComputationContext
: ARCMatchingSetComputationContext {

ARCSequenceDataflowEvaluator Evaluator;

BlockARCMatchingSetComputationContext(SILFunction &F, AliasAnalysis *AA,
PostOrderAnalysis *POTA,
RCIdentityFunctionInfo *RCFI)
: ARCMatchingSetComputationContext(F, RCFI),
Evaluator(F, AA, POTA, RCIA, DecToIncStateMap, IncToDecStateMap) {}
virtual ~BlockARCMatchingSetComputationContext() override final {}

virtual bool run(bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) override final {
bool NestingDetected = Evaluator.run(FreezePostDomReleases);
Evaluator.clear();

bool MatchedPair = performMatching(Callback);
return NestingDetected && MatchedPair;
}
};

} // end anonymous namespace

//===----------------------------------------------------------------------===//
// Loop ARC
//===----------------------------------------------------------------------===//

namespace {

struct LoopARCMatchingSetComputationContext : ARCMatchingSetComputationContext {
LoopARCSequenceDataflowEvaluator Evaluator;
LoopRegionFunctionInfo *LRFI;
SILLoopInfo *SLI;

LoopARCMatchingSetComputationContext(SILFunction &F, AliasAnalysis *AA,
LoopRegionFunctionInfo *LRFI,
SILLoopInfo *SLI,
RCIdentityFunctionInfo *RCFI)
: ARCMatchingSetComputationContext(F, RCFI),
Evaluator(F, AA, LRFI, SLI, RCIA, DecToIncStateMap, IncToDecStateMap),
LRFI(LRFI), SLI(SLI) {}
virtual ~LoopARCMatchingSetComputationContext() override final {}

virtual bool run(bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) override final;
void processLoop(const LoopRegion *R, bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback);
};

} // end anonymous namespace

void LoopARCMatchingSetComputationContext::processLoop(
const LoopRegion *Region, bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) {
void LoopARCPairingContext::processLoop(const LoopRegion *Region,
bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) {
bool NestingDetected = Evaluator.runOnLoop(Region, FreezePostDomReleases);
bool MatchedPair = performMatching(Callback);
DecToIncStateMap.clear();
IncToDecStateMap.clear();
bool MatchedPair = Context.performMatching(Callback);
Context.DecToIncStateMap.clear();
Context.IncToDecStateMap.clear();

while (NestingDetected && MatchedPair) {
Evaluator.clearLoopState(Region);
NestingDetected = Evaluator.runOnLoop(Region, FreezePostDomReleases);
MatchedPair = performMatching(Callback);
DecToIncStateMap.clear();
IncToDecStateMap.clear();
MatchedPair = Context.performMatching(Callback);
Context.DecToIncStateMap.clear();
Context.IncToDecStateMap.clear();
}

Evaluator.summarizeLoop(Region);
}

bool LoopARCMatchingSetComputationContext::run(
bool FreezePostDomReleases, ARCMatchingSetCallback &Callback) {
bool LoopARCPairingContext::run(bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) {
// We visit the loop nest inside out via a depth first, post order using this
// worklist.
llvm::SmallVector<std::pair<SILLoop *, bool>, 32> Worklist;
Expand Down Expand Up @@ -527,41 +454,3 @@ bool LoopARCMatchingSetComputationContext::run(
// externally.
return false;
}

//===----------------------------------------------------------------------===//
// Top Level EntryPoints
//===----------------------------------------------------------------------===//

ARCMatchingSetComputationContext *swift::createARCMatchingSetComputationContext(
SILFunction &F, AliasAnalysis *AA, PostOrderAnalysis *POTA,
LoopRegionFunctionInfo *LRFI, SILLoopInfo *SLI,
RCIdentityFunctionInfo *RCFI, bool EnableLoopARC) {
unsigned Size = F.size();

// We do not handle CFGs with more than INT_MAX BBs. Fail gracefully.
if (Size > unsigned(INT_MAX))
return nullptr;

// We pass in size to avoid expensively recomputing size over and over
// again. Currently F has to do a walk to perform that computation.
if (EnableLoopARC) {
return new LoopARCMatchingSetComputationContext(F, AA, LRFI, SLI, RCFI);
}
return new BlockARCMatchingSetComputationContext(F, AA, POTA, RCFI);
}

void
swift::
destroyARCMatchingSetComputationContext(ARCMatchingSetComputationContext *Ctx) {
delete Ctx;
}

bool swift::computeARCMatchingSet(ARCMatchingSetComputationContext *Ctx,
bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback) {

DEBUG(llvm::dbgs() << "**** Performing ARC Dataflow for " << Ctx->F.getName()
<< " ****\n");

return Ctx->run(FreezePostDomReleases, Callback);
}
75 changes: 49 additions & 26 deletions lib/SILPasses/ARC/GlobalARCPairingAnalysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#ifndef SWIFT_SILPASSES_GLOBALARCPAIRINGANALYSIS_H
#define SWIFT_SILPASSES_GLOBALARCPAIRINGANALYSIS_H

#include "GlobalARCSequenceDataflow.h"
#include "GlobalLoopARCSequenceDataflow.h"
#include "swift/SIL/SILValue.h"
#include "llvm/ADT/SetVector.h"

Expand Down Expand Up @@ -51,21 +53,6 @@ struct ARCMatchingSet {
}
};

/// An opaque context that contains cached information that can be used on
/// multiple calls to computeARCMatchingSet on the same function.
struct ARCMatchingSetComputationContext;

/// Create an opaque arc mutation set computation context for SILFunction F
/// using AliasAnalysis AA.
ARCMatchingSetComputationContext *createARCMatchingSetComputationContext(
SILFunction &F, AliasAnalysis *AA, PostOrderAnalysis *POTA,
LoopRegionFunctionInfo *LRFI, SILLoopInfo *SLI,
RCIdentityFunctionInfo *RCIA, bool EnableLoopARC = false);

/// Destroy the context.
void
destroyARCMatchingSetComputationContext(ARCMatchingSetComputationContext *Ctx);

/// A structure that via its virtual calls recieves the results of the analysis.
///
/// TODO: We could potentially pass in all of the matching sets as a list and
Expand All @@ -84,17 +71,53 @@ struct ARCMatchingSetCallback {
virtual void finalize() {}
};

/// Use the opaque context to recompute the matching set for the input function.
///
/// \param Ctx The opaque context for the computation.
/// \param FreezeOwningPtrEpiloqueReleases Should we not attempt to move, remove
/// epilogue release pointers and instead use them as post dominating releases
/// for other pointers.
/// \param Callback The callback used to propagate information to analysis
/// users.
bool computeARCMatchingSet(ARCMatchingSetComputationContext *Ctx,
bool FreezeOwningPtrEpiloqueReleases,
ARCMatchingSetCallback &Callback);
struct ARCPairingContext {
SILFunction &F;
BlotMapVector<SILInstruction *, TopDownRefCountState> DecToIncStateMap;
BlotMapVector<SILInstruction *, BottomUpRefCountState> IncToDecStateMap;
RCIdentityFunctionInfo *RCIA;

ARCPairingContext(SILFunction &F, RCIdentityFunctionInfo *RCIA)
: F(F), DecToIncStateMap(), IncToDecStateMap(), RCIA(RCIA) {}
bool performMatching(ARCMatchingSetCallback &Callback);
};

struct BlockARCPairingContext {
ARCPairingContext Context;
ARCSequenceDataflowEvaluator Evaluator;

BlockARCPairingContext(SILFunction &F, AliasAnalysis *AA,
PostOrderAnalysis *POTA, RCIdentityFunctionInfo *RCFI)
: Context(F, RCFI), Evaluator(F, AA, POTA, RCFI, Context.DecToIncStateMap,
Context.IncToDecStateMap) {}

bool run(bool FreezePostDomReleases, ARCMatchingSetCallback &Callback) {
bool NestingDetected = Evaluator.run(FreezePostDomReleases);
Evaluator.clear();

bool MatchedPair = Context.performMatching(Callback);
return NestingDetected && MatchedPair;
}
};

struct LoopARCPairingContext {
ARCPairingContext Context;
LoopARCSequenceDataflowEvaluator Evaluator;
LoopRegionFunctionInfo *LRFI;
SILLoopInfo *SLI;

LoopARCPairingContext(SILFunction &F, AliasAnalysis *AA,
LoopRegionFunctionInfo *LRFI, SILLoopInfo *SLI,
RCIdentityFunctionInfo *RCFI)
: Context(F, RCFI),
Evaluator(F, AA, LRFI, SLI, RCFI, Context.DecToIncStateMap,
Context.IncToDecStateMap),
LRFI(LRFI), SLI(SLI) {}

bool run(bool FreezePostDomReleases, ARCMatchingSetCallback &Callback);
void processLoop(const LoopRegion *R, bool FreezePostDomReleases,
ARCMatchingSetCallback &Callback);
};

} // end swift namespace

Expand Down

0 comments on commit a768dc2

Please sign in to comment.