1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; Test for (x & y) + ~(x | y) -> ~(x ^ y) 3; RUN: opt < %s -passes=instcombine -S | FileCheck %s 4 5; (x & y) + ~(x | y) 6define i32 @src(i32 noundef %0, i32 noundef %1) { 7; CHECK-LABEL: @src( 8; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]] 9; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 10; CHECK-NEXT: ret i32 [[TMP4]] 11; 12 %3 = and i32 %1, %0 13 %4 = or i32 %1, %0 14 %5 = xor i32 %4, -1 15 %6 = add i32 %3, %5 16 ret i32 %6 17} 18 19; vector version of src 20define <2 x i32> @src_vec(<2 x i32> noundef %0, <2 x i32> noundef %1) { 21; CHECK-LABEL: @src_vec( 22; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i32> [[TMP1:%.*]], [[TMP0:%.*]] 23; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], splat (i32 -1) 24; CHECK-NEXT: ret <2 x i32> [[TMP4]] 25; 26 %3 = and <2 x i32> %1, %0 27 %4 = or <2 x i32> %1, %0 28 %5 = xor <2 x i32> %4, <i32 -1, i32 -1> 29 %6 = add <2 x i32> %3, %5 30 ret <2 x i32> %6 31} 32 33; vector version of src with poison values 34define <2 x i32> @src_vec_poison(<2 x i32> noundef %0, <2 x i32> noundef %1) { 35; CHECK-LABEL: @src_vec_poison( 36; CHECK-NEXT: [[TMP3:%.*]] = xor <2 x i32> [[TMP1:%.*]], [[TMP0:%.*]] 37; CHECK-NEXT: [[TMP4:%.*]] = xor <2 x i32> [[TMP3]], splat (i32 -1) 38; CHECK-NEXT: ret <2 x i32> [[TMP4]] 39; 40 %3 = and <2 x i32> %1, %0 41 %4 = or <2 x i32> %1, %0 42 %5 = xor <2 x i32> %4, <i32 -1, i32 poison> 43 %6 = add <2 x i32> %3, %5 44 ret <2 x i32> %6 45} 46 47; (x & y) + ~(y | x) 48define i32 @src2(i32 noundef %0, i32 noundef %1) { 49; CHECK-LABEL: @src2( 50; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]] 51; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 52; CHECK-NEXT: ret i32 [[TMP4]] 53; 54 %3 = and i32 %1, %0 55 %4 = or i32 %0, %1 56 %5 = xor i32 %4, -1 57 %6 = add i32 %3, %5 58 ret i32 %6 59} 60 61; (x & y) + (~x & ~y) 62define i32 @src3(i32 noundef %0, i32 noundef %1) { 63; CHECK-LABEL: @src3( 64; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]] 65; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 66; CHECK-NEXT: ret i32 [[TMP4]] 67; 68 %3 = and i32 %1, %0 69 %4 = xor i32 %0, -1 70 %5 = xor i32 %1, -1 71 %6 = and i32 %4, %5 72 %7 = add i32 %3, %6 73 ret i32 %7 74} 75 76; ~(x | y) + (y & x) 77define i32 @src4(i32 noundef %0, i32 noundef %1) { 78; CHECK-LABEL: @src4( 79; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP0:%.*]], [[TMP1:%.*]] 80; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 81; CHECK-NEXT: ret i32 [[TMP4]] 82; 83 %3 = and i32 %0, %1 84 %4 = or i32 %1, %0 85 %5 = xor i32 %4, -1 86 %6 = add i32 %3, %5 87 ret i32 %6 88} 89 90; ~(x | y) + (x & y) 91define i32 @src5(i32 noundef %0, i32 noundef %1) { 92; CHECK-LABEL: @src5( 93; CHECK-NEXT: [[TMP3:%.*]] = xor i32 [[TMP1:%.*]], [[TMP0:%.*]] 94; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 95; CHECK-NEXT: ret i32 [[TMP4]] 96; 97 %3 = or i32 %1, %0 98 %4 = xor i32 %3, -1 99 %5 = and i32 %1, %0 100 %6 = add i32 %4, %5 101 ret i32 %6 102} 103 104; (a & b) + ~(c | d) 105define i32 @src6(i32 %0, i32 %1, i32 %2, i32 %3) { 106; CHECK-LABEL: @src6( 107; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP0:%.*]], [[TMP1:%.*]] 108; CHECK-NEXT: [[TMP6:%.*]] = or i32 [[TMP2:%.*]], [[TMP3:%.*]] 109; CHECK-NEXT: [[TMP7:%.*]] = xor i32 [[TMP6]], -1 110; CHECK-NEXT: [[TMP8:%.*]] = add i32 [[TMP5]], [[TMP7]] 111; CHECK-NEXT: ret i32 [[TMP8]] 112; 113 %5 = and i32 %0, %1 114 %6 = or i32 %2, %3 115 %7 = xor i32 %6, -1 116 %8 = add i32 %5, %7 117 ret i32 %8 118} 119