715 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; Given pattern:5; icmp eq/ne (and ((x shift Q), (y oppositeshift K))), 06; we should move shifts to the same hand of 'and', i.e. e.g. rewrite as7; icmp eq/ne (and (((x shift Q) shift K), y)), 08; We are only interested in opposite logical shifts here.9 10; Basic scalar test with constants11 12define i1 @t0_const_lshr_shl_ne(i32 %x, i32 %y) {13; CHECK-LABEL: @t0_const_lshr_shl_ne(14; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 215; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]16; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 017; CHECK-NEXT: ret i1 [[T3]]18;19 %t0 = lshr i32 %x, 120 %t1 = shl i32 %y, 121 %t2 = and i32 %t1, %t022 %t3 = icmp ne i32 %t2, 023 ret i1 %t324}25define i1 @t1_const_shl_lshr_ne(i32 %x, i32 %y) {26; CHECK-LABEL: @t1_const_shl_lshr_ne(27; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 228; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]29; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 030; CHECK-NEXT: ret i1 [[T3]]31;32 %t0 = shl i32 %x, 133 %t1 = lshr i32 %y, 134 %t2 = and i32 %t1, %t035 %t3 = icmp ne i32 %t2, 036 ret i1 %t337}38 39; We are ok with 'eq' predicate too.40define i1 @t2_const_lshr_shl_eq(i32 %x, i32 %y) {41; CHECK-LABEL: @t2_const_lshr_shl_eq(42; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 243; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]44; CHECK-NEXT: [[T3:%.*]] = icmp eq i32 [[TMP2]], 045; CHECK-NEXT: ret i1 [[T3]]46;47 %t0 = lshr i32 %x, 148 %t1 = shl i32 %y, 149 %t2 = and i32 %t1, %t050 %t3 = icmp eq i32 %t2, 051 ret i1 %t352}53 54; Basic scalar test with constants after folding55 56define i1 @t3_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) {57; CHECK-LABEL: @t3_const_after_fold_lshr_shl_ne(58; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 3159; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]60; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[TMP2]], 061; CHECK-NEXT: ret i1 [[T5]]62;63 %t0 = sub i32 32, %len64 %t1 = lshr i32 %x, %t065 %t2 = add i32 %len, -166 %t3 = shl i32 %y, %t267 %t4 = and i32 %t1, %t368 %t5 = icmp ne i32 %t4, 069 ret i1 %t570}71define i1 @t4_const_after_fold_lshr_shl_ne(i32 %x, i32 %y, i32 %len) {72; CHECK-LABEL: @t4_const_after_fold_lshr_shl_ne(73; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[Y:%.*]], 3174; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[X:%.*]]75; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[TMP2]], 076; CHECK-NEXT: ret i1 [[T5]]77;78 %t0 = sub i32 32, %len79 %t1 = shl i32 %x, %t080 %t2 = add i32 %len, -181 %t3 = lshr i32 %y, %t282 %t4 = and i32 %t1, %t383 %t5 = icmp ne i32 %t4, 084 ret i1 %t585}86 87; Completely variable shift amounts88 89define i1 @t5_const_lshr_shl_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {90; CHECK-LABEL: @t5_const_lshr_shl_ne(91; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]92; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]93; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]94; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 095; CHECK-NEXT: ret i1 [[T3]]96;97 %t0 = lshr i32 %x, %shamt098 %t1 = shl i32 %y, %shamt199 %t2 = and i32 %t1, %t0100 %t3 = icmp ne i32 %t2, 0101 ret i1 %t3102}103define i1 @t6_const_shl_lshr_ne(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {104; CHECK-LABEL: @t6_const_shl_lshr_ne(105; CHECK-NEXT: [[T0:%.*]] = shl i32 [[X:%.*]], [[SHAMT0:%.*]]106; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[Y:%.*]], [[SHAMT1:%.*]]107; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]108; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0109; CHECK-NEXT: ret i1 [[T3]]110;111 %t0 = shl i32 %x, %shamt0112 %t1 = lshr i32 %y, %shamt1113 %t2 = and i32 %t1, %t0114 %t3 = icmp ne i32 %t2, 0115 ret i1 %t3116}117 118; Very basic vector tests119 120define <2 x i1> @t7_const_lshr_shl_ne_vec_splat(<2 x i32> %x, <2 x i32> %y) {121; CHECK-LABEL: @t7_const_lshr_shl_ne_vec_splat(122; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 2)123; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]]124; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer125; CHECK-NEXT: ret <2 x i1> [[T3]]126;127 %t0 = lshr <2 x i32> %x, <i32 1, i32 1>128 %t1 = shl <2 x i32> %y, <i32 1, i32 1>129 %t2 = and <2 x i32> %t1, %t0130 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>131 ret <2 x i1> %t3132}133define <2 x i1> @t8_const_lshr_shl_ne_vec_nonsplat(<2 x i32> %x, <2 x i32> %y) {134; CHECK-LABEL: @t8_const_lshr_shl_ne_vec_nonsplat(135; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 4, i32 6>136; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y:%.*]]137; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer138; CHECK-NEXT: ret <2 x i1> [[T3]]139;140 %t0 = lshr <2 x i32> %x, <i32 1, i32 2>141 %t1 = shl <2 x i32> %y, <i32 3, i32 4>142 %t2 = and <2 x i32> %t1, %t0143 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>144 ret <2 x i1> %t3145}146define <3 x i1> @t9_const_lshr_shl_ne_vec_poison0(<3 x i32> %x, <3 x i32> %y) {147; CHECK-LABEL: @t9_const_lshr_shl_ne_vec_poison0(148; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>149; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]150; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer151; CHECK-NEXT: ret <3 x i1> [[T3]]152;153 %t0 = lshr <3 x i32> %x, <i32 1, i32 poison, i32 1>154 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>155 %t2 = and <3 x i32> %t1, %t0156 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>157 ret <3 x i1> %t3158}159define <3 x i1> @t10_const_lshr_shl_ne_vec_poison1(<3 x i32> %x, <3 x i32> %y) {160; CHECK-LABEL: @t10_const_lshr_shl_ne_vec_poison1(161; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>162; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]163; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer164; CHECK-NEXT: ret <3 x i1> [[T3]]165;166 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>167 %t1 = shl <3 x i32> %y, <i32 1, i32 poison, i32 1>168 %t2 = and <3 x i32> %t1, %t0169 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>170 ret <3 x i1> %t3171}172define <3 x i1> @t11_const_lshr_shl_ne_vec_poison2(<3 x i32> %x, <3 x i32> %y) {173; CHECK-LABEL: @t11_const_lshr_shl_ne_vec_poison2(174; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], splat (i32 2)175; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]176; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer177; CHECK-NEXT: ret <3 x i1> [[T3]]178;179 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>180 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>181 %t2 = and <3 x i32> %t1, %t0182 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 poison, i32 0>183 ret <3 x i1> %t3184}185define <3 x i1> @t12_const_lshr_shl_ne_vec_poison3(<3 x i32> %x, <3 x i32> %y) {186; CHECK-LABEL: @t12_const_lshr_shl_ne_vec_poison3(187; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>188; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]189; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer190; CHECK-NEXT: ret <3 x i1> [[T3]]191;192 %t0 = lshr <3 x i32> %x, <i32 1, i32 poison, i32 1>193 %t1 = shl <3 x i32> %y, <i32 1, i32 poison, i32 1>194 %t2 = and <3 x i32> %t1, %t0195 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 0, i32 0>196 ret <3 x i1> %t3197}198define <3 x i1> @t13_const_lshr_shl_ne_vec_poison4(<3 x i32> %x, <3 x i32> %y) {199; CHECK-LABEL: @t13_const_lshr_shl_ne_vec_poison4(200; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>201; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]202; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer203; CHECK-NEXT: ret <3 x i1> [[T3]]204;205 %t0 = lshr <3 x i32> %x, <i32 1, i32 1, i32 1>206 %t1 = shl <3 x i32> %y, <i32 1, i32 poison, i32 1>207 %t2 = and <3 x i32> %t1, %t0208 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 poison, i32 0>209 ret <3 x i1> %t3210}211define <3 x i1> @t14_const_lshr_shl_ne_vec_poison5(<3 x i32> %x, <3 x i32> %y) {212; CHECK-LABEL: @t14_const_lshr_shl_ne_vec_poison5(213; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>214; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]215; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer216; CHECK-NEXT: ret <3 x i1> [[T3]]217;218 %t0 = lshr <3 x i32> %x, <i32 1, i32 poison, i32 1>219 %t1 = shl <3 x i32> %y, <i32 1, i32 1, i32 1>220 %t2 = and <3 x i32> %t1, %t0221 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 poison, i32 0>222 ret <3 x i1> %t3223}224define <3 x i1> @t15_const_lshr_shl_ne_vec_poison6(<3 x i32> %x, <3 x i32> %y) {225; CHECK-LABEL: @t15_const_lshr_shl_ne_vec_poison6(226; CHECK-NEXT: [[TMP1:%.*]] = lshr <3 x i32> [[X:%.*]], <i32 2, i32 poison, i32 2>227; CHECK-NEXT: [[TMP2:%.*]] = and <3 x i32> [[TMP1]], [[Y:%.*]]228; CHECK-NEXT: [[T3:%.*]] = icmp ne <3 x i32> [[TMP2]], zeroinitializer229; CHECK-NEXT: ret <3 x i1> [[T3]]230;231 %t0 = lshr <3 x i32> %x, <i32 1, i32 poison, i32 1>232 %t1 = shl <3 x i32> %y, <i32 1, i32 poison, i32 1>233 %t2 = and <3 x i32> %t1, %t0234 %t3 = icmp ne <3 x i32> %t2, <i32 0, i32 poison, i32 0>235 ret <3 x i1> %t3236}237 238; Commutativity tests239 240declare i32 @gen32()241 242define i1 @t16_commutativity0(i32 %x) {243; CHECK-LABEL: @t16_commutativity0(244; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()245; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2246; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]247; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0248; CHECK-NEXT: ret i1 [[T3]]249;250 %y = call i32 @gen32()251 %t0 = lshr i32 %x, 1252 %t1 = shl i32 %y, 1253 %t2 = and i32 %t1, %t0254 %t3 = icmp ne i32 %t2, 0255 ret i1 %t3256}257 258define i1 @t17_commutativity1(i32 %y) {259; CHECK-LABEL: @t17_commutativity1(260; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()261; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2262; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]263; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0264; CHECK-NEXT: ret i1 [[T3]]265;266 %x = call i32 @gen32()267 %t0 = lshr i32 %x, 1268 %t1 = shl i32 %y, 1269 %t2 = and i32 %t0, %t1 ; "swapped"270 %t3 = icmp ne i32 %t2, 0271 ret i1 %t3272}273 274; One-use tests275 276declare void @use32(i32)277 278define i1 @t18_const_oneuse0(i32 %x, i32 %y) {279; CHECK-LABEL: @t18_const_oneuse0(280; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1281; CHECK-NEXT: call void @use32(i32 [[T0]])282; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2283; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]284; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0285; CHECK-NEXT: ret i1 [[T3]]286;287 %t0 = lshr i32 %x, 1288 call void @use32(i32 %t0)289 %t1 = shl i32 %y, 1290 %t2 = and i32 %t1, %t0291 %t3 = icmp ne i32 %t2, 0292 ret i1 %t3293}294define i1 @t19_const_oneuse1(i32 %x, i32 %y) {295; CHECK-LABEL: @t19_const_oneuse1(296; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1297; CHECK-NEXT: call void @use32(i32 [[T1]])298; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2299; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]300; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0301; CHECK-NEXT: ret i1 [[T3]]302;303 %t0 = lshr i32 %x, 1304 %t1 = shl i32 %y, 1305 call void @use32(i32 %t1)306 %t2 = and i32 %t1, %t0307 %t3 = icmp ne i32 %t2, 0308 ret i1 %t3309}310define i1 @t20_const_oneuse2(i32 %x, i32 %y) {311; CHECK-LABEL: @t20_const_oneuse2(312; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1313; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1314; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]315; CHECK-NEXT: call void @use32(i32 [[T2]])316; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0317; CHECK-NEXT: ret i1 [[T3]]318;319 %t0 = lshr i32 %x, 1320 %t1 = shl i32 %y, 1321 %t2 = and i32 %t1, %t0322 call void @use32(i32 %t2)323 %t3 = icmp ne i32 %t2, 0324 ret i1 %t3325}326define i1 @t21_const_oneuse3(i32 %x, i32 %y) {327; CHECK-LABEL: @t21_const_oneuse3(328; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1329; CHECK-NEXT: call void @use32(i32 [[T0]])330; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1331; CHECK-NEXT: call void @use32(i32 [[T1]])332; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]333; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0334; CHECK-NEXT: ret i1 [[T3]]335;336 %t0 = lshr i32 %x, 1337 call void @use32(i32 %t0)338 %t1 = shl i32 %y, 1339 call void @use32(i32 %t1)340 %t2 = and i32 %t1, %t0341 %t3 = icmp ne i32 %t2, 0342 ret i1 %t3343}344define i1 @t22_const_oneuse4(i32 %x, i32 %y) {345; CHECK-LABEL: @t22_const_oneuse4(346; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1347; CHECK-NEXT: call void @use32(i32 [[T0]])348; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1349; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]350; CHECK-NEXT: call void @use32(i32 [[T2]])351; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0352; CHECK-NEXT: ret i1 [[T3]]353;354 %t0 = lshr i32 %x, 1355 call void @use32(i32 %t0)356 %t1 = shl i32 %y, 1357 %t2 = and i32 %t1, %t0358 call void @use32(i32 %t2)359 %t3 = icmp ne i32 %t2, 0360 ret i1 %t3361}362define i1 @t23_const_oneuse5(i32 %x, i32 %y) {363; CHECK-LABEL: @t23_const_oneuse5(364; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1365; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1366; CHECK-NEXT: call void @use32(i32 [[T1]])367; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]368; CHECK-NEXT: call void @use32(i32 [[T2]])369; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0370; CHECK-NEXT: ret i1 [[T3]]371;372 %t0 = lshr i32 %x, 1373 %t1 = shl i32 %y, 1374 call void @use32(i32 %t1)375 %t2 = and i32 %t1, %t0376 call void @use32(i32 %t2)377 %t3 = icmp ne i32 %t2, 0378 ret i1 %t3379}380define i1 @t24_const_oneuse6(i32 %x, i32 %y) {381; CHECK-LABEL: @t24_const_oneuse6(382; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1383; CHECK-NEXT: call void @use32(i32 [[T0]])384; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1385; CHECK-NEXT: call void @use32(i32 [[T1]])386; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]387; CHECK-NEXT: call void @use32(i32 [[T2]])388; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0389; CHECK-NEXT: ret i1 [[T3]]390;391 %t0 = lshr i32 %x, 1392 call void @use32(i32 %t0)393 %t1 = shl i32 %y, 1394 call void @use32(i32 %t1)395 %t2 = and i32 %t1, %t0396 call void @use32(i32 %t2)397 %t3 = icmp ne i32 %t2, 0398 ret i1 %t3399}400 401define i1 @t25_var_oneuse0(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {402; CHECK-LABEL: @t25_var_oneuse0(403; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]404; CHECK-NEXT: call void @use32(i32 [[T0]])405; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]406; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]407; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0408; CHECK-NEXT: ret i1 [[T3]]409;410 %t0 = lshr i32 %x, %shamt0411 call void @use32(i32 %t0)412 %t1 = shl i32 %y, %shamt1413 %t2 = and i32 %t1, %t0414 %t3 = icmp ne i32 %t2, 0415 ret i1 %t3416}417define i1 @t26_var_oneuse1(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {418; CHECK-LABEL: @t26_var_oneuse1(419; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]420; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]421; CHECK-NEXT: call void @use32(i32 [[T1]])422; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]423; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0424; CHECK-NEXT: ret i1 [[T3]]425;426 %t0 = lshr i32 %x, %shamt0427 %t1 = shl i32 %y, %shamt1428 call void @use32(i32 %t1)429 %t2 = and i32 %t1, %t0430 %t3 = icmp ne i32 %t2, 0431 ret i1 %t3432}433define i1 @t27_var_oneuse2(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {434; CHECK-LABEL: @t27_var_oneuse2(435; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]436; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]437; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]438; CHECK-NEXT: call void @use32(i32 [[T2]])439; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0440; CHECK-NEXT: ret i1 [[T3]]441;442 %t0 = lshr i32 %x, %shamt0443 %t1 = shl i32 %y, %shamt1444 %t2 = and i32 %t1, %t0445 call void @use32(i32 %t2)446 %t3 = icmp ne i32 %t2, 0447 ret i1 %t3448}449define i1 @t28_var_oneuse3(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {450; CHECK-LABEL: @t28_var_oneuse3(451; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]452; CHECK-NEXT: call void @use32(i32 [[T0]])453; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]454; CHECK-NEXT: call void @use32(i32 [[T1]])455; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]456; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0457; CHECK-NEXT: ret i1 [[T3]]458;459 %t0 = lshr i32 %x, %shamt0460 call void @use32(i32 %t0)461 %t1 = shl i32 %y, %shamt1462 call void @use32(i32 %t1)463 %t2 = and i32 %t1, %t0464 %t3 = icmp ne i32 %t2, 0465 ret i1 %t3466}467define i1 @t29_var_oneuse4(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {468; CHECK-LABEL: @t29_var_oneuse4(469; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]470; CHECK-NEXT: call void @use32(i32 [[T0]])471; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]472; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]473; CHECK-NEXT: call void @use32(i32 [[T2]])474; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0475; CHECK-NEXT: ret i1 [[T3]]476;477 %t0 = lshr i32 %x, %shamt0478 call void @use32(i32 %t0)479 %t1 = shl i32 %y, %shamt1480 %t2 = and i32 %t1, %t0481 call void @use32(i32 %t2)482 %t3 = icmp ne i32 %t2, 0483 ret i1 %t3484}485define i1 @t30_var_oneuse5(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {486; CHECK-LABEL: @t30_var_oneuse5(487; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]488; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]489; CHECK-NEXT: call void @use32(i32 [[T1]])490; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]491; CHECK-NEXT: call void @use32(i32 [[T2]])492; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0493; CHECK-NEXT: ret i1 [[T3]]494;495 %t0 = lshr i32 %x, %shamt0496 %t1 = shl i32 %y, %shamt1497 call void @use32(i32 %t1)498 %t2 = and i32 %t1, %t0499 call void @use32(i32 %t2)500 %t3 = icmp ne i32 %t2, 0501 ret i1 %t3502}503define i1 @t31_var_oneuse6(i32 %x, i32 %y, i32 %shamt0, i32 %shamt1) {504; CHECK-LABEL: @t31_var_oneuse6(505; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]506; CHECK-NEXT: call void @use32(i32 [[T0]])507; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], [[SHAMT1:%.*]]508; CHECK-NEXT: call void @use32(i32 [[T1]])509; CHECK-NEXT: [[T2:%.*]] = and i32 [[T1]], [[T0]]510; CHECK-NEXT: call void @use32(i32 [[T2]])511; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0512; CHECK-NEXT: ret i1 [[T3]]513;514 %t0 = lshr i32 %x, %shamt0515 call void @use32(i32 %t0)516 %t1 = shl i32 %y, %shamt1517 call void @use32(i32 %t1)518 %t2 = and i32 %t1, %t0519 call void @use32(i32 %t2)520 %t3 = icmp ne i32 %t2, 0521 ret i1 %t3522}523 524; Shift-of-const525 526; Ok, non-truncated shift is of constant;527define i1 @t32_shift_of_const_oneuse0(i32 %x, i32 %y, i32 %len) {528; CHECK-LABEL: @t32_shift_of_const_oneuse0(529; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]530; CHECK-NEXT: call void @use32(i32 [[T0]])531; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]]532; CHECK-NEXT: call void @use32(i32 [[T1]])533; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1534; CHECK-NEXT: call void @use32(i32 [[T2]])535; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]]536; CHECK-NEXT: call void @use32(i32 [[T3]])537; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[Y]], 1538; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[TMP1]], 0539; CHECK-NEXT: ret i1 [[T5]]540;541 %t0 = sub i32 32, %len542 call void @use32(i32 %t0)543 %t1 = lshr i32 4242424242, %t0 ; shift-of-constant544 call void @use32(i32 %t1)545 %t2 = add i32 %len, -1546 call void @use32(i32 %t2)547 %t3 = shl i32 %y, %t2548 call void @use32(i32 %t3)549 %t4 = and i32 %t1, %t3 ; no extra uses550 %t5 = icmp ne i32 %t4, 0551 ret i1 %t5552}553; Ok, truncated shift is of constant;554define i1 @t33_shift_of_const_oneuse1(i32 %x, i32 %y, i32 %len) {555; CHECK-LABEL: @t33_shift_of_const_oneuse1(556; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]557; CHECK-NEXT: call void @use32(i32 [[T0]])558; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]559; CHECK-NEXT: call void @use32(i32 [[T1]])560; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1561; CHECK-NEXT: call void @use32(i32 [[T2]])562; CHECK-NEXT: [[T3:%.*]] = shl i32 -52543054, [[T2]]563; CHECK-NEXT: call void @use32(i32 [[T3]])564; CHECK-NEXT: ret i1 false565;566 %t0 = sub i32 32, %len567 call void @use32(i32 %t0)568 %t1 = lshr i32 %x, %t0 ; shift-of-constant569 call void @use32(i32 %t1)570 %t2 = add i32 %len, -1571 call void @use32(i32 %t2)572 %t3 = shl i32 4242424242, %t2573 call void @use32(i32 %t3)574 %t4 = and i32 %t1, %t3 ; no extra uses575 %t5 = icmp ne i32 %t4, 0576 ret i1 %t5577}578 579; Commutativity with extra uses580 581define i1 @t34_commutativity0_oneuse0(i32 %x) {582; CHECK-LABEL: @t34_commutativity0_oneuse0(583; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()584; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], 1585; CHECK-NEXT: call void @use32(i32 [[T0]])586; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2587; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]588; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0589; CHECK-NEXT: ret i1 [[T3]]590;591 %y = call i32 @gen32()592 %t0 = lshr i32 %x, 1593 call void @use32(i32 %t0)594 %t1 = shl i32 %y, 1595 %t2 = and i32 %t1, %t0596 %t3 = icmp ne i32 %t2, 0597 ret i1 %t3598}599define i1 @t35_commutativity0_oneuse1(i32 %x) {600; CHECK-LABEL: @t35_commutativity0_oneuse1(601; CHECK-NEXT: [[Y:%.*]] = call i32 @gen32()602; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y]], 1603; CHECK-NEXT: call void @use32(i32 [[T1]])604; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 2605; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]606; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0607; CHECK-NEXT: ret i1 [[T3]]608;609 %y = call i32 @gen32()610 %t0 = lshr i32 %x, 1611 %t1 = shl i32 %y, 1612 call void @use32(i32 %t1)613 %t2 = and i32 %t1, %t0614 %t3 = icmp ne i32 %t2, 0615 ret i1 %t3616}617 618define i1 @t36_commutativity1_oneuse0(i32 %y) {619; CHECK-LABEL: @t36_commutativity1_oneuse0(620; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()621; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X]], 1622; CHECK-NEXT: call void @use32(i32 [[T0]])623; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2624; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y:%.*]]625; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0626; CHECK-NEXT: ret i1 [[T3]]627;628 %x = call i32 @gen32()629 %t0 = lshr i32 %x, 1630 call void @use32(i32 %t0)631 %t1 = shl i32 %y, 1632 %t2 = and i32 %t0, %t1 ; "swapped"633 %t3 = icmp ne i32 %t2, 0634 ret i1 %t3635}636define i1 @t37_commutativity1_oneuse1(i32 %y) {637; CHECK-LABEL: @t37_commutativity1_oneuse1(638; CHECK-NEXT: [[X:%.*]] = call i32 @gen32()639; CHECK-NEXT: [[T1:%.*]] = shl i32 [[Y:%.*]], 1640; CHECK-NEXT: call void @use32(i32 [[T1]])641; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X]], 2642; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y]]643; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0644; CHECK-NEXT: ret i1 [[T3]]645;646 %x = call i32 @gen32()647 %t0 = lshr i32 %x, 1648 %t1 = shl i32 %y, 1649 call void @use32(i32 %t1)650 %t2 = and i32 %t0, %t1 ; "swapped"651 %t3 = icmp ne i32 %t2, 0652 ret i1 %t3653}654 655; Negative tests656define <2 x i1> @n38_overshift(<2 x i32> %x, <2 x i32> %y) {657; CHECK-LABEL: @n38_overshift(658; CHECK-NEXT: [[T0:%.*]] = lshr <2 x i32> [[X:%.*]], <i32 15, i32 1>659; CHECK-NEXT: [[T1:%.*]] = shl <2 x i32> [[Y:%.*]], <i32 17, i32 1>660; CHECK-NEXT: [[T2:%.*]] = and <2 x i32> [[T1]], [[T0]]661; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[T2]], zeroinitializer662; CHECK-NEXT: ret <2 x i1> [[T3]]663;664 %t0 = lshr <2 x i32> %x, <i32 15, i32 1>665 %t1 = shl <2 x i32> %y, <i32 17, i32 1>666 %t2 = and <2 x i32> %t1, %t0667 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>668 ret <2 x i1> %t3669}670 671; As usual, don't crash given constantexpr's :/672@f.a = internal global i16 0, align 1673define i1 @constantexpr() {674; CHECK-LABEL: @constantexpr(675; CHECK-NEXT: entry:676; CHECK-NEXT: [[TMP0:%.*]] = load i16, ptr @f.a, align 2677; CHECK-NEXT: [[SHR:%.*]] = lshr i16 [[TMP0]], 1678; CHECK-NEXT: [[CMP:%.*]] = icmp ne i16 ptrtoint (ptr @f.a to i16), 1679; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP]] to i16680; CHECK-NEXT: [[TMP1:%.*]] = shl nuw nsw i16 1, [[ZEXT]]681; CHECK-NEXT: [[TMP2:%.*]] = and i16 [[SHR]], [[TMP1]]682; CHECK-NEXT: [[TOBOOL:%.*]] = icmp ne i16 [[TMP2]], 0683; CHECK-NEXT: ret i1 [[TOBOOL]]684;685entry:686 %0 = load i16, ptr @f.a687 %shr = ashr i16 %0, 1688 %cmp = icmp ne i16 ptrtoint (ptr @f.a to i16), 1689 %zext = zext i1 %cmp to i16690 %shr1 = ashr i16 %shr, %zext691 %and = and i16 %shr1, 1692 %tobool = icmp ne i16 %and, 0693 ret i1 %tobool694}695 696; See https://bugs.llvm.org/show_bug.cgi?id=44802697define i1 @pr44802(i3 %a, i3 %x, i3 %y) {698; CHECK-LABEL: @pr44802(699; CHECK-NEXT: [[T0:%.*]] = icmp ne i3 [[A:%.*]], 0700; CHECK-NEXT: [[T1:%.*]] = zext i1 [[T0]] to i3701; CHECK-NEXT: [[T2:%.*]] = lshr i3 [[X:%.*]], [[T1]]702; CHECK-NEXT: [[T3:%.*]] = shl i3 [[Y:%.*]], [[T1]]703; CHECK-NEXT: [[T4:%.*]] = and i3 [[T2]], [[T3]]704; CHECK-NEXT: [[T5:%.*]] = icmp ne i3 [[T4]], 0705; CHECK-NEXT: ret i1 [[T5]]706;707 %t0 = icmp ne i3 %a, 0708 %t1 = zext i1 %t0 to i3709 %t2 = lshr i3 %x, %t1710 %t3 = shl i3 %y, %t1711 %t4 = and i3 %t2, %t3712 %t5 = icmp ne i3 %t4, 0713 ret i1 %t5714}715