forked from OSchip/llvm-project
[ValueTracking] Improve mul handling in isKnownNonEqual()
X != X * C is true if: * C is not 0 or 1 * X is not 0 * mul is nsw or nuw Proof: https://alive2.llvm.org/ce/z/uwF29z This is motivated by one of the cases in D98422.
This commit is contained in:
parent
f5bbdf2a67
commit
d11d5d1c5f
|
@ -2530,6 +2530,19 @@ static bool isAddOfNonZero(const Value *V1, const Value *V2, unsigned Depth,
|
|||
return isKnownNonZero(Op, Depth + 1, Q);
|
||||
}
|
||||
|
||||
/// Return true if V2 == V1 * C, where V1 is known non-zero, C is not 0/1 and
|
||||
/// the multiplication is nuw or nsw.
|
||||
static bool isNonEqualMul(const Value *V1, const Value *V2, unsigned Depth,
|
||||
const Query &Q) {
|
||||
if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(V2)) {
|
||||
const APInt *C;
|
||||
return match(OBO, m_Mul(m_Specific(V1), m_APInt(C))) &&
|
||||
(OBO->hasNoUnsignedWrap() || OBO->hasNoSignedWrap()) &&
|
||||
!C->isNullValue() && !C->isOneValue() &&
|
||||
isKnownNonZero(V1, Depth + 1, Q);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Return true if it is known that V1 != V2.
|
||||
static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
|
||||
|
@ -2591,6 +2604,9 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth,
|
|||
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
|
||||
return true;
|
||||
|
||||
if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q))
|
||||
return true;
|
||||
|
||||
if (V1->getType()->isIntOrIntVectorTy()) {
|
||||
// Are any known bits in V1 contradictory to known bits in V2? If V1
|
||||
// has a known zero where V2 has a known one, they must not be equal.
|
||||
|
|
|
@ -216,10 +216,7 @@ define i1 @mul_constantexpr(i16 %a) {
|
|||
|
||||
define i1 @mul_nuw(i16 %x) {
|
||||
; CHECK-LABEL: @mul_nuw(
|
||||
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
|
||||
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[NZ]], 2
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%nz = or i16 %x, 2
|
||||
%mul = mul nuw i16 %nz, 2
|
||||
|
@ -229,10 +226,7 @@ define i1 @mul_nuw(i16 %x) {
|
|||
|
||||
define i1 @mul_nuw_comm(i16 %x) {
|
||||
; CHECK-LABEL: @mul_nuw_comm(
|
||||
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
|
||||
; CHECK-NEXT: [[MUL:%.*]] = mul nuw i16 [[NZ]], 2
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[MUL]], [[NZ]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%nz = or i16 %x, 2
|
||||
%mul = mul nuw i16 %nz, 2
|
||||
|
@ -242,10 +236,7 @@ define i1 @mul_nuw_comm(i16 %x) {
|
|||
|
||||
define i1 @mul_nsw(i16 %x) {
|
||||
; CHECK-LABEL: @mul_nsw(
|
||||
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
|
||||
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[NZ]], 2
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[NZ]], [[MUL]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%nz = or i16 %x, 2
|
||||
%mul = mul nsw i16 %nz, 2
|
||||
|
@ -255,10 +246,7 @@ define i1 @mul_nsw(i16 %x) {
|
|||
|
||||
define i1 @mul_nsw_comm(i16 %x) {
|
||||
; CHECK-LABEL: @mul_nsw_comm(
|
||||
; CHECK-NEXT: [[NZ:%.*]] = or i16 [[X:%.*]], 2
|
||||
; CHECK-NEXT: [[MUL:%.*]] = mul nsw i16 [[NZ]], 2
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[MUL]], [[NZ]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
; CHECK-NEXT: ret i1 false
|
||||
;
|
||||
%nz = or i16 %x, 2
|
||||
%mul = mul nsw i16 %nz, 2
|
||||
|
|
Loading…
Reference in New Issue