Index: lib/Analysis/ValueTracking.cpp =================================================================== --- lib/Analysis/ValueTracking.cpp +++ lib/Analysis/ValueTracking.cpp @@ -1078,6 +1078,12 @@ // leading zero bits. MaxHighZeros = std::max(Known.countMinLeadingZeros(), Known2.countMinLeadingZeros()); + } else if (SPF == SPF_ABS) { + // 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 (cast(RHS)->hasNoSignedWrap()) + MaxHighZeros = 1; } // Only known if known in both the LHS and RHS. Index: test/Transforms/InstCombine/abs_abs.ll =================================================================== --- test/Transforms/InstCombine/abs_abs.ll +++ test/Transforms/InstCombine/abs_abs.ll @@ -883,8 +883,9 @@ ; CHECK-LABEL: @nabs_abs_x09( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp sgt i32 %x, -1 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x -; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]] +; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond +; CHECK-NEXT: ret i32 [[SUB16]] } define i32 @nabs_abs_x10(i32 %x) { @@ -898,8 +899,9 @@ ; CHECK-LABEL: @nabs_abs_x10( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp sgt i32 %x, 0 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x -; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]] +; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond +; CHECK-NEXT: ret i32 [[SUB16]] } define i32 @nabs_abs_x11(i32 %x) { @@ -913,8 +915,9 @@ ; CHECK-LABEL: @nabs_abs_x11( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp slt i32 %x, 0 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x -; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]] -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x +; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond +; CHECK-NEXT: ret i32 [[SUB16]] } define i32 @nabs_abs_x12(i32 %x) { @@ -928,8 +931,9 @@ ; CHECK-LABEL: @nabs_abs_x12( ; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp slt i32 %x, 1 ; CHECK-NEXT: [[NEG:%[a-z0-9]+]] = sub nsw i32 0, %x -; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 %x, i32 [[NEG]] -; CHECK-NEXT: ret i32 [[SEL]] +; CHECK-NEXT: [[SEL:%[a-z0-9]+]] = select i1 [[CMP]], i32 [[NEG]], i32 %x +; CHECK-NEXT: [[SUB16:%[a-z0-9]+]] = sub nsw i32 0, %cond +; CHECK-NEXT: ret i32 [[SUB16]] } define i32 @nabs_abs_x13(i32 %x) {