Index: llvm/trunk/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/trunk/lib/Analysis/ValueTracking.cpp +++ llvm/trunk/lib/Analysis/ValueTracking.cpp @@ -1095,7 +1095,8 @@ // RHS from matchSelectPattern returns the negation part of abs pattern. // If the negate has an NSW flag we can assume the sign bit of the result // will be 0 because that makes abs(INT_MIN) undefined. - if (Q.IIQ.hasNoSignedWrap(cast(RHS))) + if (match(RHS, m_Neg(m_Specific(LHS))) && + Q.IIQ.hasNoSignedWrap(cast(RHS))) MaxHighZeros = 1; } @@ -5611,7 +5612,7 @@ } static void setLimitsForSelectPattern(const SelectInst &SI, APInt &Lower, - APInt &Upper) { + APInt &Upper, const InstrInfoQuery &IIQ) { const Value *LHS, *RHS; SelectPatternResult R = matchSelectPattern(&SI, LHS, RHS); if (R.Flavor == SPF_UNKNOWN) @@ -5624,7 +5625,8 @@ // then the result of abs(X) is [0..SIGNED_MAX], // otherwise it is [0..SIGNED_MIN], as -SIGNED_MIN == SIGNED_MIN. Lower = APInt::getNullValue(BitWidth); - if (cast(RHS)->hasNoSignedWrap()) + if (match(RHS, m_Neg(m_Specific(LHS))) && + IIQ.hasNoSignedWrap(cast(RHS))) Upper = APInt::getSignedMaxValue(BitWidth) + 1; else Upper = APInt::getSignedMinValue(BitWidth) + 1; @@ -5678,7 +5680,7 @@ else if (auto *II = dyn_cast(V)) setLimitsForIntrinsic(*II, Lower, Upper); else if (auto *SI = dyn_cast(V)) - setLimitsForSelectPattern(*SI, Lower, Upper); + setLimitsForSelectPattern(*SI, Lower, Upper, IIQ); ConstantRange CR = ConstantRange::getNonEmpty(Lower, Upper); Index: llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll =================================================================== --- llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll +++ llvm/trunk/test/Transforms/InstSimplify/icmp-abs-nabs.ll @@ -404,7 +404,12 @@ ; We can't fold this to false unless both subs have nsw. define i1 @abs_sub_sub_missing_nsw(i32 %x, i32 %y) { ; CHECK-LABEL: @abs_sub_sub_missing_nsw( -; CHECK-NEXT: ret i1 false +; CHECK-NEXT: [[A:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[B:%.*]] = sub nsw i32 [[Y]], [[X]] +; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A]], -1 +; CHECK-NEXT: [[D:%.*]] = select i1 [[C]], i32 [[A]], i32 [[B]] +; CHECK-NEXT: [[E:%.*]] = icmp slt i32 [[D]], 0 +; CHECK-NEXT: ret i1 [[E]] ; %a = sub i32 %x, %y %b = sub nsw i32 %y, %x