| ; 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, <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 |
| } |