Index: lib/Transforms/Utils/MemorySSA.cpp =================================================================== --- lib/Transforms/Utils/MemorySSA.cpp +++ lib/Transforms/Utils/MemorySSA.cpp @@ -95,6 +95,60 @@ } 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(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(); + else + 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; +}; + struct UpwardsMemoryQuery { // True if our original query started off as a call bool IsCall; @@ -122,12 +176,27 @@ AliasAnalysis &AA) { Instruction *DefInst = MD->getMemoryInst(); assert(DefInst && "Defining instruction not actually an instruction"); - ImmutableCallSite UseCS(UseInst); - if (!UseCS) - return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod; - ModRefInfo I = AA.getModRefInfo(DefInst, UseCS); - return I != MRI_NoModRef; + if (UseInst) { + ImmutableCallSite UseCS(UseInst); + if (UseCS) { + ModRefInfo I = AA.getModRefInfo(DefInst, UseCS); + return I != MRI_NoModRef; + } + } + return AA.getModRefInfo(DefInst, UseLoc) & MRI_Mod; +} + +static bool instructionClobbersQuery(MemoryDef *MD, + 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(), + UseMLOC.getCS().getInstruction(), AA); + else + return instructionClobbersQuery(MD, UseMLOC.getLoc(), nullptr, AA); } /// Cache for our caching MemorySSA walker. @@ -1071,59 +1140,6 @@ Res.first->second = make_unique(); 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(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(); - else - 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 { static inline MemoryLocOrCall getEmptyKey() { return MemoryLocOrCall(DenseMapInfo::getEmptyKey()); @@ -1188,18 +1204,6 @@ 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 /// 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