1575 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4define i1 @is_pow2or0_negate_op(i32 %x) {5; CHECK-LABEL: @is_pow2or0_negate_op(6; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])7; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[TMP1]], 28; CHECK-NEXT: ret i1 [[CMP]]9;10 %neg = sub i32 0, %x11 %and = and i32 %neg, %x12 %cmp = icmp eq i32 %and, %x13 ret i1 %cmp14}15 16define <2 x i1> @is_pow2or0_negate_op_vec(<2 x i32> %x) {17; CHECK-LABEL: @is_pow2or0_negate_op_vec(18; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])19; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult <2 x i32> [[TMP1]], splat (i32 2)20; CHECK-NEXT: ret <2 x i1> [[CMP]]21;22 %neg = sub <2 x i32> zeroinitializer, %x23 %and = and <2 x i32> %neg, %x24 %cmp = icmp eq <2 x i32> %and, %x25 ret <2 x i1> %cmp26}27 28define i1 @is_pow2or0_decrement_op(i8 %x) {29; CHECK-LABEL: @is_pow2or0_decrement_op(30; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])31; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i8 [[TMP1]], 232; CHECK-NEXT: ret i1 [[CMP]]33;34 %dec = add i8 %x, -135 %and = and i8 %dec, %x36 %cmp = icmp eq i8 %and, 037 ret i1 %cmp38}39 40define <2 x i1> @is_pow2or0_decrement_op_vec(<2 x i8> %x) {41; CHECK-LABEL: @is_pow2or0_decrement_op_vec(42; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])43; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult <2 x i8> [[TMP1]], splat (i8 2)44; CHECK-NEXT: ret <2 x i1> [[CMP]]45;46 %dec = add <2 x i8> %x, <i8 -1, i8 -1>47 %and = and <2 x i8> %dec, %x48 %cmp = icmp eq <2 x i8> %and, zeroinitializer49 ret <2 x i1> %cmp50}51 52define i1 @isnot_pow2or0_negate_op(i32 %x) {53; CHECK-LABEL: @isnot_pow2or0_negate_op(54; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])55; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[TMP1]], 156; CHECK-NEXT: ret i1 [[CMP]]57;58 %neg = sub i32 0, %x59 %and = and i32 %neg, %x60 %cmp = icmp ne i32 %and, %x61 ret i1 %cmp62}63 64define <2 x i1> @isnot_pow2or0_negate_op_vec(<2 x i32> %x) {65; CHECK-LABEL: @isnot_pow2or0_negate_op_vec(66; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])67; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt <2 x i32> [[TMP1]], splat (i32 1)68; CHECK-NEXT: ret <2 x i1> [[CMP]]69;70 %neg = sub <2 x i32> zeroinitializer, %x71 %and = and <2 x i32> %neg, %x72 %cmp = icmp ne <2 x i32> %and, %x73 ret <2 x i1> %cmp74}75 76define i1 @isnot_pow2or0_decrement_op(i8 %x) {77; CHECK-LABEL: @isnot_pow2or0_decrement_op(78; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])79; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i8 [[TMP1]], 180; CHECK-NEXT: ret i1 [[CMP]]81;82 %dec = add i8 %x, -183 %and = and i8 %dec, %x84 %cmp = icmp ne i8 %and, 085 ret i1 %cmp86}87 88define <2 x i1> @isnot_pow2or0_decrement_op_vec(<2 x i8> %x) {89; CHECK-LABEL: @isnot_pow2or0_decrement_op_vec(90; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])91; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt <2 x i8> [[TMP1]], splat (i8 1)92; CHECK-NEXT: ret <2 x i1> [[CMP]]93;94 %dec = add <2 x i8> %x, <i8 -1, i8 -1>95 %and = and <2 x i8> %dec, %x96 %cmp = icmp ne <2 x i8> %and, zeroinitializer97 ret <2 x i1> %cmp98}99 100define i1 @is_pow2or0_negate_op_commute1(i32 %p) {101; CHECK-LABEL: @is_pow2or0_negate_op_commute1(102; CHECK-NEXT: [[X:%.*]] = srem i32 42, [[P:%.*]]103; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 7) i32 @llvm.ctpop.i32(i32 [[X]])104; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[TMP1]], 2105; CHECK-NEXT: ret i1 [[CMP]]106;107 %x = srem i32 42, %p ; thwart complexity-based canonicalization108 %neg = sub i32 0, %x109 %and = and i32 %x, %neg110 %cmp = icmp eq i32 %and, %x111 ret i1 %cmp112}113 114; x can't be <= complexity of the 'neg' but >= complexity of the 'and'.115 116define i1 @isnot_pow2or0_negate_op_commute2(i32 %p) {117; CHECK-LABEL: @isnot_pow2or0_negate_op_commute2(118; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[P:%.*]]119; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 7) i32 @llvm.ctpop.i32(i32 [[X]])120; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[TMP1]], 1121; CHECK-NEXT: ret i1 [[CMP]]122;123 %x = urem i32 42, %p ; thwart complexity-based canonicalization124 %neg = sub i32 0, %x125 %and = and i32 %neg, %x126 %cmp = icmp ne i32 %x, %and127 ret i1 %cmp128}129 130define i1 @isnot_pow2or0_negate_op_commute3(i32 %p) {131; CHECK-LABEL: @isnot_pow2or0_negate_op_commute3(132; CHECK-NEXT: [[X:%.*]] = urem i32 42, [[P:%.*]]133; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 7) i32 @llvm.ctpop.i32(i32 [[X]])134; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[TMP1]], 1135; CHECK-NEXT: ret i1 [[CMP]]136;137 %x = urem i32 42, %p ; thwart complexity-based canonicalization138 %neg = sub i32 0, %x139 %and = and i32 %x, %neg140 %cmp = icmp ne i32 %x, %and141 ret i1 %cmp142}143 144declare void @use(i32)145 146define i1 @is_pow2or0_negate_op_extra_use1(i32 %x) {147; CHECK-LABEL: @is_pow2or0_negate_op_extra_use1(148; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]149; CHECK-NEXT: call void @use(i32 [[NEG]])150; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])151; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[TMP1]], 2152; CHECK-NEXT: ret i1 [[CMP]]153;154 %neg = sub i32 0, %x155 call void @use(i32 %neg)156 %and = and i32 %neg, %x157 %cmp = icmp eq i32 %and, %x158 ret i1 %cmp159}160 161define i1 @is_pow2or0_negate_op_extra_use2(i32 %x) {162; CHECK-LABEL: @is_pow2or0_negate_op_extra_use2(163; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]164; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], [[NEG]]165; CHECK-NEXT: call void @use(i32 [[AND]])166; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[AND]], [[X]]167; CHECK-NEXT: ret i1 [[CMP]]168;169 %neg = sub i32 0, %x170 %and = and i32 %neg, %x171 call void @use(i32 %and)172 %cmp = icmp eq i32 %and, %x173 ret i1 %cmp174}175 176declare i32 @llvm.ctpop.i32(i32)177declare <2 x i8> @llvm.ctpop.v2i8(<2 x i8>)178declare void @llvm.assume(i1)179 180; (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1181 182define i1 @is_pow2_ctpop(i32 %x) {183; CHECK-LABEL: @is_pow2_ctpop(184; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])185; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1186; CHECK-NEXT: ret i1 [[R]]187;188 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)189 %cmp = icmp ult i32 %t0, 2190 %notzero = icmp ne i32 %x, 0191 %r = and i1 %notzero, %cmp192 ret i1 %r193}194 195; tests from PR57328196define i1 @is_pow2_non_zero_ult_2(i32 %x) {197; CHECK-LABEL: @is_pow2_non_zero_ult_2(198; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0199; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])200; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])201; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2202; CHECK-NEXT: ret i1 [[CMP]]203;204 %notzero = icmp ne i32 %x, 0205 call void @llvm.assume(i1 %notzero)206 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)207 %cmp = icmp ult i32 %t0, 2208 ret i1 %cmp209}210 211define i1 @is_pow2_non_zero_eq_1(i32 %x) {212; CHECK-LABEL: @is_pow2_non_zero_eq_1(213; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0214; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])215; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])216; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1217; CHECK-NEXT: ret i1 [[CMP]]218;219 %notzero = icmp ne i32 %x, 0220 call void @llvm.assume(i1 %notzero)221 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)222 %cmp = icmp eq i32 %t0, 1223 ret i1 %cmp224}225 226define i1 @is_pow2_non_zero_ugt_1(i32 %x) {227; CHECK-LABEL: @is_pow2_non_zero_ugt_1(228; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0229; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])230; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])231; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1232; CHECK-NEXT: ret i1 [[CMP]]233;234 %notzero = icmp ne i32 %x, 0235 call void @llvm.assume(i1 %notzero)236 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)237 %cmp = icmp ugt i32 %t0, 1238 ret i1 %cmp239}240 241define i1 @is_pow2_non_zero_ne_1(i32 %x) {242; CHECK-LABEL: @is_pow2_non_zero_ne_1(243; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X:%.*]], 0244; CHECK-NEXT: call void @llvm.assume(i1 [[NOTZERO]])245; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])246; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1247; CHECK-NEXT: ret i1 [[CMP]]248;249 %notzero = icmp ne i32 %x, 0250 call void @llvm.assume(i1 %notzero)251 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)252 %cmp = icmp ne i32 %t0, 1253 ret i1 %cmp254}255 256define i1 @is_pow2_ctpop_logical(i32 %x) {257; CHECK-LABEL: @is_pow2_ctpop_logical(258; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])259; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1260; CHECK-NEXT: ret i1 [[R]]261;262 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)263 %cmp = icmp ult i32 %t0, 2264 %notzero = icmp ne i32 %x, 0265 %r = select i1 %notzero, i1 %cmp, i1 false266 ret i1 %r267}268 269; Extra uses don't change the fold.270declare void @use_i1(i1)271 272define i1 @is_pow2_ctpop_extra_uses(i32 %x) {273; CHECK-LABEL: @is_pow2_ctpop_extra_uses(274; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])275; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2276; CHECK-NEXT: call void @use_i1(i1 [[CMP]])277; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0278; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])279; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1280; CHECK-NEXT: ret i1 [[R]]281;282 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)283 %cmp = icmp ult i32 %t0, 2284 call void @use_i1(i1 %cmp)285 %notzero = icmp ne i32 %x, 0286 call void @use_i1(i1 %notzero)287 %r = and i1 %notzero, %cmp288 ret i1 %r289}290 291define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) {292; CHECK-LABEL: @is_pow2_ctpop_extra_uses_logical(293; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])294; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2295; CHECK-NEXT: call void @use_i1(i1 [[CMP]])296; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0297; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])298; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1299; CHECK-NEXT: ret i1 [[R]]300;301 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)302 %cmp = icmp ult i32 %t0, 2303 call void @use_i1(i1 %cmp)304 %notzero = icmp ne i32 %x, 0305 call void @use_i1(i1 %notzero)306 %r = select i1 %notzero, i1 %cmp, i1 false307 ret i1 %r308}309 310; Test vector type and commuted 'and' operands.311 312define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) {313; CHECK-LABEL: @is_pow2_ctpop_commute_vec(314; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])315; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[T0]], splat (i8 1)316; CHECK-NEXT: ret <2 x i1> [[R]]317;318 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)319 %cmp = icmp ult <2 x i8> %t0, <i8 2, i8 2>320 %notzero = icmp ne <2 x i8> %x, zeroinitializer321 %r = and <2 x i1> %cmp, %notzero322 ret <2 x i1> %r323}324 325; Negative test - wrong constant.326 327define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) {328; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1(329; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])330; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 3331; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0332; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]333; CHECK-NEXT: ret i1 [[R]]334;335 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)336 %cmp = icmp ult i32 %t0, 3337 %notzero = icmp ne i32 %x, 0338 %r = and i1 %notzero, %cmp339 ret i1 %r340}341 342define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {343; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1_logical(344; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])345; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 3346; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0347; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false348; CHECK-NEXT: ret i1 [[R]]349;350 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)351 %cmp = icmp ult i32 %t0, 3352 %notzero = icmp ne i32 %x, 0353 %r = select i1 %notzero, i1 %cmp, i1 false354 ret i1 %r355}356 357; Negative test - wrong constant.358 359define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) {360; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2(361; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])362; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2363; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1364; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]365; CHECK-NEXT: ret i1 [[R]]366;367 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)368 %cmp = icmp ult i32 %t0, 2369 %notzero = icmp ne i32 %x, 1370 %r = and i1 %notzero, %cmp371 ret i1 %r372}373 374define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {375; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2_logical(376; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])377; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2378; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1379; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false380; CHECK-NEXT: ret i1 [[R]]381;382 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)383 %cmp = icmp ult i32 %t0, 2384 %notzero = icmp ne i32 %x, 1385 %r = select i1 %notzero, i1 %cmp, i1 false386 ret i1 %r387}388 389; Negative test - wrong predicate.390 391define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) {392; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1(393; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])394; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 2395; CHECK-NEXT: ret i1 [[CMP]]396;397 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)398 %cmp = icmp ugt i32 %t0, 2399 %notzero = icmp ne i32 %x, 0400 %r = and i1 %notzero, %cmp401 ret i1 %r402}403 404define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) {405; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1_logical(406; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])407; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 2408; CHECK-NEXT: ret i1 [[CMP]]409;410 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)411 %cmp = icmp ugt i32 %t0, 2412 %notzero = icmp ne i32 %x, 0413 %r = select i1 %notzero, i1 %cmp, i1 false414 ret i1 %r415}416 417; Negative test - wrong predicate.418 419define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) {420; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2(421; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])422; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2423; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0424; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]]425; CHECK-NEXT: ret i1 [[R]]426;427 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)428 %cmp = icmp ult i32 %t0, 2429 %cmp2 = icmp sgt i32 %x, 0430 %r = and i1 %cmp2, %cmp431 ret i1 %r432}433 434define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) {435; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2_logical(436; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])437; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i32 [[T0]], 2438; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0439; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 [[CMP]], i1 false440; CHECK-NEXT: ret i1 [[R]]441;442 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)443 %cmp = icmp ult i32 %t0, 2444 %cmp2 = icmp sgt i32 %x, 0445 %r = select i1 %cmp2, i1 %cmp, i1 false446 ret i1 %r447}448 449; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1450 451define i1 @isnot_pow2_ctpop(i32 %x) {452; CHECK-LABEL: @isnot_pow2_ctpop(453; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])454; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1455; CHECK-NEXT: ret i1 [[R]]456;457 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)458 %cmp = icmp ugt i32 %t0, 1459 %iszero = icmp eq i32 %x, 0460 %r = or i1 %iszero, %cmp461 ret i1 %r462}463 464define i1 @isnot_pow2_ctpop_logical(i32 %x) {465; CHECK-LABEL: @isnot_pow2_ctpop_logical(466; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])467; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1468; CHECK-NEXT: ret i1 [[R]]469;470 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)471 %cmp = icmp ugt i32 %t0, 1472 %iszero = icmp eq i32 %x, 0473 %r = select i1 %iszero, i1 true, i1 %cmp474 ret i1 %r475}476 477; Extra uses don't change the fold.478 479define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) {480; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses(481; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])482; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1483; CHECK-NEXT: call void @use_i1(i1 [[CMP]])484; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0485; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])486; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1487; CHECK-NEXT: ret i1 [[R]]488;489 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)490 %cmp = icmp ugt i32 %t0, 1491 call void @use_i1(i1 %cmp)492 %iszero = icmp eq i32 %x, 0493 call void @use_i1(i1 %iszero)494 %r = or i1 %iszero, %cmp495 ret i1 %r496}497 498define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) {499; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses_logical(500; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])501; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1502; CHECK-NEXT: call void @use_i1(i1 [[CMP]])503; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0504; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])505; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1506; CHECK-NEXT: ret i1 [[R]]507;508 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)509 %cmp = icmp ugt i32 %t0, 1510 call void @use_i1(i1 %cmp)511 %iszero = icmp eq i32 %x, 0512 call void @use_i1(i1 %iszero)513 %r = select i1 %iszero, i1 true, i1 %cmp514 ret i1 %r515}516 517; Test vector type and commuted 'or' operands.518 519define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) {520; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec(521; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])522; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[T0]], splat (i8 1)523; CHECK-NEXT: ret <2 x i1> [[R]]524;525 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)526 %cmp = icmp ugt <2 x i8> %t0, <i8 1, i8 1>527 %iszero = icmp eq <2 x i8> %x, zeroinitializer528 %r = or <2 x i1> %cmp, %iszero529 ret <2 x i1> %r530}531 532; Negative test - wrong constant.533 534define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) {535; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1(536; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])537; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 2538; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0539; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]540; CHECK-NEXT: ret i1 [[R]]541;542 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)543 %cmp = icmp ugt i32 %t0, 2544 %iszero = icmp eq i32 %x, 0545 %r = or i1 %iszero, %cmp546 ret i1 %r547}548 549define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) {550; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1_logical(551; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])552; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 2553; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0554; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]555; CHECK-NEXT: ret i1 [[R]]556;557 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)558 %cmp = icmp ugt i32 %t0, 2559 %iszero = icmp eq i32 %x, 0560 %r = select i1 %iszero, i1 true, i1 %cmp561 ret i1 %r562}563 564; Negative test - wrong constant.565 566define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) {567; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2(568; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])569; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1570; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1571; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]572; CHECK-NEXT: ret i1 [[R]]573;574 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)575 %cmp = icmp ugt i32 %t0, 1576 %iszero = icmp eq i32 %x, 1577 %r = or i1 %iszero, %cmp578 ret i1 %r579}580 581define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) {582; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2_logical(583; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])584; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1585; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1586; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]587; CHECK-NEXT: ret i1 [[R]]588;589 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)590 %cmp = icmp ugt i32 %t0, 1591 %iszero = icmp eq i32 %x, 1592 %r = select i1 %iszero, i1 true, i1 %cmp593 ret i1 %r594}595 596; Negative test - wrong predicate.597 598define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) {599; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2(600; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])601; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1602; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0603; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]]604; CHECK-NEXT: ret i1 [[R]]605;606 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)607 %cmp = icmp ugt i32 %t0, 1608 %cmp2 = icmp slt i32 %x, 0609 %r = or i1 %cmp2, %cmp610 ret i1 %r611}612 613define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) {614; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2_logical(615; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])616; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ugt i32 [[T0]], 1617; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0618; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 true, i1 [[CMP]]619; CHECK-NEXT: ret i1 [[R]]620;621 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)622 %cmp = icmp ugt i32 %t0, 1623 %cmp2 = icmp slt i32 %x, 0624 %r = select i1 %cmp2, i1 true, i1 %cmp625 ret i1 %r626}627 628define i1 @is_pow2_negate_op(i32 %x) {629; CHECK-LABEL: @is_pow2_negate_op(630; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])631; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 1632; CHECK-NEXT: ret i1 [[R]]633;634 %neg = sub i32 0, %x635 %and = and i32 %neg, %x636 %cmp = icmp eq i32 %and, %x637 %notzero = icmp ne i32 %x, 0638 %r = and i1 %notzero, %cmp639 ret i1 %r640}641 642define i1 @is_pow2_negate_op_logical(i32 %x) {643; CHECK-LABEL: @is_pow2_negate_op_logical(644; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])645; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 1646; CHECK-NEXT: ret i1 [[R]]647;648 %neg = sub i32 0, %x649 %and = and i32 %neg, %x650 %cmp = icmp eq i32 %and, %x651 %notzero = icmp ne i32 %x, 0652 %r = select i1 %notzero, i1 %cmp, i1 false653 ret i1 %r654}655 656define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) {657; CHECK-LABEL: @is_pow2_negate_op_vec(658; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])659; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i32> [[TMP1]], splat (i32 1)660; CHECK-NEXT: ret <2 x i1> [[R]]661;662 %neg = sub <2 x i32> zeroinitializer, %x663 %and = and <2 x i32> %neg, %x664 %cmp = icmp eq <2 x i32> %and, %x665 %notzero = icmp ne <2 x i32> %x, zeroinitializer666 %r = and <2 x i1> %cmp, %notzero667 ret <2 x i1> %r668}669 670define i1 @is_pow2_decrement_op(i8 %x) {671; CHECK-LABEL: @is_pow2_decrement_op(672; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])673; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], 1674; CHECK-NEXT: ret i1 [[R]]675;676 %dec = add i8 %x, -1677 %and = and i8 %dec, %x678 %cmp = icmp eq i8 %and, 0679 %notzero = icmp ne i8 %x, 0680 %r = and i1 %cmp, %notzero681 ret i1 %r682}683 684define i1 @is_pow2_decrement_op_logical(i8 %x) {685; CHECK-LABEL: @is_pow2_decrement_op_logical(686; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])687; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[TMP1]], 1688; CHECK-NEXT: ret i1 [[R]]689;690 %dec = add i8 %x, -1691 %and = and i8 %dec, %x692 %cmp = icmp eq i8 %and, 0693 %notzero = icmp ne i8 %x, 0694 %r = select i1 %cmp, i1 %notzero, i1 false695 ret i1 %r696}697 698define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) {699; CHECK-LABEL: @is_pow2_decrement_op_vec(700; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])701; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], splat (i8 1)702; CHECK-NEXT: ret <2 x i1> [[R]]703;704 %dec = add <2 x i8> %x, <i8 -1, i8 -1>705 %and = and <2 x i8> %dec, %x706 %cmp = icmp eq <2 x i8> %and, zeroinitializer707 %notzero = icmp ne <2 x i8> %x, zeroinitializer708 %r = and <2 x i1> %notzero, %cmp709 ret <2 x i1> %r710}711 712define i1 @isnot_pow2_negate_op(i32 %x) {713; CHECK-LABEL: @isnot_pow2_negate_op(714; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])715; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 1716; CHECK-NEXT: ret i1 [[R]]717;718 %neg = sub i32 0, %x719 %and = and i32 %neg, %x720 %cmp = icmp ne i32 %and, %x721 %iszero = icmp eq i32 %x, 0722 %r = or i1 %cmp, %iszero723 ret i1 %r724}725 726define i1 @isnot_pow2_negate_op_logical(i32 %x) {727; CHECK-LABEL: @isnot_pow2_negate_op_logical(728; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])729; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[TMP1]], 1730; CHECK-NEXT: ret i1 [[R]]731;732 %neg = sub i32 0, %x733 %and = and i32 %neg, %x734 %cmp = icmp ne i32 %and, %x735 %iszero = icmp eq i32 %x, 0736 %r = select i1 %cmp, i1 true, i1 %iszero737 ret i1 %r738}739 740define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) {741; CHECK-LABEL: @isnot_pow2_negate_op_vec(742; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]])743; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], splat (i32 1)744; CHECK-NEXT: ret <2 x i1> [[R]]745;746 %neg = sub <2 x i32> zeroinitializer, %x747 %and = and <2 x i32> %neg, %x748 %cmp = icmp ne <2 x i32> %and, %x749 %iszero = icmp eq <2 x i32> %x, zeroinitializer750 %r = or <2 x i1> %iszero, %cmp751 ret <2 x i1> %r752}753 754define i1 @isnot_pow2_decrement_op(i8 %x) {755; CHECK-LABEL: @isnot_pow2_decrement_op(756; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])757; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], 1758; CHECK-NEXT: ret i1 [[R]]759;760 %dec = add i8 %x, -1761 %and = and i8 %dec, %x762 %cmp = icmp ne i8 %and, 0763 %iszero = icmp eq i8 %x, 0764 %r = or i1 %iszero, %cmp765 ret i1 %r766}767 768define i1 @isnot_pow2_decrement_op_logical(i8 %x) {769; CHECK-LABEL: @isnot_pow2_decrement_op_logical(770; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X:%.*]])771; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[TMP1]], 1772; CHECK-NEXT: ret i1 [[R]]773;774 %dec = add i8 %x, -1775 %and = and i8 %dec, %x776 %cmp = icmp ne i8 %and, 0777 %iszero = icmp eq i8 %x, 0778 %r = select i1 %iszero, i1 true, i1 %cmp779 ret i1 %r780}781 782define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) {783; CHECK-LABEL: @isnot_pow2_decrement_op_vec(784; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])785; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[TMP1]], splat (i8 1)786; CHECK-NEXT: ret <2 x i1> [[R]]787;788 %dec = add <2 x i8> %x, <i8 -1, i8 -1>789 %and = and <2 x i8> %dec, %x790 %cmp = icmp ne <2 x i8> %and, zeroinitializer791 %iszero = icmp eq <2 x i8> %x, zeroinitializer792 %r = or <2 x i1> %cmp, %iszero793 ret <2 x i1> %r794}795 796; (ctpop(X) == 1) || (X == 0) --> ctpop(X) u< 2797 798define i1 @is_pow2or0_ctpop(i32 %x) {799; CHECK-LABEL: @is_pow2or0_ctpop(800; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])801; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2802; CHECK-NEXT: ret i1 [[R]]803;804 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)805 %cmp = icmp eq i32 %t0, 1806 %iszero = icmp eq i32 %x, 0807 %r = or i1 %iszero, %cmp808 ret i1 %r809}810 811define i1 @is_pow2or0_ctpop_swap_cmp(i32 %x) {812; CHECK-LABEL: @is_pow2or0_ctpop_swap_cmp(813; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])814; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2815; CHECK-NEXT: ret i1 [[R]]816;817 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)818 %cmp = icmp eq i32 %t0, 1819 %iszero = icmp eq i32 %x, 0820 %r = or i1 %cmp, %iszero821 ret i1 %r822}823 824define i1 @is_pow2or0_ctpop_logical(i32 %x) {825; CHECK-LABEL: @is_pow2or0_ctpop_logical(826; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])827; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2828; CHECK-NEXT: ret i1 [[R]]829;830 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)831 %cmp = icmp eq i32 %t0, 1832 %iszero = icmp eq i32 %x, 0833 %r = select i1 %iszero, i1 true, i1 %cmp834 ret i1 %r835}836 837define <2 x i1> @is_pow2or0_ctpop_commute_vec(<2 x i8> %x) {838; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec(839; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])840; CHECK-NEXT: [[R:%.*]] = icmp samesign ult <2 x i8> [[T0]], splat (i8 2)841; CHECK-NEXT: ret <2 x i1> [[R]]842;843 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)844 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1>845 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>846 %r = or <2 x i1> %iszero, %cmp847 ret <2 x i1> %r848}849 850; Extra uses don't change the fold.851 852define i1 @is_pow2or0_ctpop_extra_uses(i32 %x) {853; CHECK-LABEL: @is_pow2or0_ctpop_extra_uses(854; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])855; CHECK-NEXT: call void @use(i32 [[T0]])856; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1857; CHECK-NEXT: call void @use_i1(i1 [[CMP]])858; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0859; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])860; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2861; CHECK-NEXT: ret i1 [[R]]862;863 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)864 call void @use(i32 %t0)865 %cmp = icmp eq i32 %t0, 1866 call void @use_i1(i1 %cmp)867 %iszero = icmp eq i32 %x, 0868 call void @use_i1(i1 %iszero)869 %r = or i1 %iszero, %cmp870 ret i1 %r871}872 873define i1 @is_pow2or0_ctpop_logical_extra_uses(i32 %x) {874; CHECK-LABEL: @is_pow2or0_ctpop_logical_extra_uses(875; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])876; CHECK-NEXT: call void @use(i32 [[T0]])877; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1878; CHECK-NEXT: call void @use_i1(i1 [[CMP]])879; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0880; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]])881; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2882; CHECK-NEXT: ret i1 [[R]]883;884 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)885 call void @use(i32 %t0)886 %cmp = icmp eq i32 %t0, 1887 call void @use_i1(i1 %cmp)888 %iszero = icmp eq i32 %x, 0889 call void @use_i1(i1 %iszero)890 %r = select i1 %iszero, i1 true, i1 %cmp891 ret i1 %r892}893 894; Negative test - wrong constant.895 896define i1 @is_pow2or0_ctpop_wrong_cmp_op1(i32 %x) {897; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1(898; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])899; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 2900; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0901; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]]902; CHECK-NEXT: ret i1 [[R]]903;904 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)905 %cmp = icmp eq i32 %t0, 2906 %iszero = icmp eq i32 %x, 0907 %r = or i1 %iszero, %cmp908 ret i1 %r909}910 911define i1 @is_pow2or0_ctpop_wrong_cmp_op1_logical(i32 %x) {912; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1_logical(913; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])914; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 3915; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0916; CHECK-NEXT: [[R:%.*]] = select i1 [[ISZERO]], i1 true, i1 [[CMP]]917; CHECK-NEXT: ret i1 [[R]]918;919 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)920 %cmp = icmp eq i32 %t0, 3921 %iszero = icmp eq i32 %x, 0922 %r = select i1 %iszero, i1 true, i1 %cmp923 ret i1 %r924}925 926define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {927; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(928; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])929; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 -1, i8 1>930; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer931; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[ISZERO]]932; CHECK-NEXT: ret <2 x i1> [[R]]933;934 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)935 %cmp = icmp eq <2 x i8> %t0, <i8 -1, i8 1>936 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>937 %r = or <2 x i1> %cmp, %iszero938 ret <2 x i1> %r939}940 941; Negative test - wrong predicate.942 943define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) {944; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred1(945; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])946; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1947; CHECK-NEXT: ret i1 [[CMP]]948;949 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)950 %cmp = icmp ne i32 %t0, 1951 %iszero = icmp eq i32 %x, 0952 %r = or i1 %iszero, %cmp953 ret i1 %r954}955 956define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) {957; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2(958; CHECK-NEXT: ret i1 true959;960 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)961 %cmp = icmp ne i32 %t0, 1962 %iszero = icmp ne i32 %x, 0963 %r = or i1 %iszero, %cmp964 ret i1 %r965}966 967define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) {968; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2_logical(969; CHECK-NEXT: ret i1 true970;971 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)972 %cmp = icmp ne i32 %t0, 1973 %iszero = icmp ne i32 %x, 0974 %r = select i1 %iszero, i1 true, i1 %cmp975 ret i1 %r976}977 978define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) {979; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_pred3(980; CHECK-NEXT: ret <2 x i1> zeroinitializer981;982 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)983 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1>984 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0>985 %r = and <2 x i1> %cmp, %iszero986 ret <2 x i1> %r987}988 989; (ctpop(X) != 1) && (X != 0) --> ctpop(X) u> 1990 991define i1 @isnot_pow2nor0_ctpop(i32 %x) {992; CHECK-LABEL: @isnot_pow2nor0_ctpop(993; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])994; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 1995; CHECK-NEXT: ret i1 [[R]]996;997 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)998 %cmp = icmp ne i32 %t0, 1999 %notzero = icmp ne i32 %x, 01000 %r = and i1 %notzero, %cmp1001 ret i1 %r1002}1003 1004define i1 @isnot_pow2nor0_ctpop_swap_cmp(i32 %x) {1005; CHECK-LABEL: @isnot_pow2nor0_ctpop_swap_cmp(1006; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1007; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 11008; CHECK-NEXT: ret i1 [[R]]1009;1010 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1011 %cmp = icmp ne i32 %t0, 11012 %notzero = icmp ne i32 %x, 01013 %r = and i1 %cmp, %notzero1014 ret i1 %r1015}1016 1017define i1 @isnot_pow2nor0_ctpop_logical(i32 %x) {1018; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical(1019; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1020; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 11021; CHECK-NEXT: ret i1 [[R]]1022;1023 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1024 %cmp = icmp ne i32 %t0, 11025 %notzero = icmp ne i32 %x, 01026 %r = select i1 %notzero, i1 %cmp, i1 false1027 ret i1 %r1028}1029 1030define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec(<2 x i8> %x) {1031; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec(1032; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])1033; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt <2 x i8> [[T0]], splat (i8 1)1034; CHECK-NEXT: ret <2 x i1> [[R]]1035;1036 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)1037 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1>1038 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>1039 %r = and <2 x i1> %notzero, %cmp1040 ret <2 x i1> %r1041}1042 1043; Extra uses don't change the fold.1044 1045define i1 @isnot_pow2nor0_ctpop_extra_uses(i32 %x) {1046; CHECK-LABEL: @isnot_pow2nor0_ctpop_extra_uses(1047; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1048; CHECK-NEXT: call void @use(i32 [[T0]])1049; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 11050; CHECK-NEXT: call void @use_i1(i1 [[CMP]])1051; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 01052; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])1053; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 11054; CHECK-NEXT: ret i1 [[R]]1055;1056 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1057 call void @use(i32 %t0)1058 %cmp = icmp ne i32 %t0, 11059 call void @use_i1(i1 %cmp)1060 %notzero = icmp ne i32 %x, 01061 call void @use_i1(i1 %notzero)1062 %r = and i1 %notzero, %cmp1063 ret i1 %r1064}1065 1066define i1 @isnot_pow2nor0_ctpop_logical_extra_uses(i32 %x) {1067; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical_extra_uses(1068; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1069; CHECK-NEXT: call void @use(i32 [[T0]])1070; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 11071; CHECK-NEXT: call void @use_i1(i1 [[CMP]])1072; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 01073; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]])1074; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 11075; CHECK-NEXT: ret i1 [[R]]1076;1077 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1078 call void @use(i32 %t0)1079 %cmp = icmp ne i32 %t0, 11080 call void @use_i1(i1 %cmp)1081 %notzero = icmp ne i32 %x, 01082 call void @use_i1(i1 %notzero)1083 %r = select i1 %notzero, i1 %cmp, i1 false1084 ret i1 %r1085}1086 1087; Negative test - wrong constant.1088 1089define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1(i32 %x) {1090; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1(1091; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1092; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 41093; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 01094; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]]1095; CHECK-NEXT: ret i1 [[R]]1096;1097 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1098 %cmp = icmp ne i32 %t0, 41099 %notzero = icmp ne i32 %x, 01100 %r = and i1 %notzero, %cmp1101 ret i1 %r1102}1103 1104define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(i32 %x) {1105; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(1106; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1107; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 51108; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 01109; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false1110; CHECK-NEXT: ret i1 [[R]]1111;1112 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1113 %cmp = icmp ne i32 %t0, 51114 %notzero = icmp ne i32 %x, 01115 %r = select i1 %notzero, i1 %cmp, i1 false1116 ret i1 %r1117}1118 1119define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) {1120; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(1121; CHECK-NEXT: [[T0:%.*]] = tail call range(i8 0, 9) <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]])1122; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 0, i8 -1>1123; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer1124; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[NOTZERO]]1125; CHECK-NEXT: ret <2 x i1> [[R]]1126;1127 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)1128 %cmp = icmp ne <2 x i8> %t0, <i8 0, i8 -1>1129 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>1130 %r = and <2 x i1> %cmp, %notzero1131 ret <2 x i1> %r1132}1133 1134; Negative test - wrong predicate.1135 1136define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) {1137; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred1(1138; CHECK-NEXT: [[T0:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1139; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 11140; CHECK-NEXT: ret i1 [[CMP]]1141;1142 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1143 %cmp = icmp eq i32 %t0, 11144 %notzero = icmp ne i32 %x, 01145 %r = and i1 %notzero, %cmp1146 ret i1 %r1147}1148 1149define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) {1150; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2(1151; CHECK-NEXT: ret i1 false1152;1153 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1154 %cmp = icmp eq i32 %t0, 11155 %notzero = icmp eq i32 %x, 01156 %r = and i1 %notzero, %cmp1157 ret i1 %r1158}1159 1160define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) {1161; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2_logical(1162; CHECK-NEXT: ret i1 false1163;1164 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x)1165 %cmp = icmp eq i32 %t0, 11166 %notzero = icmp eq i32 %x, 01167 %r = select i1 %notzero, i1 %cmp, i1 false1168 ret i1 %r1169}1170 1171define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) {1172; CHECK-LABEL: @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(1173; CHECK-NEXT: ret <2 x i1> splat (i1 true)1174;1175 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x)1176 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1>1177 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0>1178 %r = or <2 x i1> %cmp, %notzero1179 ret <2 x i1> %r1180}1181 1182define i1 @is_pow2_fail_pr63327(i32 %x) {1183; CHECK-LABEL: @is_pow2_fail_pr63327(1184; CHECK-NEXT: [[NX:%.*]] = sub i32 0, [[X:%.*]]1185; CHECK-NEXT: [[X_AND_NX:%.*]] = and i32 [[X]], [[NX]]1186; CHECK-NEXT: [[R:%.*]] = icmp sge i32 [[X_AND_NX]], [[X]]1187; CHECK-NEXT: ret i1 [[R]]1188;1189 %nx = sub i32 0, %x1190 %x_and_nx = and i32 %x, %nx1191 %r = icmp sge i32 %x_and_nx, %x1192 ret i1 %r1193}1194 1195define i1 @blsmsk_is_p2_or_z(i32 %xx, i32 %yy) {1196; CHECK-LABEL: @blsmsk_is_p2_or_z(1197; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]]1198; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X]], -11199; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]]1200; CHECK-NEXT: [[R:%.*]] = icmp uge i32 [[X]], [[Y]]1201; CHECK-NEXT: ret i1 [[R]]1202;1203 %x = or i32 %xx, %yy1204 %xm1 = add i32 %x, -11205 %y = xor i32 %x, %xm11206 %r = icmp uge i32 %x, %y1207 ret i1 %r1208}1209 1210define i1 @blsmsk_isnt_p2_or_z(i32 %x) {1211; CHECK-LABEL: @blsmsk_isnt_p2_or_z(1212; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1213; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[TMP1]], 11214; CHECK-NEXT: ret i1 [[R]]1215;1216 %xm1 = add i32 %x, -11217 %y = xor i32 %x, %xm11218 %r = icmp ult i32 %y, %x1219 ret i1 %r1220}1221 1222define i1 @blsmsk_is_p2_or_z_fail(i32 %xx, i32 %yy) {1223; CHECK-LABEL: @blsmsk_is_p2_or_z_fail(1224; CHECK-NEXT: [[X:%.*]] = or i32 [[XX:%.*]], [[YY:%.*]]1225; CHECK-NEXT: [[TMP1:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X]])1226; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[TMP1]], 11227; CHECK-NEXT: ret i1 [[R]]1228;1229 %x = or i32 %xx, %yy1230 %xm1 = add i32 %x, -11231 %y = xor i32 %x, %xm11232 %r = icmp ugt i32 %x, %y1233 ret i1 %r1234}1235 1236define i1 @blsmsk_isnt_p2_or_z_fail(i32 %x) {1237; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail(1238; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -11239; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]]1240; CHECK-NEXT: [[R:%.*]] = icmp ule i32 [[Y]], [[X]]1241; CHECK-NEXT: ret i1 [[R]]1242;1243 %xm1 = add i32 %x, -11244 %y = xor i32 %x, %xm11245 %r = icmp ule i32 %y, %x1246 ret i1 %r1247}1248 1249declare void @use.i32(i32)1250 1251define i1 @blsmsk_isnt_p2_or_z_fail_multiuse(i32 %x) {1252; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_multiuse(1253; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -11254; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]]1255; CHECK-NEXT: call void @use.i32(i32 [[Y]])1256; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]1257; CHECK-NEXT: ret i1 [[R]]1258;1259 %xm1 = add i32 %x, -11260 %y = xor i32 %x, %xm11261 call void @use.i32(i32 %y)1262 %r = icmp ult i32 %y, %x1263 ret i1 %r1264}1265 1266define i1 @blsmsk_isnt_p2_or_z_fail_wrong_add(i32 %x, i32 %z) {1267; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_wrong_add(1268; CHECK-NEXT: [[XM1:%.*]] = add i32 [[Z:%.*]], -11269; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X:%.*]], [[XM1]]1270; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]1271; CHECK-NEXT: ret i1 [[R]]1272;1273 %xm1 = add i32 %z, -11274 %y = xor i32 %x, %xm11275 %r = icmp ult i32 %y, %x1276 ret i1 %r1277}1278 1279 1280define i1 @blsmsk_isnt_p2_or_z_fail_bad_xor(i32 %x, i32 %z) {1281; CHECK-LABEL: @blsmsk_isnt_p2_or_z_fail_bad_xor(1282; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -11283; CHECK-NEXT: [[Y:%.*]] = xor i32 [[Z:%.*]], [[XM1]]1284; CHECK-NEXT: [[R:%.*]] = icmp ult i32 [[Y]], [[X]]1285; CHECK-NEXT: ret i1 [[R]]1286;1287 %xm1 = add i32 %x, -11288 %y = xor i32 %z, %xm11289 %r = icmp ult i32 %y, %x1290 ret i1 %r1291}1292 1293 1294define i1 @blsmsk_is_p2_or_z_fail_bad_cmp(i32 %x, i32 %z) {1295; CHECK-LABEL: @blsmsk_is_p2_or_z_fail_bad_cmp(1296; CHECK-NEXT: [[XM1:%.*]] = add i32 [[X:%.*]], -11297; CHECK-NEXT: [[Y:%.*]] = xor i32 [[X]], [[XM1]]1298; CHECK-NEXT: [[R:%.*]] = icmp uge i32 [[Y]], [[Z:%.*]]1299; CHECK-NEXT: ret i1 [[R]]1300;1301 %xm1 = add i32 %x, -11302 %y = xor i32 %x, %xm11303 %r = icmp uge i32 %y, %z1304 ret i1 %r1305}1306 1307define i1 @blsmsk_is_p2_or_z_ule_xy(i8 %xx, i8 %yy) {1308; CHECK-LABEL: @blsmsk_is_p2_or_z_ule_xy(1309; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1310; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X]])1311; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i8 [[TMP1]], 21312; CHECK-NEXT: ret i1 [[R]]1313;1314 %x = or i8 %xx, %yy1315 %xm1 = add i8 %x, -11316 %y = xor i8 %x, %xm11317 %r = icmp ule i8 %x, %y1318 ret i1 %r1319}1320 1321 1322define i1 @blsmsk_is_p2_or_z_ule_yx_fail(i8 %xx, i8 %yy) {1323; CHECK-LABEL: @blsmsk_is_p2_or_z_ule_yx_fail(1324; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1325; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -11326; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]1327; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[Y]], [[X]]1328; CHECK-NEXT: ret i1 [[R]]1329;1330 %x = or i8 %xx, %yy1331 %xm1 = add i8 %x, -11332 %y = xor i8 %x, %xm11333 %r = icmp ule i8 %y, %x1334 ret i1 %r1335}1336 1337 1338define i1 @blsmsk_is_p2_or_z_uge_yx(i8 %xx, i8 %yy) {1339; CHECK-LABEL: @blsmsk_is_p2_or_z_uge_yx(1340; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1341; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X]])1342; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i8 [[TMP1]], 21343; CHECK-NEXT: ret i1 [[R]]1344;1345 %x = or i8 %xx, %yy1346 %xm1 = add i8 %x, -11347 %y = xor i8 %x, %xm11348 %r = icmp uge i8 %y, %x1349 ret i1 %r1350}1351 1352 1353define i1 @blsmsk_is_p2_or_z_uge_xy_fail(i8 %xx, i8 %yy) {1354; CHECK-LABEL: @blsmsk_is_p2_or_z_uge_xy_fail(1355; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1356; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -11357; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]1358; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[X]], [[Y]]1359; CHECK-NEXT: ret i1 [[R]]1360;1361 %x = or i8 %xx, %yy1362 %xm1 = add i8 %x, -11363 %y = xor i8 %x, %xm11364 %r = icmp uge i8 %x, %y1365 ret i1 %r1366}1367 1368define i1 @blsmsk_isnt_p2_or_z_ugt_xy(i8 %xx, i8 %yy) {1369; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ugt_xy(1370; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1371; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X]])1372; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i8 [[TMP1]], 11373; CHECK-NEXT: ret i1 [[R]]1374;1375 %x = or i8 %xx, %yy1376 %xm1 = add i8 %x, -11377 %y = xor i8 %x, %xm11378 %r = icmp ugt i8 %x, %y1379 ret i1 %r1380}1381 1382 1383define i1 @blsmsk_isnt_p2_or_z_ugt_yx_fail(i8 %xx, i8 %yy) {1384; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ugt_yx_fail(1385; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1386; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -11387; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]1388; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[Y]], [[X]]1389; CHECK-NEXT: ret i1 [[R]]1390;1391 %x = or i8 %xx, %yy1392 %xm1 = add i8 %x, -11393 %y = xor i8 %x, %xm11394 %r = icmp ugt i8 %y, %x1395 ret i1 %r1396}1397 1398 1399define i1 @blsmsk_isnt_p2_or_z_ult_yx(i8 %xx, i8 %yy) {1400; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ult_yx(1401; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1402; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.ctpop.i8(i8 [[X]])1403; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i8 [[TMP1]], 11404; CHECK-NEXT: ret i1 [[R]]1405;1406 %x = or i8 %xx, %yy1407 %xm1 = add i8 %x, -11408 %y = xor i8 %x, %xm11409 %r = icmp ult i8 %y, %x1410 ret i1 %r1411}1412 1413 1414define i1 @blsmsk_isnt_p2_or_z_ult_xy_fail(i8 %xx, i8 %yy) {1415; CHECK-LABEL: @blsmsk_isnt_p2_or_z_ult_xy_fail(1416; CHECK-NEXT: [[X:%.*]] = or i8 [[XX:%.*]], [[YY:%.*]]1417; CHECK-NEXT: [[XM1:%.*]] = add i8 [[X]], -11418; CHECK-NEXT: [[Y:%.*]] = xor i8 [[X]], [[XM1]]1419; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[X]], [[Y]]1420; CHECK-NEXT: ret i1 [[R]]1421;1422 %x = or i8 %xx, %yy1423 %xm1 = add i8 %x, -11424 %y = xor i8 %x, %xm11425 %r = icmp ult i8 %x, %y1426 ret i1 %r1427}1428 1429declare <2 x i32> @llvm.ctpop.2xi32(<2 x i32>)1430define i1 @is_pow2_nz_known_bits(i32 %xin) {1431; CHECK-LABEL: @is_pow2_nz_known_bits(1432; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[XIN:%.*]], -651433; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 01434; CHECK-NEXT: ret i1 [[R]]1435;1436 %x = or i32 %xin, 641437 %cnt = call i32 @llvm.ctpop.i32(i32 %x)1438 %r = icmp eq i32 %cnt, 11439 ret i1 %r1440}1441 1442define i1 @is_pow2_nz_known_bits_fail_multiuse(i32 %xin) {1443; CHECK-LABEL: @is_pow2_nz_known_bits_fail_multiuse(1444; CHECK-NEXT: [[X:%.*]] = or i32 [[XIN:%.*]], 641445; CHECK-NEXT: [[CNT:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])1446; CHECK-NEXT: call void @use.i32(i32 [[CNT]])1447; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[CNT]], 11448; CHECK-NEXT: ret i1 [[R]]1449;1450 %x = or i32 %xin, 641451 %cnt = call i32 @llvm.ctpop.i32(i32 %x)1452 call void @use.i32(i32 %cnt)1453 %r = icmp eq i32 %cnt, 11454 ret i1 %r1455}1456 1457define i1 @not_pow2_nz_known_bits(i32 %xin) {1458; CHECK-LABEL: @not_pow2_nz_known_bits(1459; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[XIN:%.*]], 11460; CHECK-NEXT: ret i1 [[R]]1461;1462 %x = or i32 %xin, 11463 %cnt = call i32 @llvm.ctpop.i32(i32 %x)1464 %r = icmp ne i32 %cnt, 11465 ret i1 %r1466}1467 1468define i1 @not_pow2_nz_known_bits_fail_not_p2_test(i32 %xin) {1469; CHECK-LABEL: @not_pow2_nz_known_bits_fail_not_p2_test(1470; CHECK-NEXT: [[X:%.*]] = or i32 [[XIN:%.*]], 11471; CHECK-NEXT: [[CNT:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]])1472; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[CNT]], 21473; CHECK-NEXT: ret i1 [[R]]1474;1475 %x = or i32 %xin, 11476 %cnt = call i32 @llvm.ctpop.i32(i32 %x)1477 %r = icmp ne i32 %cnt, 21478 ret i1 %r1479}1480 1481define i1 @is_pow2_or_z_known_bits(i32 %xin) {1482; CHECK-LABEL: @is_pow2_or_z_known_bits(1483; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[XIN:%.*]], 21474836471484; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 01485; CHECK-NEXT: ret i1 [[R]]1486;1487 %x = or i32 %xin, 21474836481488 %cnt = call i32 @llvm.ctpop.i32(i32 %x)1489 %r = icmp ult i32 %cnt, 21490 ret i1 %r1491}1492 1493define <2 x i1> @not_pow2_or_z_known_bits(<2 x i32> %xin) {1494; CHECK-LABEL: @not_pow2_or_z_known_bits(1495; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[XIN:%.*]], splat (i32 -65)1496; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i32> [[TMP1]], zeroinitializer1497; CHECK-NEXT: ret <2 x i1> [[R]]1498;1499 %x = or <2 x i32> %xin, <i32 64, i32 64>1500 %cnt = call <2 x i32> @llvm.ctpop.2xi32(<2 x i32> %x)1501 %r = icmp ugt <2 x i32> %cnt, <i32 1, i32 1>1502 ret <2 x i1> %r1503}1504 1505define <2 x i1> @not_pow2_or_z_known_bits_fail_wrong_cmp(<2 x i32> %xin) {1506; CHECK-LABEL: @not_pow2_or_z_known_bits_fail_wrong_cmp(1507; CHECK-NEXT: [[X:%.*]] = or <2 x i32> [[XIN:%.*]], splat (i32 64)1508; CHECK-NEXT: [[CNT:%.*]] = call range(i32 1, 33) <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X]])1509; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt <2 x i32> [[CNT]], splat (i32 2)1510; CHECK-NEXT: ret <2 x i1> [[R]]1511;1512 %x = or <2 x i32> %xin, <i32 64, i32 64>1513 %cnt = call <2 x i32> @llvm.ctpop.2xi32(<2 x i32> %x)1514 %r = icmp ugt <2 x i32> %cnt, <i32 2, i32 2>1515 ret <2 x i1> %r1516}1517 1518; Make sure that range attributes on return values are dropped after merging these two icmps1519 1520define i1 @has_single_bit(i32 %x) {1521; CHECK-LABEL: @has_single_bit(1522; CHECK-NEXT: entry:1523; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1524; CHECK-NEXT: [[SEL:%.*]] = icmp eq i32 [[POPCNT]], 11525; CHECK-NEXT: ret i1 [[SEL]]1526;1527entry:1528 %cmp1 = icmp ne i32 %x, 01529 %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)1530 %cmp2 = icmp ult i32 %popcnt, 21531 %sel = select i1 %cmp1, i1 %cmp2, i1 false1532 ret i1 %sel1533}1534 1535define i1 @has_single_bit_inv(i32 %x) {1536; CHECK-LABEL: @has_single_bit_inv(1537; CHECK-NEXT: entry:1538; CHECK-NEXT: [[POPCNT:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1539; CHECK-NEXT: [[SEL:%.*]] = icmp ne i32 [[POPCNT]], 11540; CHECK-NEXT: ret i1 [[SEL]]1541;1542entry:1543 %cmp1 = icmp eq i32 %x, 01544 %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)1545 %cmp2 = icmp ugt i32 %popcnt, 11546 %sel = select i1 %cmp1, i1 true, i1 %cmp21547 ret i1 %sel1548}1549 1550define i1 @is_power2_or_zero_with_range(i32 %x) {1551; CHECK-LABEL: @is_power2_or_zero_with_range(1552; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1553; CHECK-NEXT: [[RES:%.*]] = icmp samesign ult i32 [[CTPOP]], 21554; CHECK-NEXT: ret i1 [[RES]]1555;1556 %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)1557 %cmp = icmp eq i32 %ctpop, 11558 %notzero = icmp eq i32 %x, 01559 %res = select i1 %notzero, i1 true, i1 %cmp1560 ret i1 %res1561}1562 1563define i1 @is_power2_or_zero_inv_with_range(i32 %x) {1564; CHECK-LABEL: @is_power2_or_zero_inv_with_range(1565; CHECK-NEXT: [[CTPOP:%.*]] = call range(i32 0, 33) i32 @llvm.ctpop.i32(i32 [[X:%.*]])1566; CHECK-NEXT: [[RES:%.*]] = icmp samesign ugt i32 [[CTPOP]], 11567; CHECK-NEXT: ret i1 [[RES]]1568;1569 %ctpop = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x)1570 %cmp = icmp ne i32 %ctpop, 11571 %notzero = icmp ne i32 %x, 01572 %res = select i1 %notzero, i1 %cmp, i1 false1573 ret i1 %res1574}1575