Index: lib/Transforms/Scalar/LoopDeletion.cpp =================================================================== --- lib/Transforms/Scalar/LoopDeletion.cpp +++ lib/Transforms/Scalar/LoopDeletion.cpp @@ -33,7 +33,7 @@ /// /// This assumes that we've already checked for unique exit and exiting blocks, /// and that the code is in LCSSA form. -static bool isLoopDead(Loop *L, ScalarEvolution &SE, +static bool isLoopDead(Loop *L, ScalarEvolution &SE, AAResults &AA, SmallVectorImpl &ExitingBlocks, BasicBlock *ExitBlock, bool &Changed, BasicBlock *Preheader) { @@ -77,11 +77,24 @@ // Make sure that no instructions in the block have potential side-effects. // This includes instructions that could write to memory, and loads that are - // marked volatile. This could be made more aggressive by using aliasing - // information to identify readonly and readnone calls. + // marked volatile. for (Loop::block_iterator LI = L->block_begin(), LE = L->block_end(); LI != LE; ++LI) { for (Instruction &I : **LI) { + // Maybe we will have more luck looking at the callsite. + if (auto CS = CallSite(&I)) { + FunctionModRefBehavior Bev = AA.getModRefBehavior(CS); + // NOTE: this kind of instructions will likely to have been remove from + // the loop at this point, but since deleting a loop can result in + // significant performance gain, we should try to be aggressive. + // This covers calls that does not write to memory. i.e. calls + // that only read memory or does not read memory. + if (AliasAnalysis::onlyReadsMemory(Bev)) + continue; + else + return false; + } + if (I.mayHaveSideEffects()) return false; } @@ -107,7 +120,8 @@ /// This also updates the relevant analysis information in \p DT, \p SE, and \p /// LI. It also updates the loop PM if an updater struct is provided. static bool deleteLoopIfDead(Loop *L, DominatorTree &DT, ScalarEvolution &SE, - LoopInfo &LI, LPMUpdater *Updater = nullptr) { + LoopInfo &LI, AAResults &AA, + LPMUpdater *Updater = nullptr) { assert(L->isLCSSAForm(DT) && "Expected LCSSA!"); // We can only remove the loop if there is a preheader that we can @@ -138,7 +152,7 @@ // Finally, we have to check that the loop really is dead. bool Changed = false; - if (!isLoopDead(L, SE, ExitingBlocks, ExitBlock, Changed, Preheader)) + if (!isLoopDead(L, SE, AA, ExitingBlocks, ExitBlock, Changed, Preheader)) return Changed; // Don't remove loops for which we can't solve the trip count. @@ -225,7 +239,7 @@ PreservedAnalyses LoopDeletionPass::run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &Updater) { - if (!deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, &Updater)) + if (!deleteLoopIfDead(&L, AR.DT, AR.SE, AR.LI, AR.AA, &Updater)) return PreservedAnalyses::all(); return getLoopPassPreservedAnalyses(); @@ -264,6 +278,7 @@ DominatorTree &DT = getAnalysis().getDomTree(); ScalarEvolution &SE = getAnalysis().getSE(); LoopInfo &LI = getAnalysis().getLoopInfo(); + AAResults &AA = getAnalysis().getAAResults(); - return deleteLoopIfDead(L, DT, SE, LI); + return deleteLoopIfDead(L, DT, SE, LI, AA); } Index: test/Transforms/LoopDeletion/no-sideeffect-call.ll =================================================================== --- /dev/null +++ test/Transforms/LoopDeletion/no-sideeffect-call.ll @@ -0,0 +1,42 @@ +; RUN: opt -S -loop-deletion < %s | FileCheck %s + +; Its possible for the optimizer to add readnone attribute when it knows +; the input to the sqrtf is going to be greater than 0 and will not cause a +; domain error (side effect). Make sure we look at the callsite and derive +; its safe to delete and remove this loop. +; +; CHECK-LABEL: define void @loop_with_readnone_call( +; CHECK-NOT: phi +; CHECK-NOT: call float @sqrt +; CHECK: ret +define void @loop_with_readnone_call(i32 %n, float %x) { +entry: + br label %for.cond + +for.cond: + %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ] + %cmp = icmp slt i32 %i.0, %n + br i1 %cmp, label %for.body, label %for.end + +for.body: + %cmp1 = fcmp ogt float %x, 0.000000e+00 + br i1 %cmp1, label %if.then, label %if.end + +if.then: + %call = call float @sqrtf(float %x) #0 + br label %if.end + +if.end: + br label %for.inc + +for.inc: + %inc = add nsw i32 %i.0, 1 + br label %for.cond + +for.end: + ret void +} + +declare float @sqrtf(float) + +attributes #0 = { readnone }