462 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; We still can handle the case where there is a truncation between a shift and10; an 'and'. If it's trunc-of-shl - no extra legality check is needed.11 12;-------------------------------------------------------------------------------13; Basic scalar tests14;-------------------------------------------------------------------------------15 16define i1 @t0_const_after_fold_lshr_shl_ne(i32 %x, i64 %y, i32 %len) {17; CHECK-LABEL: @t0_const_after_fold_lshr_shl_ne(18; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 3119; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i32 [[TMP1]] to i6420; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[Y:%.*]], [[TMP2]]21; CHECK-NEXT: [[T5:%.*]] = icmp ne i64 [[TMP3]], 022; CHECK-NEXT: ret i1 [[T5]]23;24 %t0 = sub i32 32, %len25 %t1 = lshr i32 %x, %t026 %t2 = add i32 %len, -127 %t2_wide = zext i32 %t2 to i6428 %t3 = shl i64 %y, %t2_wide29 %t3_trunc = trunc i64 %t3 to i3230 %t4 = and i32 %t1, %t3_trunc31 %t5 = icmp ne i32 %t4, 032 ret i1 %t533}34 35;-------------------------------------------------------------------------------36; Very basic vector tests37;-------------------------------------------------------------------------------38 39define <2 x i1> @t1_vec_splat(<2 x i32> %x, <2 x i64> %y, <2 x i32> %len) {40; CHECK-LABEL: @t1_vec_splat(41; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 31)42; CHECK-NEXT: [[TMP2:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>43; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i64> [[Y:%.*]], [[TMP2]]44; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i64> [[TMP3]], zeroinitializer45; CHECK-NEXT: ret <2 x i1> [[T5]]46;47 %t0 = sub <2 x i32> <i32 32, i32 32>, %len48 %t1 = lshr <2 x i32> %x, %t049 %t2 = add <2 x i32> %len, <i32 -1, i32 -1>50 %t2_wide = zext <2 x i32> %t2 to <2 x i64>51 %t3 = shl <2 x i64> %y, %t2_wide52 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>53 %t4 = and <2 x i32> %t1, %t3_trunc54 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>55 ret <2 x i1> %t556}57 58define <2 x i1> @t2_vec_nonsplat(<2 x i32> %x, <2 x i64> %y, <2 x i32> %len) {59; CHECK-LABEL: @t2_vec_nonsplat(60; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>61; CHECK-NEXT: [[TMP2:%.*]] = lshr <2 x i64> [[TMP1]], <i64 31, i64 30>62; CHECK-NEXT: [[TMP3:%.*]] = and <2 x i64> [[TMP2]], [[Y:%.*]]63; CHECK-NEXT: [[T5:%.*]] = icmp ne <2 x i64> [[TMP3]], zeroinitializer64; CHECK-NEXT: ret <2 x i1> [[T5]]65;66 %t0 = sub <2 x i32> <i32 30, i32 32>, %len67 %t1 = lshr <2 x i32> %x, %t068 %t2 = add <2 x i32> %len, <i32 1, i32 -2>69 %t2_wide = zext <2 x i32> %t2 to <2 x i64>70 %t3 = shl <2 x i64> %y, %t2_wide71 %t3_trunc = trunc <2 x i64> %t3 to <2 x i32>72 %t4 = and <2 x i32> %t1, %t3_trunc73 %t5 = icmp ne <2 x i32> %t4, <i32 0, i32 0>74 ret <2 x i1> %t575}76 77;-------------------------------------------------------------------------------78; Commutativity tests79;-------------------------------------------------------------------------------80 81declare i32 @gen32()82declare i64 @gen64()83 84; While 'and' is commutative, the 'trunc' *always* seems to be getting85; canonicalized to the RHS, it does not seem possible to prevent that.86 87;-------------------------------------------------------------------------------88; One-use tests89;-------------------------------------------------------------------------------90 91declare void @use32(i32)92declare void @use64(i64)93 94; Nope, everything has extra uses.95define i1 @t3_oneuse0(i32 %x, i64 %y, i32 %len) {96; CHECK-LABEL: @t3_oneuse0(97; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]98; CHECK-NEXT: call void @use32(i32 [[T0]])99; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]100; CHECK-NEXT: call void @use32(i32 [[T1]])101; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1102; CHECK-NEXT: call void @use32(i32 [[T2]])103; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64104; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])105; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]106; CHECK-NEXT: call void @use64(i64 [[T3]])107; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32108; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])109; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]110; CHECK-NEXT: call void @use32(i32 [[T4]])111; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0112; CHECK-NEXT: ret i1 [[T5]]113;114 %t0 = sub i32 32, %len115 call void @use32(i32 %t0)116 %t1 = lshr i32 %x, %t0117 call void @use32(i32 %t1)118 %t2 = add i32 %len, -1119 call void @use32(i32 %t2)120 %t2_wide = zext i32 %t2 to i64121 call void @use64(i64 %t2_wide)122 %t3 = shl i64 %y, %t2_wide123 call void @use64(i64 %t3)124 %t3_trunc = trunc i64 %t3 to i32125 call void @use32(i32 %t3_trunc)126 %t4 = and i32 %t1, %t3_trunc127 call void @use32(i32 %t4)128 %t5 = icmp ne i32 %t4, 0129 ret i1 %t5130}131 132; Nope, still too much extra uses.133define i1 @t4_oneuse1(i32 %x, i64 %y, i32 %len) {134; CHECK-LABEL: @t4_oneuse1(135; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]136; CHECK-NEXT: call void @use32(i32 [[T0]])137; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]138; CHECK-NEXT: call void @use32(i32 [[T1]])139; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1140; CHECK-NEXT: call void @use32(i32 [[T2]])141; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64142; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])143; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]144; CHECK-NEXT: call void @use64(i64 [[T3]])145; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32146; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])147; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]148; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0149; CHECK-NEXT: ret i1 [[T5]]150;151 %t0 = sub i32 32, %len152 call void @use32(i32 %t0)153 %t1 = lshr i32 %x, %t0154 call void @use32(i32 %t1)155 %t2 = add i32 %len, -1156 call void @use32(i32 %t2)157 %t2_wide = zext i32 %t2 to i64158 call void @use64(i64 %t2_wide)159 %t3 = shl i64 %y, %t2_wide160 call void @use64(i64 %t3)161 %t3_trunc = trunc i64 %t3 to i32162 call void @use32(i32 %t3_trunc)163 %t4 = and i32 %t1, %t3_trunc ; no extra uses164 %t5 = icmp ne i32 %t4, 0165 ret i1 %t5166}167 168; Still too much extra uses.169define i1 @t5_oneuse2(i32 %x, i64 %y, i32 %len) {170; CHECK-LABEL: @t5_oneuse2(171; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]172; CHECK-NEXT: call void @use32(i32 [[T0]])173; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]174; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1175; CHECK-NEXT: call void @use32(i32 [[T2]])176; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64177; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])178; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]179; CHECK-NEXT: call void @use64(i64 [[T3]])180; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32181; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])182; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]183; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0184; CHECK-NEXT: ret i1 [[T5]]185;186 %t0 = sub i32 32, %len187 call void @use32(i32 %t0)188 %t1 = lshr i32 %x, %t0 ; no extra uses189 %t2 = add i32 %len, -1190 call void @use32(i32 %t2)191 %t2_wide = zext i32 %t2 to i64192 call void @use64(i64 %t2_wide)193 %t3 = shl i64 %y, %t2_wide194 call void @use64(i64 %t3)195 %t3_trunc = trunc i64 %t3 to i32196 call void @use32(i32 %t3_trunc)197 %t4 = and i32 %t1, %t3_trunc ; no extra uses198 %t5 = icmp ne i32 %t4, 0199 ret i1 %t5200}201 202; Ok, trunc has no extra uses.203define i1 @t6_oneuse3(i32 %x, i64 %y, i32 %len) {204; CHECK-LABEL: @t6_oneuse3(205; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]206; CHECK-NEXT: call void @use32(i32 [[T0]])207; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1208; CHECK-NEXT: call void @use32(i32 [[T2]])209; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64210; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])211; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]212; CHECK-NEXT: call void @use64(i64 [[T3]])213; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31214; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i32 [[TMP1]] to i64215; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[Y]], [[TMP2]]216; CHECK-NEXT: [[T5:%.*]] = icmp ne i64 [[TMP3]], 0217; CHECK-NEXT: ret i1 [[T5]]218;219 %t0 = sub i32 32, %len220 call void @use32(i32 %t0)221 %t1 = lshr i32 %x, %t0 ; no extra uses222 %t2 = add i32 %len, -1223 call void @use32(i32 %t2)224 %t2_wide = zext i32 %t2 to i64225 call void @use64(i64 %t2_wide)226 %t3 = shl i64 %y, %t2_wide227 call void @use64(i64 %t3)228 %t3_trunc = trunc i64 %t3 to i32 ; no extra uses229 %t4 = and i32 %t1, %t3_trunc ; no extra uses230 %t5 = icmp ne i32 %t4, 0231 ret i1 %t5232}233 234; Ok, shift amount of non-truncated shift has no extra uses;235define i1 @t7_oneuse4(i32 %x, i64 %y, i32 %len) {236; CHECK-LABEL: @t7_oneuse4(237; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN:%.*]], -1238; CHECK-NEXT: call void @use32(i32 [[T2]])239; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64240; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])241; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]242; CHECK-NEXT: call void @use64(i64 [[T3]])243; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32244; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])245; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 31246; CHECK-NEXT: [[TMP2:%.*]] = zext nneg i32 [[TMP1]] to i64247; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[Y]], [[TMP2]]248; CHECK-NEXT: [[T5:%.*]] = icmp ne i64 [[TMP3]], 0249; CHECK-NEXT: ret i1 [[T5]]250;251 %t0 = sub i32 32, %len ; no extra uses252 %t1 = lshr i32 %x, %t0 ; no extra uses253 %t2 = add i32 %len, -1254 call void @use32(i32 %t2)255 %t2_wide = zext i32 %t2 to i64256 call void @use64(i64 %t2_wide)257 %t3 = shl i64 %y, %t2_wide258 call void @use64(i64 %t3)259 %t3_trunc = trunc i64 %t3 to i32260 call void @use32(i32 %t3_trunc)261 %t4 = and i32 %t1, %t3_trunc ; no extra uses262 %t5 = icmp ne i32 %t4, 0263 ret i1 %t5264}265 266; Ok, non-truncated shift is of constant;267define i1 @t8_oneuse5(i32 %x, i64 %y, i32 %len) {268; CHECK-LABEL: @t8_oneuse5(269; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]270; CHECK-NEXT: call void @use32(i32 [[T0]])271; CHECK-NEXT: [[T1:%.*]] = lshr i32 -52543054, [[T0]]272; CHECK-NEXT: call void @use32(i32 [[T1]])273; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1274; CHECK-NEXT: call void @use32(i32 [[T2]])275; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64276; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])277; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]278; CHECK-NEXT: call void @use64(i64 [[T3]])279; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32280; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])281; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[Y]], 1282; CHECK-NEXT: [[T5:%.*]] = icmp ne i64 [[TMP1]], 0283; CHECK-NEXT: ret i1 [[T5]]284;285 %t0 = sub i32 32, %len286 call void @use32(i32 %t0)287 %t1 = lshr i32 4242424242, %t0 ; shift-of-constant288 call void @use32(i32 %t1)289 %t2 = add i32 %len, -1290 call void @use32(i32 %t2)291 %t2_wide = zext i32 %t2 to i64292 call void @use64(i64 %t2_wide)293 %t3 = shl i64 %y, %t2_wide294 call void @use64(i64 %t3)295 %t3_trunc = trunc i64 %t3 to i32296 call void @use32(i32 %t3_trunc)297 %t4 = and i32 %t1, %t3_trunc ; no extra uses298 %t5 = icmp ne i32 %t4, 0299 ret i1 %t5300}301 302; Ok, truncated shift is of constant;303define i1 @t9_oneuse5(i32 %x, i64 %y, i32 %len) {304; CHECK-LABEL: @t9_oneuse5(305; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]306; CHECK-NEXT: call void @use32(i32 [[T0]])307; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]308; CHECK-NEXT: call void @use32(i32 [[T1]])309; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1310; CHECK-NEXT: call void @use32(i32 [[T2]])311; CHECK-NEXT: [[T2_WIDE:%.*]] = zext i32 [[T2]] to i64312; CHECK-NEXT: call void @use64(i64 [[T2_WIDE]])313; CHECK-NEXT: [[T3:%.*]] = shl i64 4242424242, [[T2_WIDE]]314; CHECK-NEXT: call void @use64(i64 [[T3]])315; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32316; CHECK-NEXT: call void @use32(i32 [[T3_TRUNC]])317; CHECK-NEXT: ret i1 false318;319 %t0 = sub i32 32, %len320 call void @use32(i32 %t0)321 %t1 = lshr i32 %x, %t0 ; shift-of-constant322 call void @use32(i32 %t1)323 %t2 = add i32 %len, -1324 call void @use32(i32 %t2)325 %t2_wide = zext i32 %t2 to i64326 call void @use64(i64 %t2_wide)327 %t3 = shl i64 4242424242, %t2_wide328 call void @use64(i64 %t3)329 %t3_trunc = trunc i64 %t3 to i32330 call void @use32(i32 %t3_trunc)331 %t4 = and i32 %t1, %t3_trunc ; no extra uses332 %t5 = icmp ne i32 %t4, 0333 ret i1 %t5334}335 336;-------------------------------------------------------------------------------337; Commutativity with extra uses338;-------------------------------------------------------------------------------339 340; While 'and' is commutative, the 'trunc' *always* seems to be getting341; canonicalized to the RHS, it does not seem possible to prevent that.342 343;344 345; Constant shift amounts346 347define i1 @t10_constants(i32 %x, i64 %y) {348; CHECK-LABEL: @t10_constants(349; CHECK-NEXT: [[Y_TR:%.*]] = trunc i64 [[Y:%.*]] to i32350; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 26351; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], [[Y_TR]]352; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[TMP2]], 0353; CHECK-NEXT: ret i1 [[T3]]354;355 %t0 = lshr i32 %x, 12356 %t1 = shl i64 %y, 14357 %t1_trunc = trunc i64 %t1 to i32358 %t2 = and i32 %t0, %t1_trunc359 %t3 = icmp ne i32 %t2, 0360 ret i1 %t3361}362 363define <2 x i1> @t11_constants_vec_splat(<2 x i32> %x, <2 x i64> %y) {364; CHECK-LABEL: @t11_constants_vec_splat(365; CHECK-NEXT: [[Y_TR:%.*]] = trunc <2 x i64> [[Y:%.*]] to <2 x i32>366; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 26)367; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y_TR]]368; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer369; CHECK-NEXT: ret <2 x i1> [[T3]]370;371 %t0 = lshr <2 x i32> %x, <i32 12, i32 12>372 %t1 = shl <2 x i64> %y, <i64 14, i64 14>373 %t1_trunc = trunc <2 x i64> %t1 to <2 x i32>374 %t2 = and <2 x i32> %t0, %t1_trunc375 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>376 ret <2 x i1> %t3377}378define <2 x i1> @t12_constants_vec_nonsplat(<2 x i32> %x, <2 x i64> %y) {379; CHECK-LABEL: @t12_constants_vec_nonsplat(380; CHECK-NEXT: [[Y_TR:%.*]] = trunc <2 x i64> [[Y:%.*]] to <2 x i32>381; CHECK-NEXT: [[TMP1:%.*]] = lshr <2 x i32> [[X:%.*]], splat (i32 28)382; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i32> [[TMP1]], [[Y_TR]]383; CHECK-NEXT: [[T3:%.*]] = icmp ne <2 x i32> [[TMP2]], zeroinitializer384; CHECK-NEXT: ret <2 x i1> [[T3]]385;386 %t0 = lshr <2 x i32> %x, <i32 12, i32 14>387 %t1 = shl <2 x i64> %y, <i64 16, i64 14>388 %t1_trunc = trunc <2 x i64> %t1 to <2 x i32>389 %t2 = and <2 x i32> %t0, %t1_trunc390 %t3 = icmp ne <2 x i32> %t2, <i32 0, i32 0>391 ret <2 x i1> %t3392}393 394;-------------------------------------------------------------------------------395; Negative tests396;-------------------------------------------------------------------------------397 398define i1 @n13_overshift(i32 %x, i64 %y, i32 %len) {399; CHECK-LABEL: @n13_overshift(400; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]401; CHECK-NEXT: [[T1:%.*]] = lshr i32 [[X:%.*]], [[T0]]402; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], 32403; CHECK-NEXT: [[T2_WIDE:%.*]] = zext nneg i32 [[T2]] to i64404; CHECK-NEXT: [[T3:%.*]] = shl i64 [[Y:%.*]], [[T2_WIDE]]405; CHECK-NEXT: [[T3_TRUNC:%.*]] = trunc i64 [[T3]] to i32406; CHECK-NEXT: [[T4:%.*]] = and i32 [[T1]], [[T3_TRUNC]]407; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0408; CHECK-NEXT: ret i1 [[T5]]409;410 %t0 = sub i32 32, %len411 %t1 = lshr i32 %x, %t0412 %t2 = add i32 %len, 32 ; too much413 %t2_wide = zext i32 %t2 to i64414 %t3 = shl i64 %y, %t2_wide415 %t3_trunc = trunc i64 %t3 to i32416 %t4 = and i32 %t1, %t3_trunc417 %t5 = icmp ne i32 %t4, 0418 ret i1 %t5419}420 421define i1 @n14_trunc_of_lshr(i64 %x, i32 %y, i32 %len) {422; CHECK-LABEL: @n14_trunc_of_lshr(423; CHECK-NEXT: [[T0:%.*]] = sub i32 32, [[LEN:%.*]]424; CHECK-NEXT: [[T0_WIDE:%.*]] = zext nneg i32 [[T0]] to i64425; CHECK-NEXT: [[T1:%.*]] = lshr i64 [[X:%.*]], [[T0_WIDE]]426; CHECK-NEXT: [[T1_TRUNC:%.*]] = trunc i64 [[T1]] to i32427; CHECK-NEXT: [[T2:%.*]] = add i32 [[LEN]], -1428; CHECK-NEXT: [[T3:%.*]] = shl i32 [[Y:%.*]], [[T2]]429; CHECK-NEXT: [[T4:%.*]] = and i32 [[T3]], [[T1_TRUNC]]430; CHECK-NEXT: [[T5:%.*]] = icmp ne i32 [[T4]], 0431; CHECK-NEXT: ret i1 [[T5]]432;433 %t0 = sub i32 32, %len434 %t0_wide = zext i32 %t0 to i64435 %t1 = lshr i64 %x, %t0_wide436 %t1_trunc = trunc i64 %t1 to i32437 %t2 = add i32 %len, -1438 %t3 = shl i32 %y, %t2439 %t4 = and i32 %t1_trunc, %t3440 %t5 = icmp ne i32 %t4, 0441 ret i1 %t5442}443 444; Completely variable shift amounts445 446define i1 @n15_variable_shamts(i32 %x, i64 %y, i32 %shamt0, i64 %shamt1) {447; CHECK-LABEL: @n15_variable_shamts(448; CHECK-NEXT: [[T0:%.*]] = lshr i32 [[X:%.*]], [[SHAMT0:%.*]]449; CHECK-NEXT: [[T1:%.*]] = shl i64 [[Y:%.*]], [[SHAMT1:%.*]]450; CHECK-NEXT: [[T1_TRUNC:%.*]] = trunc i64 [[T1]] to i32451; CHECK-NEXT: [[T2:%.*]] = and i32 [[T0]], [[T1_TRUNC]]452; CHECK-NEXT: [[T3:%.*]] = icmp ne i32 [[T2]], 0453; CHECK-NEXT: ret i1 [[T3]]454;455 %t0 = lshr i32 %x, %shamt0456 %t1 = shl i64 %y, %shamt1457 %t1_trunc = trunc i64 %t1 to i32458 %t2 = and i32 %t1_trunc, %t0459 %t3 = icmp ne i32 %t2, 0460 ret i1 %t3461}462