[g-arc-opts] Perform same refactoring for top down analysis as I performed for bottom up analysis in r26901.

Swift SVN r26906
This commit is contained in:
Michael Gottesman
2015-04-02 22:07:28 +00:00
parent 5c8fde3f2e
commit 9b77fe1cb1
4 changed files with 141 additions and 74 deletions

View File

@@ -24,7 +24,6 @@
#include "swift/SIL/SILModule.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Debug.h"
using namespace swift;
@@ -33,21 +32,6 @@ using namespace swift;
// Utilities
//===----------------------------------------------------------------------===//
static bool isAutoreleasePoolCall(SILInstruction &I) {
ApplyInst *AI = dyn_cast<ApplyInst>(&I);
if (!AI)
return false;
FunctionRefInst *FRI = dyn_cast<FunctionRefInst>(AI->getCallee());
if (!FRI)
return false;
return llvm::StringSwitch<bool>(FRI->getReferencedFunction()->getName())
.Case("objc_autoreleasePoolPush", true)
.Case("objc_autoreleasePoolPop", true)
.Default(false);
}
namespace {
using ARCBBState = ARCSequenceDataflowEvaluator::ARCBBState;
@@ -102,72 +86,28 @@ static bool processBBTopDown(
}
}
TopDownDataflowRCStateVisitor DataflowVisitor(RCIA, BBState,
DecToIncStateMap);
// For each instruction I in BB...
for (auto &I : BB) {
DEBUG(llvm::dbgs() << "VISITING:\n " << I);
// If we see an autorelease pool call, be conservative and clear all state
// that we are currently tracking in the BB.
if (isAutoreleasePoolCall(I)) {
BBState.clear();
auto Result = DataflowVisitor.visit(&I);
// If this instruction can have no further effects on another instructions,
// continue. This happens for instance if we have cleared all of the state
// we are tracking.
if (Result.Kind == RCStateTransitionDataflowResultKind::NoEffects)
continue;
}
SILValue Op;
RCStateTransitionKind TransitionKind = getRCStateTransitionKind(&I);
// Make sure that we propagate out whether or not nesting was detected.
NestingDetected |= Result.NestingDetected;
// If I is a ref count increment instruction...
if (TransitionKind == RCStateTransitionKind::StrongIncrement) {
// map its operand to a newly initialized or reinitialized ref count
// state and continue...
Op = RCIA->getRCIdentityRoot(I.getOperand(0));
TopDownRefCountState &State = BBState.getTopDownRefCountState(Op);
NestingDetected |= State.initWithInst(&I);
DEBUG(llvm::dbgs() << " REF COUNT INCREMENT! Known Safe: "
<< (State.isKnownSafe() ? "yes" : "no") << "\n");
// Continue processing in case this increment could be a CanUse for a
// different pointer.
}
// If we have a reference count decrement...
if (TransitionKind == RCStateTransitionKind::StrongDecrement) {
// Look up the state associated with its operand...
Op = RCIA->getRCIdentityRoot(I.getOperand(0));
TopDownRefCountState &RefCountState = BBState.getTopDownRefCountState(Op);
DEBUG(llvm::dbgs() << " REF COUNT DECREMENT!\n");
// If we are tracking an increment on the ref count root associated with
// the decrement and the decrement matches, pair this decrement with a
// copy of the increment state and then clear the original increment state
// so that we are ready to process further values.
if (RefCountState.isRefCountInstMatchedToTrackedInstruction(&I)) {
// Copy the current value of ref count state into the result map.
DecToIncStateMap[&I] = RefCountState;
DEBUG(llvm::dbgs() << " MATCHING INCREMENT:\n"
<< RefCountState.getRCRoot());
// Clear the ref count state in preparation for more pairs.
RefCountState.clear();
}
#if NDEBUG
else {
if (RefCountState.isTrackingRefCountInst()) {
DEBUG(llvm::dbgs() << " FAILED MATCH INCREMENT:\n"
<< RefCountState.getValue());
} else {
DEBUG(llvm::dbgs() << " FAILED MATCH. NO INCREMENT.\n");
}
}
#endif
// Otherwise we continue processing the reference count decrement to
// see if the decrement can affect any other pointers that we are
// tracking.
}
// This SILValue may be null if we were unable to find a specific RCIdentity
// that the instruction "visits".
SILValue Op = Result.RCIdentity;
// For all other [(SILValue, TopDownState)] we are tracking...
for (auto &OtherState : BBState.getTopDownStates()) {

View File

@@ -11,12 +11,34 @@
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "sil-global-arc-opts"
#include "RCStateTransition.h"
#include "swift/Basic/Fallthrough.h"
#include "swift/SIL/SILInstruction.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Support/Debug.h"
using namespace swift;
//===----------------------------------------------------------------------===//
// Utility
//===----------------------------------------------------------------------===//
static bool isAutoreleasePoolCall(SILInstruction *I) {
auto *AI = dyn_cast<ApplyInst>(I);
if (!AI)
return false;
auto *FRI = dyn_cast<FunctionRefInst>(AI->getCallee());
if (!FRI)
return false;
return llvm::StringSwitch<bool>(FRI->getReferencedFunction()->getName())
.Case("objc_autoreleasePoolPush", true)
.Case("objc_autoreleasePoolPop", true)
.Default(false);
}
//===----------------------------------------------------------------------===//
// RCStateTransitionKind
//===----------------------------------------------------------------------===//
@@ -39,6 +61,10 @@ RCStateTransitionKind swift::getRCStateTransitionKind(ValueBase *V) {
return RCStateTransitionKind::Unknown;
}
case ValueKind::ApplyInst:
if (isAutoreleasePoolCall(cast<SILInstruction>(V)))
return RCStateTransitionKind::AutoreleasePoolCall;
SWIFT_FALLTHROUGH;
default:
return RCStateTransitionKind::Unknown;
}

View File

@@ -101,3 +101,71 @@ BottomUpDataflowRCStateVisitor::visitStrongIncrement(SILInstruction *I) {
#endif
return DataflowResult(Op);
}
//===----------------------------------------------------------------------===//
// TopDownDataflowRCStateVisitor
//===----------------------------------------------------------------------===//
TopDownDataflowRCStateVisitor::TopDownDataflowRCStateVisitor(
RCIdentityFunctionInfo *RCFI, ARCBBState &BBState,
DecToIncStateMapTy &DecToIncStateMap)
: RCFI(RCFI), BBState(BBState), DecToIncStateMap(DecToIncStateMap) {}
TopDownDataflowRCStateVisitor::DataflowResult
TopDownDataflowRCStateVisitor::visitAutoreleasePoolCall(SILInstruction *I) {
BBState.clear();
return DataflowResult();
}
TopDownDataflowRCStateVisitor::DataflowResult
TopDownDataflowRCStateVisitor::visitStrongDecrement(SILInstruction *I) {
// Look up the state associated with I's operand...
SILValue Op = RCFI->getRCIdentityRoot(I->getOperand(0));
TopDownRefCountState &RefCountState = BBState.getTopDownRefCountState(Op);
DEBUG(llvm::dbgs() << " REF COUNT DECREMENT!\n");
// If we are tracking an increment on the ref count root associated with
// the decrement and the decrement matches, pair this decrement with a
// copy of the increment state and then clear the original increment state
// so that we are ready to process further values.
if (RefCountState.isRefCountInstMatchedToTrackedInstruction(I)) {
// Copy the current value of ref count state into the result map.
DecToIncStateMap[I] = RefCountState;
DEBUG(llvm::dbgs() << " MATCHING INCREMENT:\n"
<< RefCountState.getRCRoot());
// Clear the ref count state in preparation for more pairs.
RefCountState.clear();
}
#if NDEBUG
else {
if (RefCountState.isTrackingRefCountInst()) {
DEBUG(llvm::dbgs() << " FAILED MATCH INCREMENT:\n"
<< RefCountState.getValue());
} else {
DEBUG(llvm::dbgs() << " FAILED MATCH. NO INCREMENT.\n");
}
}
#endif
// Otherwise we continue processing the reference count decrement to see if
// the decrement can affect any other pointers that we are tracking.
return DataflowResult(Op);
}
TopDownDataflowRCStateVisitor::DataflowResult
TopDownDataflowRCStateVisitor::visitStrongIncrement(SILInstruction *I) {
// Map the increment's operand to a newly initialized or reinitialized ref
// count state and continue...
SILValue Op = RCFI->getRCIdentityRoot(I->getOperand(0));
TopDownRefCountState &State = BBState.getTopDownRefCountState(Op);
bool NestingDetected = State.initWithInst(I);
DEBUG(llvm::dbgs() << " REF COUNT INCREMENT! Known Safe: "
<< (State.isKnownSafe() ? "yes" : "no") << "\n");
// Continue processing in case this increment could be a CanUse for a
// different pointer.
return DataflowResult(Op, NestingDetected);
}

View File

@@ -130,4 +130,37 @@ public:
} // end swift namespace
//===----------------------------------------------------------------------===//
// TopDownDataflowRCStateVisitor
//===----------------------------------------------------------------------===//
namespace swift {
/// A visitor for performing the bottom up dataflow depending on the
/// RCState. Enables behavior to be cleanly customized depending on the
/// RCStateTransition associated with an instruction.
class TopDownDataflowRCStateVisitor
: public RCStateTransitionKindVisitor<TopDownDataflowRCStateVisitor,
RCStateTransitionDataflowResult> {
/// A local typedef to make things cleaner.
using DataflowResult = RCStateTransitionDataflowResult;
using ARCBBState = ARCSequenceDataflowEvaluator::ARCBBState;
using DecToIncStateMapTy =
BlotMapVector<SILInstruction *, TopDownRefCountState>;
RCIdentityFunctionInfo *RCFI;
ARCBBState &BBState;
DecToIncStateMapTy &DecToIncStateMap;
public:
TopDownDataflowRCStateVisitor(RCIdentityFunctionInfo *RCFI,
ARCBBState &BBState,
DecToIncStateMapTy &DecToIncStateMap);
DataflowResult visitAutoreleasePoolCall(SILInstruction *I);
DataflowResult visitStrongDecrement(SILInstruction *I);
DataflowResult visitStrongIncrement(SILInstruction *I);
};
} // end swift namespace
#endif