Skip to content

Commit

Permalink
[ValueTracking] mul nuw nsw with factor sgt 1 is non-negative (llvm#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
nikic authored and xgupta committed Oct 4, 2024
1 parent d4aa843 commit 6a339a1
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 9 deletions.
20 changes: 14 additions & 6 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,9 +369,9 @@ static void computeKnownBitsAddSub(bool Add, const Value *Op0, const Value *Op1,
}

static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
const APInt &DemandedElts, KnownBits &Known,
KnownBits &Known2, unsigned Depth,
const SimplifyQuery &Q) {
bool NUW, const APInt &DemandedElts,
KnownBits &Known, KnownBits &Known2,
unsigned Depth, const SimplifyQuery &Q) {
computeKnownBits(Op1, DemandedElts, Known, Depth + 1, Q);
computeKnownBits(Op0, DemandedElts, Known2, Depth + 1, Q);

Expand All @@ -390,6 +390,13 @@ static void computeKnownBitsMul(const Value *Op0, const Value *Op1, bool NSW,
// The product of two numbers with the same sign is non-negative.
isKnownNonNegative = (isKnownNegativeOp1 && isKnownNegativeOp0) ||
(isKnownNonNegativeOp1 && isKnownNonNegativeOp0);
if (!isKnownNonNegative && NUW) {
// mul nuw nsw with a factor > 1 is non-negative.
KnownBits One = KnownBits::makeConstant(APInt(Known.getBitWidth(), 1));
isKnownNonNegative = KnownBits::sgt(Known, One).value_or(false) ||
KnownBits::sgt(Known2, One).value_or(false);
}

// The product of a negative number and a non-negative number is either
// negative or zero.
if (!isKnownNonNegative)
Expand Down Expand Up @@ -1090,8 +1097,9 @@ static void computeKnownBitsFromOperator(const Operator *I,
break;
case Instruction::Mul: {
bool NSW = Q.IIQ.hasNoSignedWrap(cast<OverflowingBinaryOperator>(I));
computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, DemandedElts,
Known, Known2, Depth, Q);
bool NUW = Q.IIQ.hasNoUnsignedWrap(cast<OverflowingBinaryOperator>(I));
computeKnownBitsMul(I->getOperand(0), I->getOperand(1), NSW, NUW,
DemandedElts, Known, Known2, Depth, Q);
break;
}
case Instruction::UDiv: {
Expand Down Expand Up @@ -1959,7 +1967,7 @@ static void computeKnownBitsFromOperator(const Operator *I,
case Intrinsic::umul_with_overflow:
case Intrinsic::smul_with_overflow:
computeKnownBitsMul(II->getArgOperand(0), II->getArgOperand(1), false,
DemandedElts, Known, Known2, Depth, Q);
false, DemandedElts, Known, Known2, Depth, Q);
break;
}
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/Transforms/InstCombine/ashr-lshr.ll
Original file line number Diff line number Diff line change
Expand Up @@ -741,7 +741,7 @@ define i32 @lshr_mul_times_5_div_4_exact_2(i32 %x) {

define i32 @ashr_mul_times_3_div_2(i32 %0) {
; CHECK-LABEL: @ashr_mul_times_3_div_2(
; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 1
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 1
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP0]], [[TMP2]]
; CHECK-NEXT: ret i32 [[ASHR]]
;
Expand Down Expand Up @@ -815,7 +815,7 @@ define i32 @ashr_mul_times_3_div_2_exact_2(i32 %x) {

define i32 @ashr_mul_times_5_div_4(i32 %0) {
; CHECK-LABEL: @ashr_mul_times_5_div_4(
; CHECK-NEXT: [[TMP2:%.*]] = ashr i32 [[TMP0:%.*]], 2
; CHECK-NEXT: [[TMP2:%.*]] = lshr i32 [[TMP0:%.*]], 2
; CHECK-NEXT: [[ASHR:%.*]] = add nuw nsw i32 [[TMP0]], [[TMP2]]
; CHECK-NEXT: ret i32 [[ASHR]]
;
Expand Down
65 changes: 65 additions & 0 deletions llvm/test/Transforms/InstCombine/known-bits.ll
Original file line number Diff line number Diff line change
Expand Up @@ -2051,6 +2051,71 @@ exit:
ret i16 %conv
}

define i1 @mul_nuw_nsw_nonneg_const(i8 %x) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_const(
; CHECK-NEXT: ret i1 true
;
%mul = mul nuw nsw i8 %x, 3
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

define i1 @mul_nuw_nsw_nonneg_const_missing_nuw(i8 %x) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_const_missing_nuw(
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[X:%.*]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%mul = mul nsw i8 %x, 3
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

define i1 @mul_nuw_nsw_nonneg_const_missing_nsw(i8 %x) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_const_missing_nsw(
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i8 [[X:%.*]], 3
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%mul = mul nuw i8 %x, 3
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

define i1 @mul_nuw_nsw_nonneg_can_be_one(i8 %x, i8 %y) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_can_be_one(
; CHECK-NEXT: [[Y_NNEG:%.*]] = and i8 [[Y:%.*]], 127
; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y_NNEG]]
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[MUL]], -1
; CHECK-NEXT: ret i1 [[CMP]]
;
%y.nneg = and i8 %y, 127
%mul = mul nuw nsw i8 %x, %y.nneg
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

define i1 @mul_nuw_nsw_nonneg_cant_be_one(i8 %x, i8 %y) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_cant_be_one(
; CHECK-NEXT: ret i1 true
;
%y.nneg = and i8 %y, 127
%y.nneg.not.one = or i8 %y.nneg, 2
%mul = mul nuw nsw i8 %x, %y.nneg.not.one
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

define i1 @mul_nuw_nsw_nonneg_cant_be_one_commuted(i8 %x, i8 %y) {
; CHECK-LABEL: @mul_nuw_nsw_nonneg_cant_be_one_commuted(
; CHECK-NEXT: ret i1 true
;
%y.nneg = and i8 %y, 127
%y.nneg.not.one = or i8 %y.nneg, 2
%mul = mul nuw nsw i8 %y.nneg.not.one, %x
%cmp = icmp sgt i8 %mul, -1
ret i1 %cmp
}

declare void @dummy()
declare void @use(i1)
declare void @sink(i8)
2 changes: 1 addition & 1 deletion llvm/test/Transforms/InstCombine/rem-mul-shl.ll
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ define i8 @srem_non_matching(i8 %X, i8 %Y) {
; CHECK-LABEL: @srem_non_matching(
; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 15
; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Y:%.*]], 5
; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]]
; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]]
; CHECK-NEXT: ret i8 [[R]]
;
%BO0 = mul nsw nuw i8 %X, 15
Expand Down

0 comments on commit 6a339a1

Please sign in to comment.