//===-------------- AliasAnalysis.h - SIL Alias Analysis -*- C++ -*--------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See http://swift.org/LICENSE.txt for license information // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #ifndef SWIFT_SILANALYSIS_ALIASANALYSIS_H #define SWIFT_SILANALYSIS_ALIASANALYSIS_H #include "swift/SIL/SILInstruction.h" #include "swift/SILAnalysis/Analysis.h" #include "llvm/ADT/DenseMap.h" namespace swift { class SILValue; class SILInstruction; /// This class is a simple wrapper around an alias analysis cache. This is /// needed since we do not have an "analysis" infrastructure. class AliasAnalysis : public SILAnalysis { public: /// The result of an alias query. This is based off of LLVM's alias /// analysis so see LLVM's documentation for more information. /// /// FIXME: PartialAlias? enum class AliasResult : unsigned { NoAlias=0, ///< The two values have no dependencies on each /// other. MayAlias, ///< The two values can not be proven to alias or /// not alias. Anything could happen. MustAlias, ///< The two values are equal. }; private: using AliasCacheKey = std::pair; llvm::DenseMap AliasCache; SILModule *Mod; using MemoryBehavior = SILInstruction::MemoryBehavior; public: AliasAnalysis(SILModule *M) : SILAnalysis(AnalysisKind::Alias), Mod(M) {} static bool classof(const SILAnalysis *S) { return S->getKind() == AnalysisKind::Alias; } /// Perform an alias query to see if V1, V2 refer to the same values. AliasResult alias(SILValue V1, SILValue V2); /// Convenience method that returns true if V1 and V2 must alias. bool isMustAlias(SILValue V1, SILValue V2) { return alias(V1, V2) == AliasResult::MustAlias; } /// Convenience method that returns true if V1, V2 can not alias. bool isNoAlias(SILValue V1, SILValue V2) { return alias(V1, V2) == AliasResult::NoAlias; } /// Convenience method that returns true if V1, V2 may alias. bool isMayAlias(SILValue V1, SILValue V2) { return alias(V1, V2) == AliasResult::MayAlias; } /// Use the alias analysis to determine the memory behavior of Inst with /// respect to V. /// /// TODO: When ref count behavior is separated from generic memory behavior, /// the IgnoreRefCountIncrements flag will be unnecessary. MemoryBehavior getMemoryBehavior(SILInstruction *Inst, SILValue V, bool IgnoreRefCountIncrements=false); /// Returns true if Inst may read from memory in a manner that affects V. bool mayReadFromMemory(SILInstruction *Inst, SILValue V) { MemoryBehavior B = getMemoryBehavior(Inst, V, true/*IgnoreRefCountIncs*/); return B == MemoryBehavior::MayRead || B == MemoryBehavior::MayReadWrite || B == MemoryBehavior::MayHaveSideEffects; } /// Returns true if Inst may write to memory in a manner that affects V. bool mayWriteToMemory(SILInstruction *Inst, SILValue V) { MemoryBehavior B = getMemoryBehavior(Inst, V, true/*IgnoreRefCountIncs*/); return B == MemoryBehavior::MayWrite || B == MemoryBehavior::MayReadWrite || B == MemoryBehavior::MayHaveSideEffects; } /// Returns true if Inst may read or write to memory in a manner that affects /// V. bool mayReadOrWriteMemory(SILInstruction *Inst, SILValue V) { auto B = getMemoryBehavior(Inst, V, true/*IgnoreRefCountIncs*/); return B != MemoryBehavior::None; } /// Returns true if Inst may have side effects in a manner that affects V. bool mayHaveSideEffects(SILInstruction *Inst, SILValue V) { MemoryBehavior B = getMemoryBehavior(Inst, V); return B == MemoryBehavior::MayWrite || B == MemoryBehavior::MayReadWrite || B == MemoryBehavior::MayHaveSideEffects; } /// Returns true if Inst may have side effects in a manner that affects /// V. This is independent of whether or not Inst may write to V and is meant /// to encode notions such as ref count modifications. bool mayHavePureSideEffects(SILInstruction *Inst, SILValue V) { return getMemoryBehavior(Inst, V) == MemoryBehavior::MayHaveSideEffects; } virtual void invalidate(InvalidationKind K) { AliasCache.clear(); } virtual void invalidate(SILFunction *, InvalidationKind K) { invalidate(K); } }; llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, AliasAnalysis::AliasResult R); } // end namespace swift #endif