summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/LICM.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LICM.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/LICM.cpp26
1 files changed, 23 insertions, 3 deletions
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");
OpenPOWER on IntegriCloud