mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user