diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1774,36 +1774,25 @@ break; } case Intrinsic::uadd_sat: - case Intrinsic::usub_sat: { - bool IsAdd = II->getIntrinsicID() == Intrinsic::uadd_sat; computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); - - // Add: Leading ones of either operand are preserved. - // Sub: Leading zeros of LHS and leading ones of RHS are preserved - // as leading zeros in the result. - unsigned LeadingKnown; - if (IsAdd) - LeadingKnown = std::max(Known.countMinLeadingOnes(), - Known2.countMinLeadingOnes()); - else - LeadingKnown = std::max(Known.countMinLeadingZeros(), - Known2.countMinLeadingOnes()); - - Known = KnownBits::computeForAddSub( - IsAdd, /* NSW */ false, Known, Known2); - - // We select between the operation result and all-ones/zero - // respectively, so we can preserve known ones/zeros. - if (IsAdd) { - Known.One.setHighBits(LeadingKnown); - Known.Zero.clearAllBits(); - } else { - Known.Zero.setHighBits(LeadingKnown); - Known.One.clearAllBits(); - } + Known = KnownBits::uadd_sat(Known, Known2); + break; + case Intrinsic::usub_sat: + computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); + computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); + Known = KnownBits::usub_sat(Known, Known2); + break; + case Intrinsic::sadd_sat: + computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); + computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); + Known = KnownBits::sadd_sat(Known, Known2); + break; + case Intrinsic::ssub_sat: + computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); + computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); + Known = KnownBits::ssub_sat(Known, Known2); break; - } case Intrinsic::umin: computeKnownBits(I->getOperand(0), Known, Depth + 1, Q); computeKnownBits(I->getOperand(1), Known2, Depth + 1, Q); diff --git a/llvm/test/Analysis/ValueTracking/knownbits-sat-addsub.ll b/llvm/test/Analysis/ValueTracking/knownbits-sat-addsub.ll --- a/llvm/test/Analysis/ValueTracking/knownbits-sat-addsub.ll +++ b/llvm/test/Analysis/ValueTracking/knownbits-sat-addsub.ll @@ -8,11 +8,7 @@ define i1 @uadd_sat_overflow(i8 %x, i8 %y) { ; CHECK-LABEL: @uadd_sat_overflow( -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[X:%.*]], -128 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[Y:%.*]], -128 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.uadd.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], -2 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %lhs = or i8 %x, 128 %rhs = or i8 %y, 128 @@ -38,11 +34,7 @@ define i1 @usub_sat_overflow(i8 %x, i8 %y) { ; CHECK-LABEL: @usub_sat_overflow( -; CHECK-NEXT: [[LHS:%.*]] = and i8 [[X:%.*]], 127 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[Y:%.*]], -128 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.usub.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], 1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %lhs = and i8 %x, 127 %rhs = or i8 %y, 128 @@ -68,13 +60,7 @@ define i1 @sadd_sat_overflow_pos(i8 %x, i8 %y) { ; CHECK-LABEL: @sadd_sat_overflow_pos( -; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 127 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 127 -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[XX]], 64 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[YY]], 65 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], -128 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xx = and i8 %x, 127 %yy = and i8 %y, 127 @@ -87,14 +73,7 @@ define i1 @sadd_sat_low_bits(i8 %x, i8 %y) { ; CHECK-LABEL: @sadd_sat_low_bits( -; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 15 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 15 -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[XX]], 1 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[YY]], -2 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[EXP]], 1 -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xx = and i8 %x, 15 %yy = and i8 %y, 15 @@ -125,11 +104,7 @@ define i1 @sadd_sat_overflow_neg(i8 %x, i8 %y) { ; CHECK-LABEL: @sadd_sat_overflow_neg( -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[X:%.*]], -64 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[Y:%.*]], -65 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.sadd.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], 127 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %lhs = or i8 %x, 192 %rhs = or i8 %y, 191 @@ -140,13 +115,7 @@ define i1 @ssub_sat_overflow_neg(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_overflow_neg( -; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 112 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 127 -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[XX]], -128 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[YY]], 126 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], 32 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xx = and i8 %x, 112 %yy = and i8 %y, 127 @@ -159,14 +128,7 @@ define i1 @ssub_sat_low_bits(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_low_bits( -; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 15 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 15 -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[XX]], 17 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[YY]], -2 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[EXP]], 1 -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[AND]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xx = and i8 %x, 15 %yy = and i8 %y, 15 @@ -201,13 +163,7 @@ define i1 @ssub_sat_overflow_pos(i8 %x, i8 %y) { ; CHECK-LABEL: @ssub_sat_overflow_pos( -; CHECK-NEXT: [[XX:%.*]] = and i8 [[X:%.*]], 24 -; CHECK-NEXT: [[YY:%.*]] = and i8 [[Y:%.*]], 3 -; CHECK-NEXT: [[LHS:%.*]] = or i8 [[XX]], 8 -; CHECK-NEXT: [[RHS:%.*]] = or i8 [[YY]], -128 -; CHECK-NEXT: [[EXP:%.*]] = call i8 @llvm.ssub.sat.i8(i8 [[LHS]], i8 [[RHS]]) -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[EXP]], -128 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %xx = and i8 %x, 24 %yy = and i8 %y, 3