393 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes=instcombine | FileCheck %s3 4declare i32 @llvm.cttz.i32(i32, i1)5declare i32 @llvm.ctlz.i32(i32, i1)6declare <2 x i64> @llvm.cttz.v2i64(<2 x i64>, i1)7declare void @use(i32)8 9define i32 @cttz_zext_zero_undef(i16 %x) {10; CHECK-LABEL: @cttz_zext_zero_undef(11; CHECK-NEXT: [[TMP1:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true)12; CHECK-NEXT: [[TZ:%.*]] = zext nneg i16 [[TMP1]] to i3213; CHECK-NEXT: ret i32 [[TZ]]14;15 %z = zext i16 %x to i3216 %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true)17 ret i32 %tz18}19 20define i32 @cttz_zext_zero_def(i16 %x) {21; CHECK-LABEL: @cttz_zext_zero_def(22; CHECK-NEXT: [[Z:%.*]] = zext i16 [[X:%.*]] to i3223; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[Z]], i1 false)24; CHECK-NEXT: ret i32 [[TZ]]25;26 %z = zext i16 %x to i3227 %tz = call i32 @llvm.cttz.i32(i32 %z, i1 false)28 ret i32 %tz29}30 31define i32 @cttz_zext_zero_undef_extra_use(i16 %x) {32; CHECK-LABEL: @cttz_zext_zero_undef_extra_use(33; CHECK-NEXT: [[Z:%.*]] = zext i16 [[X:%.*]] to i3234; CHECK-NEXT: call void @use(i32 [[Z]])35; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[Z]], i1 true)36; CHECK-NEXT: ret i32 [[TZ]]37;38 %z = zext i16 %x to i3239 call void @use(i32 %z)40 %tz = call i32 @llvm.cttz.i32(i32 %z, i1 true)41 ret i32 %tz42}43 44define <2 x i64> @cttz_zext_zero_undef_vec(<2 x i32> %x) {45; CHECK-LABEL: @cttz_zext_zero_undef_vec(46; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true)47; CHECK-NEXT: [[TZ:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>48; CHECK-NEXT: ret <2 x i64> [[TZ]]49;50 %z = zext <2 x i32> %x to <2 x i64>51 %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %z, i1 true)52 ret <2 x i64> %tz53}54 55define <2 x i64> @cttz_zext_zero_def_vec(<2 x i32> %x) {56; CHECK-LABEL: @cttz_zext_zero_def_vec(57; CHECK-NEXT: [[Z:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>58; CHECK-NEXT: [[TZ:%.*]] = tail call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[Z]], i1 false)59; CHECK-NEXT: ret <2 x i64> [[TZ]]60;61 %z = zext <2 x i32> %x to <2 x i64>62 %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %z, i1 false)63 ret <2 x i64> %tz64}65 66define i32 @cttz_sext_zero_undef(i16 %x) {67; CHECK-LABEL: @cttz_sext_zero_undef(68; CHECK-NEXT: [[TMP1:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 true)69; CHECK-NEXT: [[TZ:%.*]] = zext nneg i16 [[TMP1]] to i3270; CHECK-NEXT: ret i32 [[TZ]]71;72 %s = sext i16 %x to i3273 %tz = call i32 @llvm.cttz.i32(i32 %s, i1 true)74 ret i32 %tz75}76 77define i32 @cttz_sext_zero_def(i16 %x) {78; CHECK-LABEL: @cttz_sext_zero_def(79; CHECK-NEXT: [[TMP1:%.*]] = zext i16 [[X:%.*]] to i3280; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[TMP1]], i1 false)81; CHECK-NEXT: ret i32 [[TZ]]82;83 %s = sext i16 %x to i3284 %tz = call i32 @llvm.cttz.i32(i32 %s, i1 false)85 ret i32 %tz86}87 88define i32 @cttz_sext_zero_undef_extra_use(i16 %x) {89; CHECK-LABEL: @cttz_sext_zero_undef_extra_use(90; CHECK-NEXT: [[S:%.*]] = sext i16 [[X:%.*]] to i3291; CHECK-NEXT: call void @use(i32 [[S]])92; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[S]], i1 true)93; CHECK-NEXT: ret i32 [[TZ]]94;95 %s = sext i16 %x to i3296 call void @use(i32 %s)97 %tz = call i32 @llvm.cttz.i32(i32 %s, i1 true)98 ret i32 %tz99}100 101define <2 x i64> @cttz_sext_zero_undef_vec(<2 x i32> %x) {102; CHECK-LABEL: @cttz_sext_zero_undef_vec(103; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true)104; CHECK-NEXT: [[TZ:%.*]] = zext nneg <2 x i32> [[TMP1]] to <2 x i64>105; CHECK-NEXT: ret <2 x i64> [[TZ]]106;107 %s = sext <2 x i32> %x to <2 x i64>108 %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 true)109 ret <2 x i64> %tz110}111 112define <2 x i64> @cttz_sext_zero_def_vec(<2 x i32> %x) {113; CHECK-LABEL: @cttz_sext_zero_def_vec(114; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i32> [[X:%.*]] to <2 x i64>115; CHECK-NEXT: [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[TMP1]], i1 false)116; CHECK-NEXT: ret <2 x i64> [[TZ]]117;118 %s = sext <2 x i32> %x to <2 x i64>119 %tz = tail call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %s, i1 false)120 ret <2 x i64> %tz121}122 123define i32 @cttz_of_lowest_set_bit(i32 %x) {124; CHECK-LABEL: @cttz_of_lowest_set_bit(125; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false)126; CHECK-NEXT: ret i32 [[TZ]]127;128 %sub = sub i32 0, %x129 %and = and i32 %sub, %x130 %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)131 ret i32 %tz132}133 134define i32 @cttz_of_lowest_set_bit_commuted(i32 %xx) {135; CHECK-LABEL: @cttz_of_lowest_set_bit_commuted(136; CHECK-NEXT: [[X:%.*]] = udiv i32 42, [[XX:%.*]]137; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X]], i1 false)138; CHECK-NEXT: ret i32 [[TZ]]139;140 %x = udiv i32 42, %xx ; thwart complexity-based canonicalization141 %sub = sub i32 0, %x142 %and = and i32 %x, %sub143 %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)144 ret i32 %tz145}146 147define i32 @cttz_of_lowest_set_bit_poison_flag(i32 %x) {148; CHECK-LABEL: @cttz_of_lowest_set_bit_poison_flag(149; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true)150; CHECK-NEXT: ret i32 [[TZ]]151;152 %sub = sub i32 0, %x153 %and = and i32 %sub, %x154 %tz = call i32 @llvm.cttz.i32(i32 %and, i1 true)155 ret i32 %tz156}157 158define <2 x i64> @cttz_of_lowest_set_bit_vec(<2 x i64> %x) {159; CHECK-LABEL: @cttz_of_lowest_set_bit_vec(160; CHECK-NEXT: [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false)161; CHECK-NEXT: ret <2 x i64> [[TZ]]162;163 %sub = sub <2 x i64> zeroinitializer, %x164 %and = and <2 x i64> %sub, %x165 %tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)166 ret <2 x i64> %tz167}168 169define <2 x i64> @cttz_of_lowest_set_bit_vec_undef(<2 x i64> %x) {170; CHECK-LABEL: @cttz_of_lowest_set_bit_vec_undef(171; CHECK-NEXT: [[TZ:%.*]] = call range(i64 0, 65) <2 x i64> @llvm.cttz.v2i64(<2 x i64> [[X:%.*]], i1 false)172; CHECK-NEXT: ret <2 x i64> [[TZ]]173;174 %sub = sub <2 x i64> zeroinitializer, %x175 %and = and <2 x i64> %sub, %x176 %tz = call <2 x i64> @llvm.cttz.v2i64(<2 x i64> %and, i1 false)177 ret <2 x i64> %tz178}179 180define i32 @cttz_of_lowest_set_bit_wrong_const(i32 %x) {181; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_const(182; CHECK-NEXT: [[SUB:%.*]] = sub i32 1, [[X:%.*]]183; CHECK-NEXT: [[AND:%.*]] = and i32 [[SUB]], [[X]]184; CHECK-NEXT: [[TZ:%.*]] = call range(i32 1, 33) i32 @llvm.cttz.i32(i32 [[AND]], i1 false)185; CHECK-NEXT: ret i32 [[TZ]]186;187 %sub = sub i32 1, %x188 %and = and i32 %sub, %x189 %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)190 ret i32 %tz191}192 193define i32 @cttz_of_lowest_set_bit_wrong_operand(i32 %x, i32 %y) {194; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_operand(195; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[Y:%.*]]196; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], [[SUB]]197; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[AND]], i1 false)198; CHECK-NEXT: ret i32 [[TZ]]199;200 %sub = sub i32 0, %y201 %and = and i32 %sub, %x202 %tz = call i32 @llvm.cttz.i32(i32 %and, i1 false)203 ret i32 %tz204}205 206define i32 @cttz_of_lowest_set_bit_wrong_intrinsic(i32 %x) {207; CHECK-LABEL: @cttz_of_lowest_set_bit_wrong_intrinsic(208; CHECK-NEXT: [[SUB:%.*]] = sub i32 0, [[X:%.*]]209; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[SUB]]210; CHECK-NEXT: [[TZ:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[AND]], i1 false)211; CHECK-NEXT: ret i32 [[TZ]]212;213 %sub = sub i32 0, %x214 %and = and i32 %sub, %x215 %tz = call i32 @llvm.ctlz.i32(i32 %and, i1 false)216 ret i32 %tz217}218 219define i32 @cttz_of_power_of_two(i32 %x) {220; CHECK-LABEL: @cttz_of_power_of_two(221; CHECK-NEXT: [[R:%.*]] = sub i32 32, [[X:%.*]]222; CHECK-NEXT: ret i32 [[R]]223;224 %lshr = lshr i32 -1, %x225 %add = add i32 %lshr, 1226 %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)227 ret i32 %r228}229 230define i32 @cttz_of_power_of_two_zero_poison(i32 %x) {231; CHECK-LABEL: @cttz_of_power_of_two_zero_poison(232; CHECK-NEXT: [[R:%.*]] = sub i32 32, [[X:%.*]]233; CHECK-NEXT: ret i32 [[R]]234;235 %lshr = lshr i32 -1, %x236 %add = add i32 %lshr, 1237 %r = call i32 @llvm.cttz.i32(i32 %add, i1 true)238 ret i32 %r239}240 241define i32 @cttz_of_power_of_two_wrong_intrinsic(i32 %x) {242; CHECK-LABEL: @cttz_of_power_of_two_wrong_intrinsic(243; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -1, [[X:%.*]]244; CHECK-NEXT: [[ADD:%.*]] = add i32 [[LSHR]], 1245; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[ADD]], i1 false)246; CHECK-NEXT: ret i32 [[R]]247;248 %lshr = lshr i32 -1, %x249 %add = add i32 %lshr, 1250 %r = call i32 @llvm.ctlz.i32(i32 %add, i1 false)251 ret i32 %r252}253 254define i32 @cttz_of_power_of_two_wrong_constant_1(i32 %x) {255; CHECK-LABEL: @cttz_of_power_of_two_wrong_constant_1(256; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -2, [[X:%.*]]257; CHECK-NEXT: [[ADD:%.*]] = add nuw i32 [[LSHR]], 1258; CHECK-NEXT: [[R:%.*]] = call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[ADD]], i1 true)259; CHECK-NEXT: ret i32 [[R]]260;261 %lshr = lshr i32 -2, %x262 %add = add i32 %lshr, 1263 %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)264 ret i32 %r265}266 267define i32 @cttz_of_power_of_two_wrong_constant_2(i32 %x) {268; CHECK-LABEL: @cttz_of_power_of_two_wrong_constant_2(269; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 -1, [[X:%.*]]270; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[LSHR]], -1271; CHECK-NEXT: [[R:%.*]] = call range(i32 1, 33) i32 @llvm.cttz.i32(i32 [[ADD]], i1 false)272; CHECK-NEXT: ret i32 [[R]]273;274 %lshr = lshr i32 -1, %x275 %add = add i32 %lshr, -1276 %r = call i32 @llvm.cttz.i32(i32 %add, i1 false)277 ret i32 %r278}279 280define i16 @cttz_assume(i16 %x) {281; CHECK-LABEL: @cttz_assume(282; CHECK-NEXT: [[ADD:%.*]] = add i16 [[X:%.*]], 1283; CHECK-NEXT: [[COND0:%.*]] = icmp ult i16 [[ADD]], 10284; CHECK-NEXT: call void @llvm.assume(i1 [[COND0]])285; CHECK-NEXT: [[COND1:%.*]] = icmp ne i16 [[X]], 0286; CHECK-NEXT: call void @llvm.assume(i1 [[COND1]])287; CHECK-NEXT: [[CTTZ:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X]], i1 true)288; CHECK-NEXT: ret i16 [[CTTZ]]289;290 %add = add i16 %x, 1291 %cond0 = icmp ult i16 %add, 10292 call void @llvm.assume(i1 %cond0)293 294 %cond1 = icmp ne i16 %x, 0295 call void @llvm.assume(i1 %cond1)296 297 %cttz = call i16 @llvm.cttz.i16(i16 %x, i1 false)298 ret i16 %cttz299}300 301 302declare void @use.i8(i8)303define i8 @fold_ctz_log2(i8 %x) {304; CHECK-LABEL: @fold_ctz_log2(305; CHECK-NEXT: [[R:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)306; CHECK-NEXT: ret i8 [[R]]307;308 %p2 = shl i8 1, %x309 %v = call i8 @llvm.umin(i8 %p2, i8 32)310 %r = call i8 @llvm.cttz(i8 %v, i1 false)311 ret i8 %r312}313 314define i9 @fold_ctz_log2_i9_okay(i9 %x) {315; CHECK-LABEL: @fold_ctz_log2_i9_okay(316; CHECK-NEXT: [[R:%.*]] = call i9 @llvm.umin.i9(i9 [[X:%.*]], i9 5)317; CHECK-NEXT: ret i9 [[R]]318;319 %p2 = shl i9 1, %x320 %v = call i9 @llvm.umin(i9 %p2, i9 32)321 %r = call i9 @llvm.cttz(i9 %v, i1 false)322 ret i9 %r323}324 325define i8 @fold_ctz_log2_maybe_z(i8 %x, i8 %y, i1 %c) {326; CHECK-LABEL: @fold_ctz_log2_maybe_z(327; CHECK-NEXT: [[V:%.*]] = shl i8 2, [[V_V:%.*]]328; CHECK-NEXT: [[P2_2:%.*]] = shl i8 4, [[Y:%.*]]329; CHECK-NEXT: [[V1:%.*]] = select i1 [[C:%.*]], i8 [[V]], i8 [[P2_2]]330; CHECK-NEXT: [[R:%.*]] = call range(i8 1, 9) i8 @llvm.cttz.i8(i8 [[V1]], i1 false)331; CHECK-NEXT: ret i8 [[R]]332;333 %p2 = shl i8 2, %x334 %p2_2 = shl i8 4, %y335 %v = select i1 %c, i8 %p2, i8 %p2_2336 %r = call i8 @llvm.cttz(i8 %v, i1 false)337 ret i8 %r338}339 340define i8 @fold_ctz_log2_maybe_z_okay(i8 %x, i8 %y, i1 %c) {341; CHECK-LABEL: @fold_ctz_log2_maybe_z_okay(342; CHECK-NEXT: [[X:%.*]] = add i8 [[X1:%.*]], 1343; CHECK-NEXT: [[Y:%.*]] = add i8 [[Y1:%.*]], 2344; CHECK-NEXT: [[V_V:%.*]] = select i1 [[C:%.*]], i8 [[X]], i8 [[Y]]345; CHECK-NEXT: ret i8 [[V_V]]346;347 %p2 = shl i8 2, %x348 %p2_2 = shl i8 4, %y349 %v = select i1 %c, i8 %p2, i8 %p2_2350 %r = call i8 @llvm.cttz(i8 %v, i1 true)351 ret i8 %r352}353 354define i8 @fold_clz_log2(i8 %x) {355; CHECK-LABEL: @fold_clz_log2(356; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[X:%.*]], i8 5)357; CHECK-NEXT: [[R:%.*]] = xor i8 [[TMP1]], 7358; CHECK-NEXT: ret i8 [[R]]359;360 %p2 = shl i8 1, %x361 %v = call i8 @llvm.umin(i8 %p2, i8 32)362 %r = call i8 @llvm.ctlz(i8 %v, i1 false)363 ret i8 %r364}365 366define i8 @fold_clz_log2_multiuse_fail(i8 %x) {367; CHECK-LABEL: @fold_clz_log2_multiuse_fail(368; CHECK-NEXT: [[P2:%.*]] = shl nuw i8 2, [[X:%.*]]369; CHECK-NEXT: [[V:%.*]] = call i8 @llvm.umin.i8(i8 [[P2]], i8 32)370; CHECK-NEXT: call void @use.i8(i8 [[V]])371; CHECK-NEXT: [[R:%.*]] = call range(i8 2, 9) i8 @llvm.ctlz.i8(i8 [[V]], i1 true)372; CHECK-NEXT: ret i8 [[R]]373;374 %p2 = shl nuw i8 2, %x375 %v = call i8 @llvm.umin(i8 %p2, i8 32)376 call void @use.i8(i8 %v)377 %r = call i8 @llvm.ctlz(i8 %v, i1 true)378 ret i8 %r379}380 381 382define i9 @fold_clz_log2_i9(i9 %x) {383; CHECK-LABEL: @fold_clz_log2_i9(384; CHECK-NEXT: [[TMP1:%.*]] = call i9 @llvm.umin.i9(i9 [[X:%.*]], i9 5)385; CHECK-NEXT: [[R:%.*]] = sub nuw nsw i9 8, [[TMP1]]386; CHECK-NEXT: ret i9 [[R]]387;388 %p2 = shl i9 1, %x389 %v = call i9 @llvm.umin(i9 %p2, i9 32)390 %r = call i9 @llvm.ctlz(i9 %v, i1 true)391 ret i9 %r392}393