1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; Transform 5; z = (~x) & y 6; into: 7; z = ~(x | (~y)) 8; iff y is free to invert and all uses of z can be freely updated. 9 10declare void @use1(i1) 11declare void @use8(i8) 12 13; Most basic positive test 14define i8 @t0(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 15; CHECK-LABEL: @t0( 16; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]] 17; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I0:%.*]], i1 true, i1 [[I1]] 18; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V3:%.*]], i8 [[V2:%.*]] 19; CHECK-NEXT: ret i8 [[I4]] 20; 21 %i1 = icmp eq i8 %v0, %v1 22 %i2 = xor i1 %i0, -1 23 %i3 = select i1 %i2, i1 %i1, i1 false 24 %i4 = select i1 %i3, i8 %v2, i8 %v3 25 ret i8 %i4 26} 27define i8 @t0_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 28; CHECK-LABEL: @t0_commutative( 29; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]] 30; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I1]], i1 true, i1 [[I0:%.*]] 31; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V3:%.*]], i8 [[V2:%.*]] 32; CHECK-NEXT: ret i8 [[I4]] 33; 34 %i1 = icmp eq i8 %v0, %v1 35 %i2 = xor i1 %i0, -1 36 %i3 = select i1 %i1, i1 %i2, i1 false 37 %i4 = select i1 %i3, i8 %v2, i8 %v3 38 ret i8 %i4 39} 40define i8 @t1(i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) { 41; CHECK-LABEL: @t1( 42; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]] 43; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]] 44; CHECK-NEXT: call void @use1(i1 [[I0]]) 45; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I0]], i1 true, i1 [[I1]] 46; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]] 47; CHECK-NEXT: ret i8 [[I4]] 48; 49 %i0 = icmp eq i8 %v0, %v1 50 %i1 = icmp eq i8 %v2, %v3 51 call void @use1(i1 %i0) 52 %i2 = xor i1 %i0, -1 53 %i3 = select i1 %i2, i1 %i1, i1 false 54 %i4 = select i1 %i3, i8 %v4, i8 %v5 55 ret i8 %i4 56} 57define i8 @t1_commutative(i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) { 58; CHECK-LABEL: @t1_commutative( 59; CHECK-NEXT: [[I0:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]] 60; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V2:%.*]], [[V3:%.*]] 61; CHECK-NEXT: call void @use1(i1 [[I0]]) 62; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I1]], i1 true, i1 [[I0]] 63; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]] 64; CHECK-NEXT: ret i8 [[I4]] 65; 66 %i0 = icmp eq i8 %v0, %v1 67 %i1 = icmp eq i8 %v2, %v3 68 call void @use1(i1 %i0) 69 %i2 = xor i1 %i0, -1 70 %i3 = select i1 %i1, i1 %i2, i1 false 71 %i4 = select i1 %i3, i8 %v4, i8 %v5 72 ret i8 %i4 73} 74 75; All users of %i3 must be invertible 76define i1 @n2(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 77; CHECK-LABEL: @n2( 78; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]] 79; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0:%.*]], true 80; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 81; CHECK-NEXT: ret i1 [[I3]] 82; 83 %i1 = icmp eq i8 %v0, %v1 84 %i2 = xor i1 %i0, -1 85 %i3 = select i1 %i2, i1 %i1, i1 false 86 ret i1 %i3 ; can not be inverted 87} 88 89; %i1 must be invertible 90define i8 @n3(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3) { 91; CHECK-LABEL: @n3( 92; CHECK-NEXT: [[I1:%.*]] = icmp eq i8 [[V0:%.*]], [[V1:%.*]] 93; CHECK-NEXT: call void @use1(i1 [[I1]]) 94; CHECK-NEXT: [[I2:%.*]] = xor i1 [[I0:%.*]], true 95; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 96; CHECK-NEXT: [[I4:%.*]] = select i1 [[I3]], i8 [[V2:%.*]], i8 [[V3:%.*]] 97; CHECK-NEXT: ret i8 [[I4]] 98; 99 %i1 = icmp eq i8 %v0, %v1 ; has extra uninvertible use 100 call void @use1(i1 %i1) ; bad extra use 101 %i2 = xor i1 %i0, -1 102 %i3 = select i1 %i2, i1 %i1, i1 false 103 %i4 = select i1 %i3, i8 %v2, i8 %v3 104 ret i8 %i4 105} 106 107; Extra uses are invertible 108define i8 @t4(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) { 109; CHECK-LABEL: @t4( 110; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]] 111; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]] 112; CHECK-NEXT: call void @use8(i8 [[I2]]) 113; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I0:%.*]], i1 true, i1 [[I1]] 114; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]] 115; CHECK-NEXT: ret i8 [[I5]] 116; 117 %i1 = icmp eq i8 %v0, %v1 ; has extra invertible use 118 %i2 = select i1 %i1, i8 %v2, i8 %v3 ; invertible use 119 call void @use8(i8 %i2) 120 %i3 = xor i1 %i0, -1 121 %i4 = select i1 %i3, i1 %i1, i1 false 122 %i5 = select i1 %i4, i8 %v4, i8 %v5 123 ret i8 %i5 124} 125define i8 @t4_commutative(i1 %i0, i8 %v0, i8 %v1, i8 %v2, i8 %v3, i8 %v4, i8 %v5) { 126; CHECK-LABEL: @t4_commutative( 127; CHECK-NEXT: [[I1:%.*]] = icmp ne i8 [[V0:%.*]], [[V1:%.*]] 128; CHECK-NEXT: [[I2:%.*]] = select i1 [[I1]], i8 [[V3:%.*]], i8 [[V2:%.*]] 129; CHECK-NEXT: call void @use8(i8 [[I2]]) 130; CHECK-NEXT: [[I4_NOT:%.*]] = select i1 [[I1]], i1 true, i1 [[I0:%.*]] 131; CHECK-NEXT: [[I5:%.*]] = select i1 [[I4_NOT]], i8 [[V5:%.*]], i8 [[V4:%.*]] 132; CHECK-NEXT: ret i8 [[I5]] 133; 134 %i1 = icmp eq i8 %v0, %v1 ; has extra invertible use 135 %i2 = select i1 %i1, i8 %v2, i8 %v3 ; invertible use 136 call void @use8(i8 %i2) 137 %i3 = xor i1 %i0, -1 138 %i4 = select i1 %i1, i1 %i3, i1 false 139 %i5 = select i1 %i4, i8 %v4, i8 %v5 140 ret i8 %i5 141} 142