; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s ; (x&z) ^ (y&z) -> (x^y)&z define i32 @test1(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test1( ; CHECK-NEXT: [[T61:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[T7:%.*]] = and i32 [[Z:%.*]], [[T61]] ; CHECK-NEXT: ret i32 [[T7]] ; %t3 = and i32 %z, %x %t6 = and i32 %z, %y %t7 = xor i32 %t3, %t6 ret i32 %t7 } ; (x & y) ^ (x|y) -> x^y define i32 @test2(i32 %x, i32 %y, i32 %z) { ; CHECK-LABEL: @test2( ; CHECK-NEXT: [[T7:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: ret i32 [[T7]] ; %t3 = and i32 %y, %x %t6 = or i32 %y, %x %t7 = xor i32 %t3, %t6 ret i32 %t7 } define i32 @PR38781(i32 %a, i32 %b) { ; CHECK-LABEL: @PR38781( ; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[B:%.*]], [[A:%.*]] ; CHECK-NEXT: [[AND2:%.*]] = icmp sgt i32 [[TMP1]], -1 ; CHECK-NEXT: [[AND:%.*]] = zext i1 [[AND2]] to i32 ; CHECK-NEXT: ret i32 [[AND]] ; %a.lobit = lshr i32 %a, 31 %a.lobit.not = xor i32 %a.lobit, 1 %b.lobit = lshr i32 %b, 31 %b.lobit.not = xor i32 %b.lobit, 1 %and = and i32 %b.lobit.not, %a.lobit.not ret i32 %and } ; (a ^ 4) & (a ^ ~4) -> 0 define i32 @PR75692_1(i32 %x) { ; CHECK-LABEL: @PR75692_1( ; CHECK-NEXT: ret i32 0 ; %t2 = xor i32 %x, 4 %t3 = xor i32 %x, -5 %t4 = and i32 %t2, %t3 ret i32 %t4 } ; (a ^ 4) & (a ^ 3) is not zero define i32 @PR75692_2(i32 %x) { ; CHECK-LABEL: @PR75692_2( ; CHECK-NEXT: [[T2:%.*]] = xor i32 [[X:%.*]], 4 ; CHECK-NEXT: [[T3:%.*]] = xor i32 [[X]], -4 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T2]], [[T3]] ; CHECK-NEXT: ret i32 [[T4]] ; %t2 = xor i32 %x, 4 %t3 = xor i32 %x, -4 %t4 = and i32 %t2, %t3 ret i32 %t4 } ; (a ^ 4) & (b ^ ~4) is not zero, since a != b is possible define i32 @PR75692_3(i32 %x, i32 %y) { ; CHECK-LABEL: @PR75692_3( ; CHECK-NEXT: [[T2:%.*]] = xor i32 [[X:%.*]], 4 ; CHECK-NEXT: [[T3:%.*]] = xor i32 [[Y:%.*]], -5 ; CHECK-NEXT: [[T4:%.*]] = and i32 [[T2]], [[T3]] ; CHECK-NEXT: ret i32 [[T4]] ; %t2 = xor i32 %x, 4 %t3 = xor i32 %y, -5 %t4 = and i32 %t2, %t3 ret i32 %t4 } ; ((X + C) & M) ^ M --> (~C − X) & M define i8 @add_and_xor_basic(i8 %x) { ; CHECK-LABEL: @add_and_xor_basic( ; CHECK-NEXT: [[ADD:%.*]] = sub i8 10, [[X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[ADD]], 15 ; CHECK-NEXT: ret i8 [[AND]] ; %add = add i8 %x, 5 %and = and i8 %add, 15 %xor = xor i8 %and, 15 ret i8 %xor } define <4 x i32> @add_and_xor_vector_splat(<4 x i32> %x) { ; CHECK-LABEL: @add_and_xor_vector_splat( ; CHECK-NEXT: [[ADD:%.*]] = sub <4 x i32> splat (i32 53), [[X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and <4 x i32> [[ADD]], splat (i32 63) ; CHECK-NEXT: ret <4 x i32> [[AND]] ; %add = add <4 x i32> %x, %and = and <4 x i32> %add, %xor = xor <4 x i32> %and, ret <4 x i32> %xor } define i32 @add_and_xor_overflow_addc(i32 %x) { ; CHECK-LABEL: @add_and_xor_overflow_addc( ; CHECK-NEXT: [[ADD:%.*]] = sub i32 27, [[X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 31 ; CHECK-NEXT: ret i32 [[AND]] ; %add = add i32 %x, 100 %and = and i32 %add, 31 %xor = xor i32 %and, 31 ret i32 %xor } define i32 @add_and_xor_negative_addc(i32 %x) { ; CHECK-LABEL: @add_and_xor_negative_addc( ; CHECK-NEXT: [[ADD:%.*]] = sub i32 1, [[X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i32 [[ADD]], 255 ; CHECK-NEXT: ret i32 [[AND]] ; %add = add i32 %x, -2 %and = and i32 %add, 255 %xor = xor i32 %and, 255 ret i32 %xor } define i8 @add_and_xor_not_low_mask(i8 %x) { ; CHECK-LABEL: @add_and_xor_not_low_mask( ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 1, [[X:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = and i8 [[TMP1]], -18 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, -2 %and = and i8 %add, 238 %xor = xor i8 %and, 238 ret i8 %xor } define i8 @add_and_xor_not_low_mask2(i8 %x) { ; CHECK-LABEL: @add_and_xor_not_low_mask2( ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 1, [[X:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = and i8 [[TMP1]], 119 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, -2 %and = and i8 %add, 119 %xor = xor i8 %and, 119 ret i8 %xor } define i8 @add_and_xor_not_low_mask3(i8 %x) { ; CHECK-LABEL: @add_and_xor_not_low_mask3( ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 1, [[X:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = and i8 [[TMP1]], -91 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, -2 %and = and i8 %add, 165 %xor = xor i8 %and, 165 ret i8 %xor } define i8 @add_and_xor_not_low_mask4(i8 %x) { ; CHECK-LABEL: @add_and_xor_not_low_mask4( ; CHECK-NEXT: [[TMP1:%.*]] = sub i8 1, [[X:%.*]] ; CHECK-NEXT: [[XOR:%.*]] = and i8 [[TMP1]], -86 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, -2 %and = and i8 %add, 170 %xor = xor i8 %and, 170 ret i8 %xor } ; This test is trasformed to 'xor(and(add x, 11), 15), 15)' and being applied. define i8 @add_and_xor_sub_op(i8 %x) { ; CHECK-LABEL: @add_and_xor_sub_op( ; CHECK-NEXT: [[SUB:%.*]] = sub i8 4, [[X:%.*]] ; CHECK-NEXT: [[AND:%.*]] = and i8 [[SUB]], 15 ; CHECK-NEXT: ret i8 [[AND]] ; %sub = sub i8 %x, 5 %and = and i8 %sub, 15 %xor = xor i8 %and, 15 ret i8 %xor } ; and_xor_mask negative tests define i8 @neg_add_and_xor_mask_mismatch(i8 %x) { ; CHECK-LABEL: @neg_add_and_xor_mask_mismatch( ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 5 ; CHECK-NEXT: [[AND:%.*]] = and i8 [[ADD]], 15 ; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], 7 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, 5 %and = and i8 %add, 15 %xor = xor i8 %and, 7 ret i8 %xor } define i8 @neg_add_and_xor_multi_use(i8 %x) { ; CHECK-LABEL: @neg_add_and_xor_multi_use( ; CHECK-NEXT: [[ADD:%.*]] = add i8 [[X:%.*]], 5 ; CHECK-NEXT: call void @use(i8 [[ADD]]) ; CHECK-NEXT: [[AND:%.*]] = and i8 [[ADD]], 15 ; CHECK-NEXT: [[XOR:%.*]] = xor i8 [[AND]], 15 ; CHECK-NEXT: ret i8 [[XOR]] ; %add = add i8 %x, 5 call void @use(i8 %add) %and = and i8 %add, 15 %xor = xor i8 %and, 15 ret i8 %xor } declare void @use(i8)