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: lib/Transforms/InstCombine/InstCombineAddSub.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -1628,6 +1628,18 @@ Value *ShAmtOp = cast(Op1)->getOperand(1); return BinaryOperator::CreateLShr(X, ShAmtOp); } + + if (Op1->hasOneUse()) { + Value *LHS, *RHS; + SelectPatternFlavor SPF = matchSelectPattern(Op1, LHS, RHS).Flavor; + if (SPF == SPF_ABS || SPF == SPF_NABS) { + // This is a negate of an ABS/NABS pattern. Just swap the operands + // of the select. + SelectInst *SI = cast(Op1); + return SelectInst::Create(SI->getCondition(), SI->getFalseValue(), + SI->getTrueValue()); + } + } } // Turn this into a xor if LHS is 2^n-1 and the remaining bits are known Index: test/Transforms/InstCombine/abs_abs.ll =================================================================== --- test/Transforms/InstCombine/abs_abs.ll +++ test/Transforms/InstCombine/abs_abs.ll @@ -933,8 +933,8 @@ ; CHECK-LABEL: @nabs_abs_x09( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: [[SUB16:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] +; CHECK-NEXT: ret i32 [[SUB16]] ; %cmp = icmp sgt i32 %x, -1 %sub = sub nsw i32 0, %x @@ -949,8 +949,8 @@ ; CHECK-LABEL: @nabs_abs_x10( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: [[SUB16:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] +; CHECK-NEXT: ret i32 [[SUB16]] ; %cmp = icmp sgt i32 %x, 0 %sub = sub nsw i32 0, %x @@ -965,8 +965,8 @@ ; CHECK-LABEL: @nabs_abs_x11( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: [[SUB16:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] +; CHECK-NEXT: ret i32 [[SUB16]] ; %cmp = icmp slt i32 %x, 0 %sub = sub nsw i32 0, %x @@ -981,8 +981,8 @@ ; CHECK-LABEL: @nabs_abs_x12( ; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[X:%.*]], 0 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 0, [[X]] -; CHECK-NEXT: [[COND1:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] -; CHECK-NEXT: ret i32 [[COND1]] +; CHECK-NEXT: [[SUB16:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]] +; CHECK-NEXT: ret i32 [[SUB16]] ; %cmp = icmp slt i32 %x, 1 %sub = sub nsw i32 0, %x