[sil-aa] Refactor memory behavior implementation to use a visitor instead of a large switch to make things more readable.

This is in preparation for increasing the amount of instructions handled
by memory behavior.

Swift SVN r16788
This commit is contained in:
Michael Gottesman
2014-04-25 00:52:02 +00:00
parent c514e8e9a8
commit 9401b1b0f4

View File

@@ -17,6 +17,7 @@
#include "swift/SIL/Projection.h"
#include "swift/SIL/SILValue.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILVisitor.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILFunction.h"
#include "swift/SIL/SILModule.h"
@@ -438,81 +439,106 @@ AliasAnalysis::AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2) {
return AliasResult::MayAlias;
}
namespace {
using MemBehavior = SILInstruction::MemoryBehavior;
class MemoryBehaviorVisitor
: public SILInstructionVisitor<MemoryBehaviorVisitor, MemBehavior> {
// The alias analysis for any queries we may need.
AliasAnalysis &AA;
// The value we are attempting to discover memory behavior relative to.
SILValue V;
public:
MemoryBehaviorVisitor(AliasAnalysis &AA, SILValue V) : AA(AA), V(V) {}
MemBehavior visitValueBase(ValueBase *V) {
llvm_unreachable("unimplemented");
}
MemBehavior visitSILInstruction(SILInstruction *Inst) {
// If we do not have any more information, just use the general memory
// behavior implementation.
return Inst->getMemoryBehavior();
}
MemBehavior visitLoadInst(LoadInst *LI);
MemBehavior visitStoreInst(StoreInst *SI);
MemBehavior visitApplyInst(ApplyInst *AI);
};
} // end anonymous namespace
MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
// If the load address doesn't alias the given address, it doesn't read or
// write the specified memory.
if (AA.isNoAlias(LI->getOperand(), V)) {
DEBUG(llvm::dbgs() << " Load does not alias inst. Returning None.\n");
return MemBehavior::None;
}
// Otherwise be conservative and just return reads since loads can only
// read.
DEBUG(llvm::dbgs() << " Could not prove load does not alias inst. "
"Returning MayRead.\n");
return MemBehavior::MayRead;
}
MemBehavior MemoryBehaviorVisitor::visitStoreInst(StoreInst *SI) {
// If the store dest cannot alias the pointer in question, then the
// specified value can not be modified by the store.
if (AA.isNoAlias(SI->getDest(), V)) {
DEBUG(llvm::dbgs() << " Store Dst does not alias inst. Returning "
"None.\n");
return MemBehavior::None;
}
// Otherwise, a store just writes.
DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
"Returning MayWrite.\n");
return MemBehavior::MayWrite;
}
MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
// If the ApplyInst is from a no-read builtin it can not read or write and
// if it comes from a no-side effect builtin, it can only read.
auto *BFR = dyn_cast<BuiltinFunctionRefInst>(AI->getCallee());
// If our callee is not a builtin, be conservative and return may have side
// effects.
if (!BFR) {
DEBUG(llvm::dbgs() << " Found apply we don't understand returning "
"MHSF.\n");
return MemBehavior::MayHaveSideEffects;
}
// If the builtin is read none, it does not read or write memory.
if (isReadNone(BFR)) {
DEBUG(llvm::dbgs() << " Found apply of read none builtin. Returning"
" None.\n");
return MemBehavior::None;
}
// If the builtin is side effect free, then it can only read memory.
if (isSideEffectFree(BFR)) {
DEBUG(llvm::dbgs() << " Found apply of side effect free builtin. "
"Returning MayRead.\n");
return MemBehavior::MayRead;
}
// Otherwise be conservative and return that we may have side effects.
DEBUG(llvm::dbgs() << " Found apply of side effect builtin. "
"Returning MayHaveSideEffects.\n");
return MemBehavior::MayHaveSideEffects;
}
SILInstruction::MemoryBehavior
AliasAnalysis::getMemoryBehavior(SILInstruction *Inst, SILValue V) {
DEBUG(llvm::dbgs() << "GET MEMORY BEHAVIOR FOR:\n " << *Inst << " "
<< *V.getDef());
// If we already know that we do not read or write memory, just return None.
if (!Inst->mayReadOrWriteMemory()) {
DEBUG(llvm::dbgs() << " Inst does not write memory. Returning None.\n");
return MemoryBehavior::None;
}
switch (Inst->getKind()) {
case ValueKind::LoadInst:
// If the load address doesn't alias the given address, it doesn't read or
// write the specified memory.
if (isNoAlias(Inst->getOperand(0), V)) {
DEBUG(llvm::dbgs() << " Load does not alias inst. Returning None.\n");
return MemoryBehavior::None;
}
// Otherwise be conservative and just return reads since loads can only
// read.
DEBUG(llvm::dbgs() << " Could not prove load does not alias inst. "
"Returning MayRead.\n");
return MemoryBehavior::MayRead;
case ValueKind::StoreInst:
// If the store dest cannot alias the pointer in question, then the
// specified value can not be modified by the store.
if (isNoAlias(cast<StoreInst>(Inst)->getDest(), V)) {
DEBUG(llvm::dbgs() << " Store Dst does not alias inst. Returning "
"None.\n");
return MemoryBehavior::None;
}
// Otherwise, a store just writes.
DEBUG(llvm::dbgs() << " Could not prove store does not alias inst. "
"Returning MayWrite.\n");
return MemoryBehavior::MayWrite;
case ValueKind::ApplyInst: {
// If the ApplyInst is from a no-read builtin it can not read or write and
// if it comes from a no-side effect builtin, it can only read.
auto *AI = cast<ApplyInst>(Inst);
auto *BFR = dyn_cast<BuiltinFunctionRefInst>(AI->getCallee());
// If our callee is not a builtin, be conservative and return may have side
// effects.
if (!BFR) {
DEBUG(llvm::dbgs() << " Found apply we don't understand returning "
"MHSF.\n");
return MemoryBehavior::MayHaveSideEffects;
}
// If the builtin is read none, it does not read or write memory.
if (isReadNone(BFR)) {
DEBUG(llvm::dbgs() << " Found apply of read none builtin. Returning"
" None.\n");
return MemoryBehavior::None;
}
// If the builtin is side effect free, then it can only read memory.
if (isSideEffectFree(BFR)) {
DEBUG(llvm::dbgs() << " Found apply of side effect free builtin. "
"Returning MayRead.\n");
return MemoryBehavior::MayRead;
}
// Otherwise be conservative and return that we may have side effects.
DEBUG(llvm::dbgs() << " Found apply of side effect builtin. "
"Returning MayHaveSideEffects.\n");
return MemoryBehavior::MayHaveSideEffects;
}
default:
// If we do not have a special case, just return the generic memory
// behavior of Inst.
return Inst->getMemoryBehavior();
}
return MemoryBehaviorVisitor(*this, V).visit(Inst);
}
SILAnalysis *swift::createAliasAnalysis(SILModule *M) {