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 both x and y are free to invert. 9 10declare void @use1(i1) 11 12; Most basic positive test 13define i1 @t0(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 14; CHECK-LABEL: @t0( 15; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 16; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] 17; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 18; CHECK-NEXT: ret i1 [[I3_NOT]] 19; 20 %i1 = icmp eq i32 %v0, %v1 21 %i2 = icmp eq i32 %v2, %v3 22 %i3 = select i1 %i2, i1 true, i1 %i1 23 %i4 = xor i1 %i3, -1 24 ret i1 %i4 25} 26 27; All operands must be invertible 28define i1 @n1(i1 %i1, i32 %v2, i32 %v3) { 29; CHECK-LABEL: @n1( 30; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] 31; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 true, i1 [[I1:%.*]] 32; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true 33; CHECK-NEXT: ret i1 [[I4]] 34; 35 %i2 = icmp eq i32 %v2, %v3 36 %i3 = select i1 %i2, i1 true, i1 %i1 37 %i4 = xor i1 %i3, -1 38 ret i1 %i4 39} 40define i1 @n2(i32 %v0, i32 %v1, i1 %i2) { 41; CHECK-LABEL: @n2( 42; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 43; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2:%.*]], true 44; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 [[I1]], i1 false 45; CHECK-NEXT: ret i1 [[I3]] 46; 47 %i1 = icmp eq i32 %v0, %v1 48 %i3 = select i1 %i2, i1 true, i1 %i1 49 %i4 = xor i1 %i3, -1 50 ret i1 %i4 51} 52define i1 @n3(i1 %i1, i1 %i2) { 53; CHECK-LABEL: @n3( 54; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2:%.*]], i1 true, i1 [[I1:%.*]] 55; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true 56; CHECK-NEXT: ret i1 [[I4]] 57; 58 %i3 = select i1 %i2, i1 true, i1 %i1 59 %i4 = xor i1 %i3, -1 60 ret i1 %i4 61} 62 63; All other uses of operands must be invertible 64define i1 @n4(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 65; CHECK-LABEL: @n4( 66; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]] 67; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] 68; CHECK-NEXT: call void @use1(i1 [[I1]]) 69; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 true, i1 [[I1]] 70; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true 71; CHECK-NEXT: ret i1 [[I4]] 72; 73 %i1 = icmp eq i32 %v0, %v1 74 %i2 = icmp eq i32 %v2, %v3 75 call void @use1(i1 %i1) 76 %i3 = select i1 %i2, i1 true, i1 %i1 77 %i4 = xor i1 %i3, -1 78 ret i1 %i4 79} 80define i1 @n5(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 81; CHECK-LABEL: @n5( 82; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 83; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] 84; CHECK-NEXT: call void @use1(i1 [[I2]]) 85; CHECK-NEXT: [[NOT_I2:%.*]] = xor i1 [[I2]], true 86; CHECK-NEXT: [[I3:%.*]] = select i1 [[NOT_I2]], i1 [[I1]], i1 false 87; CHECK-NEXT: ret i1 [[I3]] 88; 89 %i1 = icmp eq i32 %v0, %v1 90 %i2 = icmp eq i32 %v2, %v3 91 call void @use1(i1 %i2) 92 %i3 = select i1 %i2, i1 true, i1 %i1 93 %i4 = xor i1 %i3, -1 94 ret i1 %i4 95} 96define i1 @n6(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 97; CHECK-LABEL: @n6( 98; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]] 99; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] 100; CHECK-NEXT: call void @use1(i1 [[I1]]) 101; CHECK-NEXT: call void @use1(i1 [[I2]]) 102; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 true, i1 [[I1]] 103; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true 104; CHECK-NEXT: ret i1 [[I4]] 105; 106 %i1 = icmp eq i32 %v0, %v1 107 %i2 = icmp eq i32 %v2, %v3 108 call void @use1(i1 %i1) 109 call void @use1(i1 %i2) 110 %i3 = select i1 %i2, i1 true, i1 %i1 111 %i4 = xor i1 %i3, -1 112 ret i1 %i4 113} 114 115; Hands have invertible uses 116define i1 @t7(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 117; CHECK-LABEL: @t7( 118; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 119; CHECK-NEXT: call void @use1(i1 [[I1]]) 120; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] 121; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 122; CHECK-NEXT: ret i1 [[I3_NOT]] 123; 124 %i1 = icmp eq i32 %v0, %v1 125 %i1.not = xor i1 %i1, -1 126 call void @use1(i1 %i1.not) 127 %i2 = icmp eq i32 %v2, %v3 128 %i3 = select i1 %i2, i1 true, i1 %i1 129 %i4 = xor i1 %i3, -1 130 ret i1 %i4 131} 132define i1 @t8(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 133; CHECK-LABEL: @t8( 134; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 135; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] 136; CHECK-NEXT: call void @use1(i1 [[I2]]) 137; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 138; CHECK-NEXT: ret i1 [[I3_NOT]] 139; 140 %i1 = icmp eq i32 %v0, %v1 141 %i2 = icmp eq i32 %v2, %v3 142 %i2.not = xor i1 %i2, -1 143 call void @use1(i1 %i2.not) 144 %i3 = select i1 %i2, i1 true, i1 %i1 145 %i4 = xor i1 %i3, -1 146 ret i1 %i4 147} 148define i1 @t9(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 149; CHECK-LABEL: @t9( 150; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 151; CHECK-NEXT: call void @use1(i1 [[I1]]) 152; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] 153; CHECK-NEXT: call void @use1(i1 [[I2]]) 154; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 155; CHECK-NEXT: ret i1 [[I3_NOT]] 156; 157 %i1 = icmp eq i32 %v0, %v1 158 %i1.not = xor i1 %i1, -1 159 call void @use1(i1 %i1.not) 160 %i2 = icmp eq i32 %v2, %v3 161 %i2.not = xor i1 %i2, -1 162 call void @use1(i1 %i2.not) 163 %i3 = select i1 %i2, i1 true, i1 %i1 164 %i4 = xor i1 %i3, -1 165 ret i1 %i4 166} 167 168; Select can have other uses 169 170; Not all uses can be adapted 171define i1 @n10(i32 %v0, i32 %v1, i32 %v2, i32 %v3) { 172; CHECK-LABEL: @n10( 173; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]] 174; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]] 175; CHECK-NEXT: [[I3:%.*]] = select i1 [[I2]], i1 true, i1 [[I1]] 176; CHECK-NEXT: call void @use1(i1 [[I3]]) 177; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true 178; CHECK-NEXT: ret i1 [[I4]] 179; 180 %i1 = icmp eq i32 %v0, %v1 181 %i2 = icmp eq i32 %v2, %v3 182 %i3 = select i1 %i2, i1 true, i1 %i1 183 call void @use1(i1 %i3) 184 %i4 = xor i1 %i3, -1 185 ret i1 %i4 186} 187 188; All other uses can be adapted. 189define i1 @t11(i32 %v0, i32 %v1, i32 %v2, i32 %v3, i1 %v4, i1 %v5) { 190; CHECK-LABEL: @t11( 191; CHECK-NEXT: [[I1:%.*]] = icmp ne i32 [[V0:%.*]], [[V1:%.*]] 192; CHECK-NEXT: [[I2:%.*]] = icmp ne i32 [[V2:%.*]], [[V3:%.*]] 193; CHECK-NEXT: [[I3_NOT:%.*]] = select i1 [[I2]], i1 [[I1]], i1 false 194; CHECK-NEXT: [[I5:%.*]] = select i1 [[I3_NOT]], i1 [[V5:%.*]], i1 [[V4:%.*]] 195; CHECK-NEXT: call void @use1(i1 [[I5]]) 196; CHECK-NEXT: ret i1 [[I3_NOT]] 197; 198 %i1 = icmp eq i32 %v0, %v1 199 %i2 = icmp eq i32 %v2, %v3 200 %i3 = select i1 %i2, i1 true, i1 %i1 201 %i4 = xor i1 %i3, -1 202 %i5 = select i1 %i3, i1 %v4, i1 %v5 203 call void @use1(i1 %i5) 204 ret i1 %i4 205} 206