; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -instcombine-infinite-loop-threshold=2 -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 (i32* @G2 to i4) ; CHECK-NEXT: ret i4 [[I1]] ; %i0 = or i4 %x, 12 %i1 = xor i4 %i0, ptrtoint (i32* @G2 to i4) ret i4 %i1 } define i4 @t12(i4 %x) { ; CHECK-LABEL: @t12( ; CHECK-NEXT: [[I0:%.*]] = or i4 [[X:%.*]], ptrtoint (i32* @G to i4) ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], -6 ; CHECK-NEXT: ret i4 [[I1]] ; %i0 = or i4 %x, ptrtoint (i32* @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 (i32* @G to i4) ; CHECK-NEXT: [[I1:%.*]] = xor i4 [[I0]], ptrtoint (i32* @G2 to i4) ; CHECK-NEXT: ret i4 [[I1]] ; %i0 = or i4 %x, ptrtoint (i32* @G to i4) %i1 = xor i4 %i0, ptrtoint (i32* @G2 to i4) ret i4 %i1 } declare void @use(i4)