llvm/llvm/test/Transforms/InstCombine/icmp-equality-test.ll

; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -passes=instcombine -S | FileCheck %s

define i1 @icmp_equality_test(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_constant(i42 %X, i42 %Y) {
; CHECK-LABEL: @icmp_equality_test_constant(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i42 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqC = icmp eq i42 %X, -42
  %YeqC = icmp eq i42 %Y, -42
  %XeqY = icmp eq i42 %X, %Y
  %not.YeqC = xor i1 %YeqC, true
  %and = select i1 %not.YeqC, i1 %XeqY, i1 false
  %equal = select i1 %XeqC, i1 %YeqC, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_swift_optional_pointers(i64 %X, i64 %Y) {
; CHECK-LABEL: @icmp_equality_test_swift_optional_pointers(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqC = icmp eq i64 %X, 0
  %YeqC = icmp eq i64 %Y, 0
  %either = select i1 %XeqC, i1 true, i1 %YeqC
  %both = select i1 %XeqC, i1 %YeqC, i1 false
  %XeqY = icmp eq i64 %X, %Y
  %equal = select i1 %either, i1 %both, i1 %XeqY
  ret i1 %equal
}

define <2 x i1> @icmp_equality_test_vector(<2 x i64> %X, <2 x i64> %Y) {
; CHECK-LABEL: @icmp_equality_test_vector(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq <2 x i64> [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret <2 x i1> [[XEQY]]
;
entry:
  %XeqC = icmp eq <2 x i64> %X, <i64 123, i64 456>
  %YeqC = icmp eq <2 x i64> %Y, <i64 123, i64 456>
  %XeqY = icmp eq <2 x i64> %X, %Y
  %not.YeqC = xor <2 x i1> %YeqC, <i1 true, i1 true>
  %and = select <2 x i1> %not.YeqC, <2 x i1> %XeqY, <2 x i1> <i1 false, i1 false>
  %equal = select <2 x i1> %XeqC, <2 x i1> %YeqC, <2 x i1> %and
  ret <2 x i1> %equal
}

define i1 @icmp_equality_test_commute_icmp1(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_commute_icmp1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqZ = icmp eq i64 %Z, %X
  %YeqZ = icmp eq i64 %Z, %Y
  %XeqY = icmp eq i64 %Y, %X
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_commute_icmp2(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_commute_icmp2(
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[Y:%.*]], [[X:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
  %XeqZ = icmp eq i64 %Z, %X
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %Y, %X
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_commute_select1(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_commute_select1(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %and = select i1 %YeqZ, i1 false, i1 %XeqY
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_commute_select2(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_commute_select2(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X:%.*]], [[Y:%.*]]
; CHECK-NEXT:    ret i1 [[XEQY]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %not.XeqZ = xor i1 %XeqZ, true
  %and = select i1 %YeqZ, i1 false, i1 %XeqY
  %equal = select i1 %not.XeqZ, i1 %and, i1 %YeqZ
  ret i1 %equal
}

; Negative tests below

define i1 @icmp_equality_test_wrong_constant(i64 %X, i64 %Y) {
; CHECK-LABEL: @icmp_equality_test_wrong_constant(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQC:%.*]] = icmp eq i64 [[X:%.*]], 0
; CHECK-NEXT:    [[YEQC:%.*]] = icmp eq i64 [[Y:%.*]], 999
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X]], [[Y]]
; CHECK-NEXT:    [[NOT_YEQC:%.*]] = xor i1 [[YEQC]], true
; CHECK-NEXT:    [[AND:%.*]] = select i1 [[NOT_YEQC]], i1 [[XEQY]], i1 false
; CHECK-NEXT:    [[EQUAL:%.*]] = select i1 [[XEQC]], i1 [[YEQC]], i1 [[AND]]
; CHECK-NEXT:    ret i1 [[EQUAL]]
;
entry:
  %XeqC = icmp eq i64 %X, 0
  %YeqC = icmp eq i64 %Y, 999
  %XeqY = icmp eq i64 %X, %Y
  %not.YeqC = xor i1 %YeqC, true
  %and = select i1 %not.YeqC, i1 %XeqY, i1 false
  %equal = select i1 %XeqC, i1 %YeqC, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_missing_not(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_missing_not(
; CHECK-NEXT:    [[XEQZ:%.*]] = icmp eq i64 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[YEQZ:%.*]] = icmp eq i64 [[Y:%.*]], [[Z]]
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X]], [[Y]]
; CHECK-NEXT:    [[AND:%.*]] = select i1 [[YEQZ]], i1 [[XEQY]], i1 false
; CHECK-NEXT:    [[EQUAL:%.*]] = select i1 [[XEQZ]], i1 [[YEQZ]], i1 [[AND]]
; CHECK-NEXT:    ret i1 [[EQUAL]]
;
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %and = select i1 %YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_wrong_and(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_wrong_and(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQZ:%.*]] = icmp eq i64 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[YEQZ:%.*]] = icmp eq i64 [[Y:%.*]], [[Z]]
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X]], [[Y]]
; CHECK-NEXT:    [[AND:%.*]] = select i1 [[YEQZ]], i1 [[XEQY]], i1 false
; CHECK-NEXT:    [[EQUAL:%.*]] = select i1 [[XEQZ]], i1 [[YEQZ]], i1 [[AND]]
; CHECK-NEXT:    ret i1 [[EQUAL]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 false, i1 %XeqY
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_wrong_cmp(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_wrong_cmp(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQZ:%.*]] = icmp eq i64 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[YEQZ:%.*]] = icmp eq i64 [[Y:%.*]], [[Z]]
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X]], 999
; CHECK-NEXT:    [[NOT_YEQZ:%.*]] = xor i1 [[YEQZ]], true
; CHECK-NEXT:    [[AND:%.*]] = select i1 [[NOT_YEQZ]], i1 [[XEQY]], i1 false
; CHECK-NEXT:    [[EQUAL:%.*]] = select i1 [[XEQZ]], i1 [[YEQZ]], i1 [[AND]]
; CHECK-NEXT:    ret i1 [[EQUAL]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, 999
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %YeqZ, i1 %and
  ret i1 %equal
}

define i1 @icmp_equality_test_wrong_equal(i64 %X, i64 %Y, i64 %Z) {
; CHECK-LABEL: @icmp_equality_test_wrong_equal(
; CHECK-NEXT:  entry:
; CHECK-NEXT:    [[XEQZ:%.*]] = icmp eq i64 [[X:%.*]], [[Z:%.*]]
; CHECK-NEXT:    [[YEQZ:%.*]] = icmp eq i64 [[Y:%.*]], [[Z]]
; CHECK-NEXT:    [[XEQY:%.*]] = icmp eq i64 [[X]], [[Y]]
; CHECK-NEXT:    [[NOT_YEQZ:%.*]] = xor i1 [[YEQZ]], true
; CHECK-NEXT:    [[AND:%.*]] = select i1 [[NOT_YEQZ]], i1 [[XEQY]], i1 false
; CHECK-NEXT:    [[EQUAL:%.*]] = select i1 [[XEQZ]], i1 [[AND]], i1 [[YEQZ]]
; CHECK-NEXT:    ret i1 [[EQUAL]]
;
entry:
  %XeqZ = icmp eq i64 %X, %Z
  %YeqZ = icmp eq i64 %Y, %Z
  %XeqY = icmp eq i64 %X, %Y
  %not.YeqZ = xor i1 %YeqZ, true
  %and = select i1 %not.YeqZ, i1 %XeqY, i1 false
  %equal = select i1 %XeqZ, i1 %and, i1 %YeqZ
  ret i1 %equal
}