; 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_constant_samesign(i42 %X, i42 %Y) { ; CHECK-LABEL: @icmp_equality_test_constant_samesign( ; 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 samesign 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, %YeqC = icmp eq <2 x i64> %Y, %XeqY = icmp eq <2 x i64> %X, %Y %not.YeqC = xor <2 x i1> %YeqC, %and = select <2 x i1> %not.YeqC, <2 x i1> %XeqY, <2 x i1> %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 }