Index: include/llvm/Analysis/AliasSetTracker.h =================================================================== --- include/llvm/Analysis/AliasSetTracker.h +++ include/llvm/Analysis/AliasSetTracker.h @@ -227,12 +227,24 @@ /// If this alias set is known to contain a single instruction and *only* a /// single unique instruction, return it. Otherwise, return nullptr. Instruction* getUniqueInstruction() { - if (size() != 0) - // Can't track source of pointer, might be many instruction - return nullptr; if (AliasAny) // May have collapses alias set return nullptr; + if (begin() != end()) { + if (!UnknownInsts.empty()) + // Another instruction found + return nullptr;; + if (std::next(begin()) != end()) + // Another instruction found + return nullptr; + Value *Addr = begin()->getValue(); + assert(!Addr->user_empty() && + "where's the instruction which added this pointer?"); + if (std::next(Addr->user_begin()) != Addr->user_end()) + // Another instruction found + return nullptr; + return cast(*(Addr->user_begin())); + } if (1 != UnknownInsts.size()) return nullptr; return cast(UnknownInsts[0]); Index: lib/Transforms/Scalar/LICM.cpp =================================================================== --- lib/Transforms/Scalar/LICM.cpp +++ lib/Transforms/Scalar/LICM.cpp @@ -581,8 +581,8 @@ /// concerns such as aliasing or speculation safety. bool isHoistableAndSinkableInst(Instruction &I) { // Only these instructions are hoistable/sinkable. - return (isa(I) || isa(I) || - isa(I) || + return (isa(I) || isa(I) || + isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || isa(I) || @@ -682,7 +682,19 @@ if (isReadOnly(CurAST)) return true; } - + if (AliasAnalysis::doesNotReadMemory(Behavior)) { + auto Begin = CurAST->begin(); + assert(Begin != CurAST->end() && "must contain FI"); + if (std::next(Begin) != CurAST->end()) + // constant memory for instance, TODO: handle better + return false; + auto *UniqueI = Begin->getUniqueInstruction(); + if (!UniqueI) + // other memory op, give up + return false; + assert(UniqueI == CI && "AS must contain FI"); + return true; + } // FIXME: This should use mod/ref information to see if we can hoist or // sink the call. @@ -702,6 +714,24 @@ (void)FI; //suppress unused variable warning assert(UniqueI == FI && "AS must contain FI"); return true; + } else if (auto *SI = dyn_cast(&I)) { + if (!SI->isUnordered()) + return false; // Don't sink/hoist volatile or ordered atomic store! + + // We can only hoist a store that we can prove writes a value which is not + // read or overwritten within the loop. For those cases, we fallback to + // load store promotion instead. + auto &AS = CurAST->getAliasSetFor(MemoryLocation::get(SI)); + + if (AS.isRef() || !AS.isMustAlias()) + // Quick exit test, handled by the full path below as well. + return false; + auto *UniqueI = AS.getUniqueInstruction(); + if (!UniqueI) + // other memory op, give up + return false; + assert(UniqueI == SI && "AS must contain SI"); + return true; } assert(!I.mayReadOrWriteMemory() && "unhandled aliasing");