llvm-6502/include/llvm/Analysis/MemoryDependenceAnalysis.h
Chris Lattner b51deb929c Make a few major changes to memdep and its clients:
1. Merge the 'None' result into 'Normal', making loads
   and stores return their dependencies on allocations as Normal.
2. Split the 'Normal' result into 'Clobber' and 'Def' to
   distinguish between the cases when memdep knows the value is
   produced from when we just know if may be changed.
3. Move some of the logic for determining whether readonly calls
   are CSEs into memdep instead of it being in GVN.  This still
   leaves verification that the arguments are hte same to GVN to
   let it know about value equivalences in different contexts.
4. Change memdep's call/call dependency analysis to use 
   getModRefInfo(CallSite,CallSite) instead of doing something 
   very weak.  This only really matters for things like DSA, but
   someday maybe we'll have some other decent context sensitive
   analyses :)
5. This reimplements the guts of memdep to handle the new results.
6. This simplifies GVN significantly:
   a) readonly call CSE is slightly simpler
   b) I eliminated the "getDependencyFrom" chaining for load 
      elimination and load CSE doesn't have to worry about 
      volatile (they are always clobbers) anymore.
   c) GVN no longer does any 'lastLoad' caching, leaving it to 
      memdep.
7. The logic in DSE is simplified a bit and sped up.  A potentially
   unsafe case was eliminated.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60607 91177308-0d34-0410-b5e6-96231b3b80d8
2008-12-05 21:04:20 +00:00

243 lines
10 KiB
C++

