diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/AliasSetTracker.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 26 |
2 files changed, 39 insertions, 6 deletions
diff --git a/llvm/lib/Analysis/AliasSetTracker.cpp b/llvm/lib/Analysis/AliasSetTracker.cpp index 377db8a569f..51a61e9e2d9 100644 --- a/llvm/lib/Analysis/AliasSetTracker.cpp +++ b/llvm/lib/Analysis/AliasSetTracker.cpp @@ -256,9 +256,22 @@ Instruction* AliasSet::getUniqueInstruction() { if (AliasAny) // May have collapses alias set return nullptr; - if (size() != 0) - // Can't track source of pointer, might be many instruction - 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 -- this is really restrictive + // TODO: generalize! + return nullptr; + return cast<Instruction>(*(Addr->user_begin())); + } if (1 != UnknownInsts.size()) return nullptr; return cast<Instruction>(UnknownInsts[0]); diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index 94fcdaf3c08..ff7cb3c26c9 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -416,7 +416,8 @@ bool llvm::sinkRegion(DomTreeNode *N, AliasAnalysis *AA, LoopInfo *LI, // bool FreeInLoop = false; if (isNotUsedOrFreeInLoop(I, CurLoop, SafetyInfo, TTI, FreeInLoop) && - canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, true, ORE)) { + canSinkOrHoistInst(I, AA, DT, CurLoop, CurAST, true, ORE) && + !I.mayHaveSideEffects()) { if (sink(I, LI, DT, CurLoop, SafetyInfo, ORE, FreeInLoop)) { if (!FreeInLoop) { ++II; @@ -604,8 +605,8 @@ namespace { /// concerns such as aliasing or speculation safety. bool isHoistableAndSinkableInst(Instruction &I) { // Only these instructions are hoistable/sinkable. - return (isa<LoadInst>(I) || isa<CallInst>(I) || - isa<FenceInst>(I) || + return (isa<LoadInst>(I) || isa<StoreInst>(I) || + isa<CallInst>(I) || isa<FenceInst>(I) || isa<BinaryOperator>(I) || isa<CastInst>(I) || isa<SelectInst>(I) || isa<GetElementPtrInst>(I) || isa<CmpInst>(I) || isa<InsertElementInst>(I) || @@ -695,6 +696,7 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, // it's arguments with arbitrary offsets. If we can prove there are no // writes to this memory in the loop, we can hoist or sink. if (AliasAnalysis::onlyAccessesArgPointees(Behavior)) { + // TODO: expand to writeable arguments for (Value *Op : CI->arg_operands()) if (Op->getType()->isPointerTy() && pointerInvalidatedByLoop( @@ -729,6 +731,24 @@ bool llvm::canSinkOrHoistInst(Instruction &I, AAResults *AA, DominatorTree *DT, (void)FI; //suppress unused variable warning assert(UniqueI == FI && "AS must contain FI"); return true; + } else if (auto *SI = dyn_cast<StoreInst>(&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"); |