mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[sil-aa] Change TBAA to use type oracle instructions instead of the raw types of instructions.
The reason that this is important is that we *ARE* allowing the stdlib to perform certain types of type punning for efficiency implying we need to have a type oracle instruction to have safety. A type oracle instruction is an instruction which implies undefined behavior unless its operand/result is of a certain type (allowing us to ignore that possibility). In a following commit I am going to go over and fix any problems in the actual TBAA implementation and give all the various checks tests. rdar://16651852 Swift SVN r18090
This commit is contained in:
@@ -330,12 +330,13 @@ static bool aggregateContainsRecord(NominalTypeDecl *Aggregate, Type Record,
|
||||
///
|
||||
/// Currently this only implements typed access based TBAA. See the TBAA section
|
||||
/// in the SIL reference manual.
|
||||
static bool typesMayAlias(SILType T1, SILType T2, SILModule &Mod) {
|
||||
static bool typedAccessTBAAMayAlias(SILType T1, SILType T2, SILModule &Mod) {
|
||||
#ifndef NDEBUG
|
||||
if (!shouldRunTypedAccessTBAA())
|
||||
return true;
|
||||
#endif
|
||||
|
||||
// If the two types are the same
|
||||
if (T1 == T2)
|
||||
return true;
|
||||
|
||||
@@ -400,13 +401,26 @@ static bool typesMayAlias(SILType T1, SILType T2, SILModule &Mod) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool typesMayAlias(SILType T1, SILType T2, SILType TBAA1Ty,
|
||||
SILType TBAA2Ty, SILModule &Mod) {
|
||||
// Perform type access based TBAA if we have TBAA info.
|
||||
if (TBAA1Ty && TBAA2Ty)
|
||||
return typedAccessTBAAMayAlias(TBAA1Ty, TBAA2Ty, Mod);
|
||||
|
||||
// Otherwise perform class based TBAA. This is not implemented currently so
|
||||
// just return true.
|
||||
return true;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Entry Points
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// The main AA entry point. Performs various analyses on V1, V2 in an attempt
|
||||
/// to disambiguate the two values.
|
||||
AliasAnalysis::AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2) {
|
||||
AliasAnalysis::AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2,
|
||||
SILType TBAAType1,
|
||||
SILType TBAAType2) {
|
||||
#ifndef NDEBUG
|
||||
// If alias analysis is disabled, always return may alias.
|
||||
if (!shouldRunAA())
|
||||
@@ -420,7 +434,9 @@ AliasAnalysis::AliasResult AliasAnalysis::alias(SILValue V1, SILValue V2) {
|
||||
DEBUG(llvm::dbgs() << "ALIAS ANALYSIS:\n V1: " << *V1.getDef()
|
||||
<< " V2: " << *V2.getDef());
|
||||
|
||||
if (!typesMayAlias(V1.getType(), V2.getType(), *Mod))
|
||||
// Pass in both the TBAA types so we can perform typed access TBAA and the
|
||||
// actual types of V1, V2 so we can perform class based TBAA.
|
||||
if (!typesMayAlias(V1.getType(), V2.getType(), TBAAType1, TBAAType2, *Mod))
|
||||
return AliasResult::NoAlias;
|
||||
|
||||
#ifndef NDEBUG
|
||||
@@ -523,6 +539,7 @@ public:
|
||||
return Inst->getMemoryBehavior();
|
||||
}
|
||||
|
||||
MemBehavior visitLoadInst(LoadInst *LI);
|
||||
MemBehavior visitStoreInst(StoreInst *SI);
|
||||
MemBehavior visitApplyInst(ApplyInst *AI);
|
||||
|
||||
@@ -544,7 +561,6 @@ public:
|
||||
return MemBehavior::None; \
|
||||
}
|
||||
|
||||
OPERANDALIAS_MEMBEHAVIOR_INST(LoadInst)
|
||||
OPERANDALIAS_MEMBEHAVIOR_INST(InjectEnumAddrInst)
|
||||
OPERANDALIAS_MEMBEHAVIOR_INST(UncheckedTakeEnumDataAddrInst)
|
||||
OPERANDALIAS_MEMBEHAVIOR_INST(InitExistentialInst)
|
||||
@@ -584,10 +600,60 @@ public:
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
/// Is this an instruction that can act as a type "oracle" allowing typed access
|
||||
/// TBAA to know what the real types associated with the SILInstruction are.
|
||||
static bool isTypedAccessOracle(SILInstruction *I) {
|
||||
switch (I->getKind()) {
|
||||
case ValueKind::RefElementAddrInst:
|
||||
case ValueKind::StructElementAddrInst:
|
||||
case ValueKind::TupleElementAddrInst:
|
||||
case ValueKind::UncheckedTakeEnumDataAddrInst:
|
||||
case ValueKind::LoadInst:
|
||||
case ValueKind::StoreInst:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// Look at the origin/user ValueBase of V to see if any of them are
|
||||
/// TypedAccessOracle which enable one to ascertain via undefined behavior the
|
||||
/// "true" type of the instruction.
|
||||
static SILType findTypedAccessType(SILValue V) {
|
||||
// First look at the origin of V and see if we have any instruction that is a
|
||||
// typed oracle.
|
||||
if (auto *I = dyn_cast<SILInstruction>(V))
|
||||
if (isTypedAccessOracle(I))
|
||||
return V.getType();
|
||||
|
||||
// Then look at any uses of V that potentially could act as a typed access
|
||||
// oracle.
|
||||
for (auto Use : V.getUses())
|
||||
if (isTypedAccessOracle(Use->getUser()))
|
||||
return V.getType();
|
||||
|
||||
// Otherwise return an empty SILType
|
||||
return SILType();
|
||||
}
|
||||
|
||||
MemBehavior MemoryBehaviorVisitor::visitLoadInst(LoadInst *LI) {
|
||||
if (AA.isNoAlias(LI->getOperand(), V, LI->getOperand().getType(),
|
||||
findTypedAccessType(V))) {
|
||||
DEBUG(llvm::dbgs() << " Load Operand does not alias inst. Returning "
|
||||
"None.\n");
|
||||
return MemBehavior::None;
|
||||
}
|
||||
|
||||
DEBUG(llvm::dbgs() << " Could not prove that load inst does not alias "
|
||||
"pointer. Returning may read.");
|
||||
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)) {
|
||||
if (AA.isNoAlias(SI->getDest(), V, SI->getDest().getType(),
|
||||
findTypedAccessType(V))) {
|
||||
DEBUG(llvm::dbgs() << " Store Dst does not alias inst. Returning "
|
||||
"None.\n");
|
||||
return MemBehavior::None;
|
||||
@@ -618,6 +684,7 @@ MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
|
||||
" 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. "
|
||||
@@ -625,6 +692,10 @@ MemBehavior MemoryBehaviorVisitor::visitApplyInst(ApplyInst *AI) {
|
||||
return MemBehavior::MayRead;
|
||||
}
|
||||
|
||||
// FIXME: If the value (or any other values from the instruction that the
|
||||
// value comes from) that we are tracking does not escape and we don't alias
|
||||
// any of the arguments of the apply inst, we should be ok.
|
||||
|
||||
// Otherwise be conservative and return that we may have side effects.
|
||||
DEBUG(llvm::dbgs() << " Found apply of side effect builtin. "
|
||||
"Returning MayHaveSideEffects.\n");
|
||||
|
||||
Reference in New Issue
Block a user