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,
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.
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
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
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
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