forked from OSchip/llvm-project
Move to having a single real instructionClobbersQuery
Summary: We really want to move towards MemoryLocOrCall (or fix AA) everywhere, but for now, this lets us have a single instructionClobbersQuery. Reviewers: george.burgess.iv Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D23072 llvm-svn: 277530
This commit is contained in:
parent
4ee7f3c9aa
commit
dff31deb1e
|
@ -94,6 +94,82 @@ public:
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
/// Our current alias analysis API differentiates heavily between calls and
|
||||||
|
/// non-calls, and functions called on one usually assert on the other.
|
||||||
|
/// This class encapsulates the distinction to simplify other code that wants
|
||||||
|
/// "Memory affecting instructions and related data" to use as a key.
|
||||||
|
/// For example, this class is used as a densemap key in the use optimizer.
|
||||||
|
class MemoryLocOrCall {
|
||||||
|
public:
|
||||||
|
MemoryLocOrCall() : IsCall(false) {}
|
||||||
|
MemoryLocOrCall(MemoryUseOrDef *MUD)
|
||||||
|
: MemoryLocOrCall(MUD->getMemoryInst()) {}
|
||||||
|
|
||||||
|
MemoryLocOrCall(Instruction *Inst) {
|
||||||
|
if (ImmutableCallSite(Inst)) {
|
||||||
|
IsCall = true;
|
||||||
|
CS = ImmutableCallSite(Inst);
|
||||||
|
} else {
|
||||||
|
IsCall = false;
|
||||||
|
// There is no such thing as a memorylocation for a fence inst, and it is
|
||||||
|
// unique in that regard.
|
||||||
|
if (!isa<FenceInst>(Inst))
|
||||||
|
Loc = MemoryLocation::get(Inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit MemoryLocOrCall(const MemoryLocation &Loc)
|
||||||
|
: IsCall(false), Loc(Loc) {}
|
||||||
|
|
||||||
|
bool IsCall;
|
||||||
|
ImmutableCallSite getCS() const {
|
||||||
|
assert(IsCall);
|
||||||
|
return CS;
|
||||||
|
}
|
||||||
|
MemoryLocation getLoc() const {
|
||||||
|
assert(!IsCall);
|
||||||
|
return Loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const MemoryLocOrCall &Other) const {
|
||||||
|
if (IsCall != Other.IsCall)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (IsCall)
|
||||||
|
return CS.getCalledValue() == Other.CS.getCalledValue();
|
||||||
|
return Loc == Other.Loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// FIXME: MSVC 2013 does not properly implement C++11 union rules, once we
|
||||||
|
// require newer versions, this should be made an anonymous union again.
|
||||||
|
ImmutableCallSite CS;
|
||||||
|
MemoryLocation Loc;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
template <> struct DenseMapInfo<MemoryLocOrCall> {
|
||||||
|
static inline MemoryLocOrCall getEmptyKey() {
|
||||||
|
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getEmptyKey());
|
||||||
|
}
|
||||||
|
static inline MemoryLocOrCall getTombstoneKey() {
|
||||||
|
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getTombstoneKey());
|
||||||
|
}
|
||||||
|
static unsigned getHashValue(const MemoryLocOrCall &MLOC) {
|
||||||
|
if (MLOC.IsCall)
|
||||||
|
return hash_combine(MLOC.IsCall,
|
||||||
|
DenseMapInfo<const Value *>::getHashValue(
|
||||||
|
MLOC.getCS().getCalledValue()));
|
||||||
|
return hash_combine(
|
||||||
|
MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
|
||||||
|
}
|
||||||
|
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
|
||||||
|
return LHS == RHS;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
namespace {
|
namespace {
|
||||||
struct UpwardsMemoryQuery {
|
struct UpwardsMemoryQuery {
|
||||||
// True if our original query started off as a call
|
// True if our original query started off as a call
|
||||||
|
@ -122,13 +198,26 @@ static bool instructionClobbersQuery(MemoryDef *MD,
|
||||||
AliasAnalysis &AA) {
|
AliasAnalysis &AA) {
|
||||||
Instruction *DefInst = MD->getMemoryInst();
|
Instruction *DefInst = MD->getMemoryInst();
|
||||||
assert(DefInst && "Defining instruction not actually an instruction");
|
assert(DefInst && "Defining instruction not actually an instruction");
|
||||||
ImmutableCallSite UseCS(UseInst);
|
|
||||||
if (!UseCS)
|
|
||||||
return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod;
|
|
||||||
|
|
||||||
|
ImmutableCallSite UseCS(UseInst);
|
||||||
|
if (UseCS) {
|
||||||
ModRefInfo I = AA.getModRefInfo(DefInst, UseCS);
|
ModRefInfo I = AA.getModRefInfo(DefInst, UseCS);
|
||||||
return I != MRI_NoModRef;
|
return I != MRI_NoModRef;
|
||||||
}
|
}
|
||||||
|
return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool instructionClobbersQuery(MemoryDef *MD, MemoryUse *MU,
|
||||||
|
const MemoryLocOrCall &UseMLOC,
|
||||||
|
AliasAnalysis &AA) {
|
||||||
|
// FIXME: This is a temporary hack to allow a single instructionClobbersQuery
|
||||||
|
// to exist while MemoryLocOrCall is pushed through places.
|
||||||
|
if (UseMLOC.IsCall)
|
||||||
|
return instructionClobbersQuery(MD, MemoryLocation(), MU->getMemoryInst(),
|
||||||
|
AA);
|
||||||
|
return instructionClobbersQuery(MD, UseMLOC.getLoc(), MU->getMemoryInst(),
|
||||||
|
AA);
|
||||||
|
}
|
||||||
|
|
||||||
/// Cache for our caching MemorySSA walker.
|
/// Cache for our caching MemorySSA walker.
|
||||||
class WalkerCache {
|
class WalkerCache {
|
||||||
|
@ -1072,77 +1161,6 @@ MemorySSA::AccessList *MemorySSA::getOrCreateAccessList(const BasicBlock *BB) {
|
||||||
return Res.first->second.get();
|
return Res.first->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Our current alias analysis API differentiates heavily between calls and
|
|
||||||
/// non-calls, and functions called on one usually assert on the other.
|
|
||||||
/// This class encapsulates the distinction to simplify other code that wants
|
|
||||||
/// "Memory affecting instructions and related data" to use as a key.
|
|
||||||
/// For example, this class is used as a densemap key in the use optimizer.
|
|
||||||
class MemoryLocOrCall {
|
|
||||||
public:
|
|
||||||
MemoryLocOrCall() : IsCall(false) {}
|
|
||||||
MemoryLocOrCall(MemoryUseOrDef *MUD)
|
|
||||||
: MemoryLocOrCall(MUD->getMemoryInst()) {}
|
|
||||||
|
|
||||||
MemoryLocOrCall(Instruction *Inst) {
|
|
||||||
if (ImmutableCallSite(Inst)) {
|
|
||||||
IsCall = true;
|
|
||||||
CS = ImmutableCallSite(Inst);
|
|
||||||
} else {
|
|
||||||
IsCall = false;
|
|
||||||
// There is no such thing as a memorylocation for a fence inst, and it is
|
|
||||||
// unique in that regard.
|
|
||||||
if (!isa<FenceInst>(Inst))
|
|
||||||
Loc = MemoryLocation::get(Inst);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit MemoryLocOrCall(MemoryLocation Loc) : IsCall(false), Loc(Loc) {}
|
|
||||||
|
|
||||||
bool IsCall;
|
|
||||||
ImmutableCallSite getCS() const {
|
|
||||||
assert(IsCall);
|
|
||||||
return CS;
|
|
||||||
}
|
|
||||||
MemoryLocation getLoc() const {
|
|
||||||
assert(!IsCall);
|
|
||||||
return Loc;
|
|
||||||
}
|
|
||||||
bool operator==(const MemoryLocOrCall &Other) const {
|
|
||||||
if (IsCall != Other.IsCall)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (IsCall)
|
|
||||||
return CS.getCalledValue() == Other.CS.getCalledValue();
|
|
||||||
return Loc == Other.Loc;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// FIXME: MSVC 2013 does not properly implement C++11 union rules, once we
|
|
||||||
// require newer versions, this should be made an anonymous union again.
|
|
||||||
ImmutableCallSite CS;
|
|
||||||
MemoryLocation Loc;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct DenseMapInfo<MemoryLocOrCall> {
|
|
||||||
static inline MemoryLocOrCall getEmptyKey() {
|
|
||||||
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getEmptyKey());
|
|
||||||
}
|
|
||||||
static inline MemoryLocOrCall getTombstoneKey() {
|
|
||||||
return MemoryLocOrCall(DenseMapInfo<MemoryLocation>::getTombstoneKey());
|
|
||||||
}
|
|
||||||
static unsigned getHashValue(const MemoryLocOrCall &MLOC) {
|
|
||||||
if (MLOC.IsCall)
|
|
||||||
return hash_combine(MLOC.IsCall,
|
|
||||||
DenseMapInfo<const Value *>::getHashValue(
|
|
||||||
MLOC.getCS().getCalledValue()));
|
|
||||||
return hash_combine(
|
|
||||||
MLOC.IsCall, DenseMapInfo<MemoryLocation>::getHashValue(MLOC.getLoc()));
|
|
||||||
}
|
|
||||||
static bool isEqual(const MemoryLocOrCall &LHS, const MemoryLocOrCall &RHS) {
|
|
||||||
return LHS == RHS;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This class is a batch walker of all MemoryUse's in the program, and points
|
/// This class is a batch walker of all MemoryUse's in the program, and points
|
||||||
/// their defining access at the thing that actually clobbers them. Because it
|
/// their defining access at the thing that actually clobbers them. Because it
|
||||||
/// is a batch walker that touches everything, it does not operate like the
|
/// is a batch walker that touches everything, it does not operate like the
|
||||||
|
@ -1185,18 +1203,6 @@ private:
|
||||||
DominatorTree *DT;
|
DominatorTree *DT;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool instructionClobbersQuery(MemoryDef *MD,
|
|
||||||
const MemoryLocOrCall &UseMLOC,
|
|
||||||
AliasAnalysis &AA) {
|
|
||||||
Instruction *DefInst = MD->getMemoryInst();
|
|
||||||
assert(DefInst && "Defining instruction not actually an instruction");
|
|
||||||
if (!UseMLOC.IsCall)
|
|
||||||
return AA.getModRefInfo(DefInst, UseMLOC.getLoc()) & MRI_Mod;
|
|
||||||
|
|
||||||
ModRefInfo I = AA.getModRefInfo(DefInst, UseMLOC.getCS());
|
|
||||||
return I != MRI_NoModRef;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Optimize the uses in a given block This is basically the SSA renaming
|
/// Optimize the uses in a given block This is basically the SSA renaming
|
||||||
/// algorithm, with one caveat: We are able to use a single stack for all
|
/// algorithm, with one caveat: We are able to use a single stack for all
|
||||||
/// MemoryUses. This is because the set of *possible* reaching MemoryDefs is
|
/// MemoryUses. This is because the set of *possible* reaching MemoryDefs is
|
||||||
|
@ -1303,7 +1309,7 @@ void MemorySSA::OptimizeUses::optimizeUsesInBlock(
|
||||||
|
|
||||||
MemoryDef *MD = cast<MemoryDef>(VersionStack[UpperBound]);
|
MemoryDef *MD = cast<MemoryDef>(VersionStack[UpperBound]);
|
||||||
|
|
||||||
if (instructionClobbersQuery(MD, UseMLOC, *AA)) {
|
if (instructionClobbersQuery(MD, MU, UseMLOC, *AA)) {
|
||||||
FoundClobberResult = true;
|
FoundClobberResult = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue