diff --git a/llvm/include/llvm/Analysis/IVUsers.h b/llvm/include/llvm/Analysis/IVUsers.h index ae9c1f5bd9ac6..00dbcbdd78063 100644 --- a/llvm/include/llvm/Analysis/IVUsers.h +++ b/llvm/include/llvm/Analysis/IVUsers.h @@ -21,6 +21,7 @@ namespace llvm { +class AssumptionCache; class DominatorTree; class Instruction; class Value; @@ -119,15 +120,19 @@ template<> struct ilist_traits class IVUsers : public LoopPass { friend class IVStrideUse; Loop *L; + AssumptionCache *AC; LoopInfo *LI; DominatorTree *DT; ScalarEvolution *SE; - SmallPtrSet Processed; + SmallPtrSet Processed; /// IVUses - A list of all tracked IV uses of induction variable expressions /// we are interested in. ilist IVUses; + // Ephemeral values used by @llvm.assume in this function. + SmallPtrSet EphValues; + void getAnalysisUsage(AnalysisUsage &AU) const override; bool runOnLoop(Loop *L, LPPassManager &LPM) override; diff --git a/llvm/lib/Analysis/IVUsers.cpp b/llvm/lib/Analysis/IVUsers.cpp index b88b2496b875e..926787d3be914 100644 --- a/llvm/lib/Analysis/IVUsers.cpp +++ b/llvm/lib/Analysis/IVUsers.cpp @@ -12,8 +12,10 @@ // //===----------------------------------------------------------------------===// -#include "llvm/Analysis/IVUsers.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/AssumptionCache.h" +#include "llvm/Analysis/CodeMetrics.h" +#include "llvm/Analysis/IVUsers.h" #include "llvm/Analysis/LoopPass.h" #include "llvm/Analysis/ScalarEvolutionExpressions.h" #include "llvm/Analysis/ValueTracking.h" @@ -34,6 +36,7 @@ using namespace llvm; char IVUsers::ID = 0; INITIALIZE_PASS_BEGIN(IVUsers, "iv-users", "Induction Variable Users", false, true) +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) INITIALIZE_PASS_DEPENDENCY(ScalarEvolution) @@ -137,6 +140,11 @@ bool IVUsers::AddUsersImpl(Instruction *I, if (Width > 64 || !DL.isLegalInteger(Width)) return false; + // Don't attempt to promote ephemeral values to indvars. They will be removed + // later anyway. + if (EphValues.count(I)) + return false; + // Get the symbolic expression for this instruction. const SCEV *ISE = SE->getSCEV(I); @@ -244,6 +252,7 @@ IVUsers::IVUsers() } void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired(); AU.addRequired(); AU.addRequired(); AU.addRequired(); @@ -253,10 +262,16 @@ void IVUsers::getAnalysisUsage(AnalysisUsage &AU) const { bool IVUsers::runOnLoop(Loop *l, LPPassManager &LPM) { L = l; + AC = &getAnalysis().getAssumptionCache( + *L->getHeader()->getParent()); LI = &getAnalysis().getLoopInfo(); DT = &getAnalysis().getDomTree(); SE = &getAnalysis(); + // Collect ephemeral values so that AddUsersIfInteresting skips them. + EphValues.clear(); + CodeMetrics::collectEphemeralValues(L, AC, EphValues); + // Find all uses of induction variables in this loop, and categorize // them by stride. Start by finding all of the PHI nodes in the header for // this loop. If they are induction variables, inspect their uses. diff --git a/llvm/test/Transforms/LoopStrengthReduce/ephemeral.ll b/llvm/test/Transforms/LoopStrengthReduce/ephemeral.ll new file mode 100644 index 0000000000000..a0d1d44b1bac4 --- /dev/null +++ b/llvm/test/Transforms/LoopStrengthReduce/ephemeral.ll @@ -0,0 +1,41 @@ +; RUN: opt < %s -loop-reduce -S | FileCheck %s + +target datalayout = "e-i64:64-v16:16-v32:32-n16:32:64" + +; for (int i = 0; i < n; ++i) { +; use(i * 5 + 3); +; // i * a + b is ephemeral and shouldn't be promoted by LSR +; __builtin_assume(i * a + b >= 0); +; } +define void @ephemeral(i32 %a, i32 %b, i32 %n) { +; CHECK-LABEL: @ephemeral( +entry: + br label %loop + +loop: + %i = phi i32 [ 0, %entry ], [ %inc, %loop ] + ; Only i and i * 5 + 3 should be indvars, not i * a + b. +; CHECK: phi i32 +; CHECK: phi i32 +; CHECK-NOT: phi i32 + %inc = add nsw i32 %i, 1 + %exitcond = icmp eq i32 %inc, %n + + %0 = mul nsw i32 %i, 5 + %1 = add nsw i32 %0, 3 + call void @use(i32 %1) + + %2 = mul nsw i32 %i, %a + %3 = add nsw i32 %2, %b + %4 = icmp sgt i32 %3, -1 + call void @llvm.assume(i1 %4) + + br i1 %exitcond, label %exit, label %loop + +exit: + ret void +} + +declare void @use(i32) + +declare void @llvm.assume(i1)