206 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Transform5; 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 test13define 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:%.*]] = or i1 [[I2]], [[I1]]18; CHECK-NEXT: ret i1 [[I3_NOT]]19;20 %i1 = icmp eq i32 %v0, %v121 %i2 = icmp eq i32 %v2, %v322 %i3 = and i1 %i2, %i123 %i4 = xor i1 %i3, -124 ret i1 %i425}26 27; All operands must be invertible28define 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:%.*]] = and i1 [[I2]], [[I1:%.*]]32; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true33; CHECK-NEXT: ret i1 [[I4]]34;35 %i2 = icmp eq i32 %v2, %v336 %i3 = and i1 %i2, %i137 %i4 = xor i1 %i3, -138 ret i1 %i439}40define i1 @n2(i32 %v0, i32 %v1, i1 %i2) {41; CHECK-LABEL: @n2(42; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]43; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2:%.*]], [[I1]]44; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true45; CHECK-NEXT: ret i1 [[I4]]46;47 %i1 = icmp eq i32 %v0, %v148 %i3 = and i1 %i2, %i149 %i4 = xor i1 %i3, -150 ret i1 %i451}52define i1 @n3(i1 %i1, i1 %i2) {53; CHECK-LABEL: @n3(54; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2:%.*]], [[I1:%.*]]55; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true56; CHECK-NEXT: ret i1 [[I4]]57;58 %i3 = and i1 %i2, %i159 %i4 = xor i1 %i3, -160 ret i1 %i461}62 63; All other uses of operands must be invertible64define 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:%.*]] = and i1 [[I2]], [[I1]]70; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true71; CHECK-NEXT: ret i1 [[I4]]72;73 %i1 = icmp eq i32 %v0, %v174 %i2 = icmp eq i32 %v2, %v375 call void @use1(i1 %i1)76 %i3 = and i1 %i2, %i177 %i4 = xor i1 %i3, -178 ret i1 %i479}80define i1 @n5(i32 %v0, i32 %v1, i32 %v2, i32 %v3) {81; CHECK-LABEL: @n5(82; CHECK-NEXT: [[I1:%.*]] = icmp eq i32 [[V0:%.*]], [[V1:%.*]]83; CHECK-NEXT: [[I2:%.*]] = icmp eq i32 [[V2:%.*]], [[V3:%.*]]84; CHECK-NEXT: call void @use1(i1 [[I2]])85; CHECK-NEXT: [[I3:%.*]] = and i1 [[I2]], [[I1]]86; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true87; CHECK-NEXT: ret i1 [[I4]]88;89 %i1 = icmp eq i32 %v0, %v190 %i2 = icmp eq i32 %v2, %v391 call void @use1(i1 %i2)92 %i3 = and i1 %i2, %i193 %i4 = xor i1 %i3, -194 ret i1 %i495}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:%.*]] = and i1 [[I2]], [[I1]]103; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true104; CHECK-NEXT: ret i1 [[I4]]105;106 %i1 = icmp eq i32 %v0, %v1107 %i2 = icmp eq i32 %v2, %v3108 call void @use1(i1 %i1)109 call void @use1(i1 %i2)110 %i3 = and i1 %i2, %i1111 %i4 = xor i1 %i3, -1112 ret i1 %i4113}114 115; Hands have invertible uses116define 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:%.*]] = or i1 [[I2]], [[I1]]122; CHECK-NEXT: ret i1 [[I3_NOT]]123;124 %i1 = icmp eq i32 %v0, %v1125 %i1.not = xor i1 %i1, -1126 call void @use1(i1 %i1.not)127 %i2 = icmp eq i32 %v2, %v3128 %i3 = and i1 %i2, %i1129 %i4 = xor i1 %i3, -1130 ret i1 %i4131}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:%.*]] = or i1 [[I2]], [[I1]]138; CHECK-NEXT: ret i1 [[I3_NOT]]139;140 %i1 = icmp eq i32 %v0, %v1141 %i2 = icmp eq i32 %v2, %v3142 %i2.not = xor i1 %i2, -1143 call void @use1(i1 %i2.not)144 %i3 = and i1 %i2, %i1145 %i4 = xor i1 %i3, -1146 ret i1 %i4147}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:%.*]] = or i1 [[I2]], [[I1]]155; CHECK-NEXT: ret i1 [[I3_NOT]]156;157 %i1 = icmp eq i32 %v0, %v1158 %i1.not = xor i1 %i1, -1159 call void @use1(i1 %i1.not)160 %i2 = icmp eq i32 %v2, %v3161 %i2.not = xor i1 %i2, -1162 call void @use1(i1 %i2.not)163 %i3 = and i1 %i2, %i1164 %i4 = xor i1 %i3, -1165 ret i1 %i4166}167 168; Select can have other uses169 170; Not all uses can be adapted171define 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:%.*]] = and i1 [[I2]], [[I1]]176; CHECK-NEXT: call void @use1(i1 [[I3]])177; CHECK-NEXT: [[I4:%.*]] = xor i1 [[I3]], true178; CHECK-NEXT: ret i1 [[I4]]179;180 %i1 = icmp eq i32 %v0, %v1181 %i2 = icmp eq i32 %v2, %v3182 %i3 = and i1 %i2, %i1183 call void @use1(i1 %i3)184 %i4 = xor i1 %i3, -1185 ret i1 %i4186}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:%.*]] = or i1 [[I2]], [[I1]]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, %v1199 %i2 = icmp eq i32 %v2, %v3200 %i3 = and i1 %i2, %i1201 %i4 = xor i1 %i3, -1202 %i5 = select i1 %i3, i1 %v4, i1 %v5203 call void @use1(i1 %i5)204 ret i1 %i4205}206