//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the MemoryDependenceAnalysis analysis pass.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H
#define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H
#include "llvm/BasicBlock.h"
#include "llvm/Pass.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
class Function;
class FunctionPass;
class Instruction;
class CallSite;
class AliasAnalysis;
class TargetData;
class MemoryDependenceAnalysis;
/// MemDepResult - A memory dependence query can return one of three different
/// answers, described below.
class MemDepResult {
enum DepType {
/// Invalid - Clients of MemDep never see this.
Invalid = 0,
/// Clobber - This is a dependence on the specified instruction which
/// clobbers the desired value. The pointer member of the MemDepResult
/// pair holds the instruction that clobbers the memory. For example,
/// this occurs when we see a may-aliased store to the memory location we
/// care about.
Clobber,
/// Def - This is a dependence on the specified instruction which
/// defines/produces the desired memory location. The pointer member of
/// the MemDepResult pair holds the instruction that defines the memory.
/// Cases of interest:
/// 1. This could be a load or store for dependence queries on
/// load/store. The value loaded or stored is the produced value.
/// Note that the pointer operand may be different than that of the
/// queried pointer due to must aliases and phi translation. Note
/// that the def may not be the same type as the query, the pointers
/// may just be must aliases.
/// 2. For loads and stores, this could be an allocation instruction. In
/// this case, the load is loading an undef value or a store is the
/// first store to (that part of) the allocation.
/// 3. Dependence queries on calls return Def only when they are
/// readonly calls with identical callees and no intervening
/// clobbers. No validation is done that the operands to the calls
/// are the same.
Def,
/// NonLocal - This marker indicates that the query has no dependency in
/// the specified block. To find out more, the client should query other
/// predecessor blocks.
NonLocal
};
typedef PointerIntPair<Instruction*, 2, DepType> PairTy;
PairTy Value;
explicit MemDepResult(PairTy V) : Value(V) {}
public:
MemDepResult() : Value(0, Invalid) {}
/// get methods: These are static ctor methods for creating various
/// MemDepResult kinds.
static MemDepResult getDef(Instruction *Inst) {
return MemDepResult(PairTy(Inst, Def));
}
static MemDepResult getClobber(Instruction *Inst) {
return MemDepResult(PairTy(Inst, Clobber));
}
static MemDepResult getNonLocal() {
return MemDepResult(PairTy(0, NonLocal));
}
/// isClobber - Return true if this MemDepResult represents a query that is
/// a instruction clobber dependency.
bool isClobber() const { return Value.getInt() == Clobber; }
/// isDef - Return true if this MemDepResult represents a query that is
/// a instruction definition dependency.
bool isDef() const { return Value.getInt() == Def; }
/// isNonLocal - Return true if this MemDepResult represents an query that
/// is transparent to the start of the block, but where a non-local hasn't
/// been done.
bool isNonLocal() const { return Value.getInt() == NonLocal; }
/// getInst() - If this is a normal dependency, return the instruction that
/// is depended on. Otherwise, return null.
Instruction *getInst() const { return Value.getPointer(); }
bool operator==(const MemDepResult &M) const { return M.Value == Value; }
bool operator!=(const MemDepResult &M) const { return M.Value != Value; }
bool operator<(const MemDepResult &M) const { return M.Value < Value; }
bool operator>(const MemDepResult &M) const { return M.Value > Value; }
private:
friend class MemoryDependenceAnalysis;
/// Dirty - Entries with this marker occur in a LocalDeps map or
/// NonLocalDeps map when the instruction they previously referenced was
/// removed from MemDep. In either case, the entry may include an
/// instruction pointer. If so, the pointer is an instruction in the
/// block where scanning can start from, saving some work.
///
/// In a default-constructed MemDepResult object, the type will be Dirty
/// and the instruction pointer will be null.
///
/// isDirty - Return true if this is a MemDepResult in its dirty/invalid.
/// state.
bool isDirty() const { return Value.getInt() == Invalid; }
static MemDepResult getDirty(Instruction *Inst) {
return MemDepResult(PairTy(Inst, Invalid));
}
};
/// MemoryDependenceAnalysis - This is an analysis that determines, for a
/// given memory operation, what preceding memory operations it depends on.
/// It builds on alias analysis information, and tries to provide a lazy,
/// caching interface to a common kind of alias information query.
///
/// The dependency information returned is somewhat unusual, but is pragmatic.
/// If queried about a store or call that might modify memory, the analysis
/// will return the instruction[s] that may either load from that memory or
/// store to it. If queried with a load or call that can never modify memory,
/// the analysis will return calls and stores that might modify the pointer,
/// but generally does not return loads unless a) they are volatile, or
/// b) they load from *must-aliased* pointers. Returning a dependence on
/// must-alias'd pointers instead of all pointers interacts well with the
/// internal caching mechanism.
///
class MemoryDependenceAnalysis : public FunctionPass {
// A map from instructions to their dependency.
typedef DenseMap<Instruction*, MemDepResult> LocalDepMapType;
LocalDepMapType LocalDeps;
public:
typedef std::pair<BasicBlock*, MemDepResult> NonLocalDepEntry;
typedef std::vector<NonLocalDepEntry> NonLocalDepInfo;
private:
/// PerInstNLInfo - This is the instruction we keep for each cached access
/// that we have for an instruction. The pointer is an owning pointer and
/// the bool indicates whether we have any dirty bits in the set.
typedef std::pair<NonLocalDepInfo, bool> PerInstNLInfo;
// A map from instructions to their non-local dependencies.
typedef DenseMap<Instruction*, PerInstNLInfo> NonLocalDepMapType;
NonLocalDepMapType NonLocalDeps;
// A reverse mapping from dependencies to the dependees. This is
// used when removing instructions to keep the cache coherent.
typedef DenseMap<Instruction*,
SmallPtrSet<Instruction*, 4> > ReverseDepMapType;
ReverseDepMapType ReverseLocalDeps;
// A reverse mapping form dependencies to the non-local dependees.
ReverseDepMapType ReverseNonLocalDeps;
/// Current AA implementation, just a cache.
AliasAnalysis *AA;
TargetData *TD;
public:
MemoryDependenceAnalysis() : FunctionPass(&ID) {}
static char ID;
/// Pass Implementation stuff. This doesn't do any analysis eagerly.
bool runOnFunction(Function &);
/// Clean up memory in between runs
void releaseMemory() {
LocalDeps.clear();
NonLocalDeps.clear();
NonLocalDeps.clear();
ReverseLocalDeps.clear();
ReverseNonLocalDeps.clear();
}
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering
/// and Alias Analysis.
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
/// getDependency - Return the instruction on which a memory operation
/// depends. See the class comment for more details. It is illegal to call
/// this on non-memory instructions.
MemDepResult getDependency(Instruction *QueryInst);
/// getDependencyFrom - Return the instruction on which the memory operation
/// 'QueryInst' depends. This starts scanning from the instruction before
/// the position indicated by ScanIt.
///
/// Note that this method does no caching at all. You should use
/// getDependency where possible.
MemDepResult getDependencyFrom(Instruction *QueryInst,
BasicBlock::iterator ScanIt, BasicBlock *BB);
/// getNonLocalDependency - Perform a full dependency query for the
/// specified instruction, returning the set of blocks that the value is
/// potentially live across. The returned set of results will include a
/// "NonLocal" result for all blocks where the value is live across.
///
/// This method assumes the instruction returns a "NonLocal" dependency
/// within its own block.
///
/// This returns a reference to an internal data structure that may be
/// invalidated on the next non-local query or when an instruction is
/// removed. Clients must copy this data if they want it around longer than
/// that.
const NonLocalDepInfo &getNonLocalDependency(Instruction *QueryInst);
/// removeInstruction - Remove an instruction from the dependence analysis,
/// updating the dependence of instructions that previously depended on it.
void removeInstruction(Instruction *InstToRemove);
private:
/// verifyRemoved - Verify that the specified instruction does not occur
/// in our internal data structures.
void verifyRemoved(Instruction *Inst) const;
MemDepResult getCallSiteDependency(CallSite C, BasicBlock::iterator ScanIt,
BasicBlock *BB);
};
} // End llvm namespace
#endif