| ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py |
| ; RUN: opt < %s -passes=instcombine -S | FileCheck %s |
| |
| ; Don't do anything for the fully-variable case. |
| define i4 @t0(i4 %x, i4 %y, i4 %z) { |
| ; CHECK-LABEL: @t0( |
| ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], [[Y:%.*]] |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], [[Z:%.*]] |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, %y |
| %i1 = xor i4 %i0, %z |
| ret i4 %i1 |
| } |
| |
| ; If the second operands are immediate constants, we can perform the fold. |
| define i4 @t1(i4 %x) { |
| ; CHECK-LABEL: @t1( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and i4 [[X:%.*]], 3 |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[TMP1]], 6 |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, 12 ; 0b1100 |
| %i1 = xor i4 %i0, 10 ; 0b1010 |
| ret i4 %i1 |
| } |
| |
| ; Must not have extra uses. |
| define i4 @t2(i4 %x) { |
| ; CHECK-LABEL: @t2( |
| ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], -4 |
| ; CHECK-NEXT: call void @use(i4 [[I0]]) |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], -6 |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, 12 ; 0b1100 |
| call void @use(i4 %i0) |
| %i1 = xor i4 %i0, 10 ; 0b1010 |
| ret i4 %i1 |
| } |
| |
| ; Splat constants are fine too. |
| define <2 x i4> @t3(<2 x i4> %x) { |
| ; CHECK-LABEL: @t3( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 3> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 6> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 12> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 10> |
| ret <2 x i4> %i1 |
| } |
| |
| ; Non-splat constants are fine too. |
| define <2 x i4> @t4(<2 x i4> %x) { |
| ; CHECK-LABEL: @t4( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 5> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 6> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 10> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 12> |
| ret <2 x i4> %i1 |
| } |
| |
| ; Partially-undef constants are fine. |
| define <2 x i4> @t5(<2 x i4> %x) { |
| ; CHECK-LABEL: @t5( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 12> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 undef> |
| ret <2 x i4> %i1 |
| } |
| define <2 x i4> @t6(<2 x i4> %x) { |
| ; CHECK-LABEL: @t6( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 undef> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 10> |
| ret <2 x i4> %i1 |
| } |
| define <2 x i4> @t7(<2 x i4> %x) { |
| ; CHECK-LABEL: @t7( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 undef> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 undef> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 undef> |
| ret <2 x i4> %i1 |
| } |
| |
| ; Partially-poison constants are fine. |
| define <2 x i4> @t8(<2 x i4> %x) { |
| ; CHECK-LABEL: @t8( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 12> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 poison> |
| ret <2 x i4> %i1 |
| } |
| define <2 x i4> @t9(<2 x i4> %x) { |
| ; CHECK-LABEL: @t9( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 0> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 5> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 poison> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 10> |
| ret <2 x i4> %i1 |
| } |
| define <2 x i4> @t10(<2 x i4> %x) { |
| ; CHECK-LABEL: @t10( |
| ; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i4> [[X:%.*]], <i4 3, i4 undef> |
| ; CHECK-NEXT: [[I1:%.*]] = xor <2 x i4> [[TMP1]], <i4 6, i4 poison> |
| ; CHECK-NEXT: ret <2 x i4> [[I1]] |
| ; |
| %i0 = or <2 x i4> %x, <i4 12, i4 poison> |
| %i1 = xor <2 x i4> %i0, <i4 10, i4 poison> |
| ret <2 x i4> %i1 |
| } |
| |
| ; Do not deal with general constant expressions. |
| @G = external global i32 |
| @G2 = external global i32 |
| define i4 @t11(i4 %x) { |
| ; CHECK-LABEL: @t11( |
| ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], -4 |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4) |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, 12 |
| %i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4) |
| ret i4 %i1 |
| } |
| define i4 @t12(i4 %x) { |
| ; CHECK-LABEL: @t12( |
| ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4) |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], -6 |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, ptrtoint (ptr @G to i4) |
| %i1 = xor i4 %i0, 10 |
| ret i4 %i1 |
| } |
| define i4 @t13(i4 %x) { |
| ; CHECK-LABEL: @t13( |
| ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (ptr @G to i4) |
| ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], ptrtoint (ptr @G2 to i4) |
| ; CHECK-NEXT: ret i4 [[I1]] |
| ; |
| %i0 = or i4 %x, ptrtoint (ptr @G to i4) |
| %i1 = xor i4 %i0, ptrtoint (ptr @G2 to i4) |
| ret i4 %i1 |
| } |
| |
| declare void @use(i4) |