Index: llvm/lib/Support/KnownBits.cpp =================================================================== --- llvm/lib/Support/KnownBits.cpp +++ llvm/lib/Support/KnownBits.cpp @@ -421,11 +421,25 @@ "Self multiplication knownbits mismatch"); // Compute a conservative estimate for high known-0 bits. + // TODO: This could be generalized to number of sign bits (negative numbers). unsigned LHSLeadZ = LHS.countMinLeadingZeros(); unsigned RHSLeadZ = RHS.countMinLeadingZeros(); unsigned LeadZ = std::max(LHSLeadZ + RHSLeadZ, BitWidth) - BitWidth; assert(LeadZ <= BitWidth && "More zeros than bits?"); + if (LeadZ) { + // Special-case: if one of the operands is 0/1, then the result has at least + // as many leading zeros as the other op (X*0 = 0, X*1 = X). This is always + // an improvement of the above estimate. + if (LHSLeadZ == BitWidth - 1) { + assert(LeadZ < RHSLeadZ && "Specialization should only improve estimate"); + LeadZ = RHSLeadZ; + } else if (RHSLeadZ == BitWidth - 1) { + assert(LeadZ < LHSLeadZ && "Specialization should only improve estimate"); + LeadZ = LHSLeadZ; + } + } + // The result of the bottom bits of an integer multiply can be // inferred by looking at the bottom bits of both operands and // multiplying them together. Index: llvm/test/Transforms/InstCombine/icmp-mul.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-mul.ll +++ llvm/test/Transforms/InstCombine/icmp-mul.ll @@ -684,11 +684,7 @@ define i1 @mul_of_bool(i32 %x, i8 %y) { ; CHECK-LABEL: @mul_of_bool( -; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 1 -; CHECK-NEXT: [[Z:%.*]] = zext i8 [[Y:%.*]] to i32 -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[B]], [[Z]] -; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[M]], 255 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %b = and i32 %x, 1 %z = zext i8 %y to i32 @@ -699,11 +695,7 @@ define i1 @mul_of_bool_commute(i32 %x, i32 %y) { ; CHECK-LABEL: @mul_of_bool_commute( -; CHECK-NEXT: [[X1:%.*]] = and i32 [[X:%.*]], 1 -; CHECK-NEXT: [[Y8:%.*]] = and i32 [[Y:%.*]], 255 -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[Y8]], [[X1]] -; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[M]], 255 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %x1 = and i32 %x, 1 %y8 = and i32 %y, 255 @@ -714,11 +706,7 @@ define i1 @mul_of_bools(i32 %x, i32 %y) { ; CHECK-LABEL: @mul_of_bools( -; CHECK-NEXT: [[X1:%.*]] = and i32 [[X:%.*]], 1 -; CHECK-NEXT: [[Y1:%.*]] = and i32 [[Y:%.*]], 1 -; CHECK-NEXT: [[M:%.*]] = mul nuw nsw i32 [[X1]], [[Y1]] -; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[M]], 2 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %x1 = and i32 %x, 1 %y1 = and i32 %y, 1 @@ -727,6 +715,8 @@ ret i1 %r } +; negative test - not a mask of low bit + define i1 @not_mul_of_bool(i32 %x, i8 %y) { ; CHECK-LABEL: @not_mul_of_bool( ; CHECK-NEXT: [[Q:%.*]] = and i32 [[X:%.*]], 3 @@ -742,6 +732,8 @@ ret i1 %r } +; negative test - not a single low bit + define i1 @not_mul_of_bool_commute(i32 %x, i32 %y) { ; CHECK-LABEL: @not_mul_of_bool_commute( ; CHECK-NEXT: [[X30:%.*]] = lshr i32 [[X:%.*]], 30 @@ -757,6 +749,9 @@ ret i1 %r } +; negative test - no leading zeros for 's' +; TODO: If analysis was generalized for sign bits, we could reduce this to false. + define i1 @mul_of_bool_no_lz_other_op(i32 %x, i8 %y) { ; CHECK-LABEL: @mul_of_bool_no_lz_other_op( ; CHECK-NEXT: [[B:%.*]] = and i32 [[X:%.*]], 1