Index: lib/Analysis/LazyValueInfo.cpp =================================================================== --- lib/Analysis/LazyValueInfo.cpp +++ lib/Analysis/LazyValueInfo.cpp @@ -930,6 +930,37 @@ if (EdgesMissing) continue; + // If this is an identity arc, we cannot be less specific now than we were + // before. + if (PhiVal == PN) + EdgeResult = intersect(EdgeResult, Result); + + // If the PHI has known bounds already and this is an increment, we can + // produce a much more accurate lattice value than overdefined. + if ((EdgeResult.isOverdefined() || + (EdgeResult.isConstantRange() && + EdgeResult.getConstantRange().isFullSet())) && + (Result.isConstant() || Result.isConstantRange())) { + // Can we determine this is a monotonically increasing increment? + ConstantInt *Inc; + bool NSW = match(PhiVal, m_NSWAdd(m_Specific(PN), m_ConstantInt(Inc))); + bool NUW = + !NSW && match(PhiVal, m_NUWAdd(m_Specific(PN), m_ConstantInt(Inc))); + if ((NSW || NUW) && !Inc->isNegative()) { + APInt Start = Result.isConstant() + ? cast(Result.getConstant())->getValue() + : Result.getConstantRange().getLower(); + APInt End = NSW ? APInt::getSignedMaxValue(Start.getBitWidth()) + : APInt::getMaxValue(Start.getBitWidth()); + EdgeResult = LVILatticeVal::getRange(ConstantRange(Start, End)); + + // We've discovered that this is a monotonically increasing increment. + // PhiVal may have been cached; in this case we must erase it so that + // it is recomputed based on this new information. + TheCache.eraseValue(PhiVal); + } + } + Result.mergeIn(EdgeResult, DL); // If we hit overdefined, exit early. The BlockVals entry is already set Index: test/Transforms/CorrelatedValuePropagation/monotonic.ll =================================================================== --- /dev/null +++ test/Transforms/CorrelatedValuePropagation/monotonic.ll @@ -0,0 +1,27 @@ +; RUN: opt -S < %s -correlated-propagation | FileCheck %s + +; CHECK-LABEL: @f +; CHECK: = phi i32 {{.*}} [ 3, %select.unfold ] +define void @f() { +entry: + br label %while.cond + +select.unfold: ; preds = %while.body + br label %while.cond + +while.cond: ; preds = %while.body, %select.unfold, %entry + %i.0 = phi i32 [ 2, %entry ], [ %i.0, %while.body ], [ %add, %select.unfold ] + %cmp = icmp slt i32 %i.0, 3 + br i1 %cmp, label %while.body, label %return + +while.body: ; preds = %while.cond + %add = add nsw i32 %i.0, 1 + %call = call i32 @g() + %cmp3 = icmp eq i32 %call, 0 + br i1 %cmp3, label %select.unfold, label %while.cond + +return: + ret void +} + +declare i32 @g()