diff --git a/llvm/lib/Analysis/LazyValueInfo.cpp b/llvm/lib/Analysis/LazyValueInfo.cpp --- a/llvm/lib/Analysis/LazyValueInfo.cpp +++ b/llvm/lib/Analysis/LazyValueInfo.cpp @@ -1147,6 +1147,18 @@ CR.getUnsignedMin().zext(BitWidth), APInt(BitWidth, 0))); } + // Recognize: + // icmp sgt (ashr X, ShAmtC), C --> icmp sgt X, ((C + 1) << ShAmtC) - 1 + const APInt *ShAmtC, *RHSC; + if (EdgePred == CmpInst::ICMP_SGT && + match(LHS, m_AShr(m_Specific(Val), m_APInt(ShAmtC))) && + match(RHS, m_APInt(RHSC))) { + APInt Lower = ((*RHSC + 1) << *ShAmtC); + auto V = ValueLatticeElement::getRange(ConstantRange::getNonEmpty( + Lower, APInt::getSignedMaxValue(Lower.getBitWidth()))); + return V; + } + return ValueLatticeElement::getOverdefined(); } diff --git a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll --- a/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll +++ b/llvm/test/Transforms/CorrelatedValuePropagation/icmp.ll @@ -1240,6 +1240,33 @@ ret <2 x i1> %cmp1 } +define void @ashr(i8 %x) { +; CHECK-LABEL: @ashr( +; CHECK-NEXT: [[S:%.*]] = ashr i8 [[X:%.*]], 2 +; CHECK-NEXT: [[C:%.*]] = icmp sgt i8 [[S]], 0 +; CHECK-NEXT: br i1 [[C]], label [[IF:%.*]], label [[ELSE:%.*]] +; CHECK: if: +; CHECK-NEXT: call void @check1(i1 true) +; CHECK-NEXT: [[C3:%.*]] = icmp ugt i8 [[X]], 10 +; CHECK-NEXT: call void @check1(i1 [[C3]]) +; CHECK-NEXT: ret void +; CHECK: else: +; CHECK-NEXT: ret void +; + %s = ashr i8 %x, 2 + %c = icmp sgt i8 %s, 0 + br i1 %c, label %if, label %else +if: + %c2 = icmp sgt i8 %x, 3 + call void @check1(i1 %c2) + %c3 = icmp sgt i8 %x, 10 + call void @check1(i1 %c3) + ret void +else: + ret void +} + + declare i8 @llvm.umin.i8(i8, i8) declare i8 @llvm.umax.i8(i8, i8) declare <2 x i8> @llvm.umin.v2i8(<2 x i8>, <2 x i8>)