1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 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]], 2 8; CHECK-NEXT: ret i1 [[CMP]] 9; 10 %neg = sub i32 0, %x 11 %and = and i32 %neg, %x 12 %cmp = icmp eq i32 %and, %x 13 ret i1 %cmp 14} 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, %x 23 %and = and <2 x i32> %neg, %x 24 %cmp = icmp eq <2 x i32> %and, %x 25 ret <2 x i1> %cmp 26} 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]], 2 32; CHECK-NEXT: ret i1 [[CMP]] 33; 34 %dec = add i8 %x, -1 35 %and = and i8 %dec, %x 36 %cmp = icmp eq i8 %and, 0 37 ret i1 %cmp 38} 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, %x 48 %cmp = icmp eq <2 x i8> %and, zeroinitializer 49 ret <2 x i1> %cmp 50} 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]], 1 56; CHECK-NEXT: ret i1 [[CMP]] 57; 58 %neg = sub i32 0, %x 59 %and = and i32 %neg, %x 60 %cmp = icmp ne i32 %and, %x 61 ret i1 %cmp 62} 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, %x 71 %and = and <2 x i32> %neg, %x 72 %cmp = icmp ne <2 x i32> %and, %x 73 ret <2 x i1> %cmp 74} 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]], 1 80; CHECK-NEXT: ret i1 [[CMP]] 81; 82 %dec = add i8 %x, -1 83 %and = and i8 %dec, %x 84 %cmp = icmp ne i8 %and, 0 85 ret i1 %cmp 86} 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, %x 96 %cmp = icmp ne <2 x i8> %and, zeroinitializer 97 ret <2 x i1> %cmp 98} 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]], 2 105; CHECK-NEXT: ret i1 [[CMP]] 106; 107 %x = srem i32 42, %p ; thwart complexity-based canonicalization 108 %neg = sub i32 0, %x 109 %and = and i32 %x, %neg 110 %cmp = icmp eq i32 %and, %x 111 ret i1 %cmp 112} 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]], 1 121; CHECK-NEXT: ret i1 [[CMP]] 122; 123 %x = urem i32 42, %p ; thwart complexity-based canonicalization 124 %neg = sub i32 0, %x 125 %and = and i32 %neg, %x 126 %cmp = icmp ne i32 %x, %and 127 ret i1 %cmp 128} 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]], 1 135; CHECK-NEXT: ret i1 [[CMP]] 136; 137 %x = urem i32 42, %p ; thwart complexity-based canonicalization 138 %neg = sub i32 0, %x 139 %and = and i32 %x, %neg 140 %cmp = icmp ne i32 %x, %and 141 ret i1 %cmp 142} 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]], 2 152; CHECK-NEXT: ret i1 [[CMP]] 153; 154 %neg = sub i32 0, %x 155 call void @use(i32 %neg) 156 %and = and i32 %neg, %x 157 %cmp = icmp eq i32 %and, %x 158 ret i1 %cmp 159} 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, %x 170 %and = and i32 %neg, %x 171 call void @use(i32 %and) 172 %cmp = icmp eq i32 %and, %x 173 ret i1 %cmp 174} 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) == 1 181 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]], 1 186; CHECK-NEXT: ret i1 [[R]] 187; 188 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 189 %cmp = icmp ult i32 %t0, 2 190 %notzero = icmp ne i32 %x, 0 191 %r = and i1 %notzero, %cmp 192 ret i1 %r 193} 194 195; tests from PR57328 196define 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:%.*]], 0 199; 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]], 2 202; CHECK-NEXT: ret i1 [[CMP]] 203; 204 %notzero = icmp ne i32 %x, 0 205 call void @llvm.assume(i1 %notzero) 206 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 207 %cmp = icmp ult i32 %t0, 2 208 ret i1 %cmp 209} 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:%.*]], 0 214; 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]], 1 217; CHECK-NEXT: ret i1 [[CMP]] 218; 219 %notzero = icmp ne i32 %x, 0 220 call void @llvm.assume(i1 %notzero) 221 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 222 %cmp = icmp eq i32 %t0, 1 223 ret i1 %cmp 224} 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:%.*]], 0 229; 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]], 1 232; CHECK-NEXT: ret i1 [[CMP]] 233; 234 %notzero = icmp ne i32 %x, 0 235 call void @llvm.assume(i1 %notzero) 236 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 237 %cmp = icmp ugt i32 %t0, 1 238 ret i1 %cmp 239} 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:%.*]], 0 244; 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]], 1 247; CHECK-NEXT: ret i1 [[CMP]] 248; 249 %notzero = icmp ne i32 %x, 0 250 call void @llvm.assume(i1 %notzero) 251 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 252 %cmp = icmp ne i32 %t0, 1 253 ret i1 %cmp 254} 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]], 1 260; CHECK-NEXT: ret i1 [[R]] 261; 262 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 263 %cmp = icmp ult i32 %t0, 2 264 %notzero = icmp ne i32 %x, 0 265 %r = select i1 %notzero, i1 %cmp, i1 false 266 ret i1 %r 267} 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]], 2 276; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 277; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 278; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 279; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1 280; CHECK-NEXT: ret i1 [[R]] 281; 282 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 283 %cmp = icmp ult i32 %t0, 2 284 call void @use_i1(i1 %cmp) 285 %notzero = icmp ne i32 %x, 0 286 call void @use_i1(i1 %notzero) 287 %r = and i1 %notzero, %cmp 288 ret i1 %r 289} 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]], 2 295; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 296; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 297; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 298; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[T0]], 1 299; CHECK-NEXT: ret i1 [[R]] 300; 301 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 302 %cmp = icmp ult i32 %t0, 2 303 call void @use_i1(i1 %cmp) 304 %notzero = icmp ne i32 %x, 0 305 call void @use_i1(i1 %notzero) 306 %r = select i1 %notzero, i1 %cmp, i1 false 307 ret i1 %r 308} 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, zeroinitializer 321 %r = and <2 x i1> %cmp, %notzero 322 ret <2 x i1> %r 323} 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]], 3 331; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 332; 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, 3 337 %notzero = icmp ne i32 %x, 0 338 %r = and i1 %notzero, %cmp 339 ret i1 %r 340} 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]], 3 346; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 347; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false 348; CHECK-NEXT: ret i1 [[R]] 349; 350 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 351 %cmp = icmp ult i32 %t0, 3 352 %notzero = icmp ne i32 %x, 0 353 %r = select i1 %notzero, i1 %cmp, i1 false 354 ret i1 %r 355} 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]], 2 363; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1 364; 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, 2 369 %notzero = icmp ne i32 %x, 1 370 %r = and i1 %notzero, %cmp 371 ret i1 %r 372} 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]], 2 378; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1 379; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false 380; CHECK-NEXT: ret i1 [[R]] 381; 382 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 383 %cmp = icmp ult i32 %t0, 2 384 %notzero = icmp ne i32 %x, 1 385 %r = select i1 %notzero, i1 %cmp, i1 false 386 ret i1 %r 387} 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]], 2 395; CHECK-NEXT: ret i1 [[CMP]] 396; 397 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 398 %cmp = icmp ugt i32 %t0, 2 399 %notzero = icmp ne i32 %x, 0 400 %r = and i1 %notzero, %cmp 401 ret i1 %r 402} 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]], 2 408; CHECK-NEXT: ret i1 [[CMP]] 409; 410 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 411 %cmp = icmp ugt i32 %t0, 2 412 %notzero = icmp ne i32 %x, 0 413 %r = select i1 %notzero, i1 %cmp, i1 false 414 ret i1 %r 415} 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]], 2 423; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0 424; 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, 2 429 %cmp2 = icmp sgt i32 %x, 0 430 %r = and i1 %cmp2, %cmp 431 ret i1 %r 432} 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]], 2 438; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0 439; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP2]], i1 [[CMP]], i1 false 440; CHECK-NEXT: ret i1 [[R]] 441; 442 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 443 %cmp = icmp ult i32 %t0, 2 444 %cmp2 = icmp sgt i32 %x, 0 445 %r = select i1 %cmp2, i1 %cmp, i1 false 446 ret i1 %r 447} 448 449; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1 450 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]], 1 455; CHECK-NEXT: ret i1 [[R]] 456; 457 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 458 %cmp = icmp ugt i32 %t0, 1 459 %iszero = icmp eq i32 %x, 0 460 %r = or i1 %iszero, %cmp 461 ret i1 %r 462} 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]], 1 468; CHECK-NEXT: ret i1 [[R]] 469; 470 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 471 %cmp = icmp ugt i32 %t0, 1 472 %iszero = icmp eq i32 %x, 0 473 %r = select i1 %iszero, i1 true, i1 %cmp 474 ret i1 %r 475} 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]], 1 483; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 484; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 485; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 486; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1 487; CHECK-NEXT: ret i1 [[R]] 488; 489 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 490 %cmp = icmp ugt i32 %t0, 1 491 call void @use_i1(i1 %cmp) 492 %iszero = icmp eq i32 %x, 0 493 call void @use_i1(i1 %iszero) 494 %r = or i1 %iszero, %cmp 495 ret i1 %r 496} 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]], 1 502; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 503; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 504; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 505; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[T0]], 1 506; CHECK-NEXT: ret i1 [[R]] 507; 508 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 509 %cmp = icmp ugt i32 %t0, 1 510 call void @use_i1(i1 %cmp) 511 %iszero = icmp eq i32 %x, 0 512 call void @use_i1(i1 %iszero) 513 %r = select i1 %iszero, i1 true, i1 %cmp 514 ret i1 %r 515} 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, zeroinitializer 528 %r = or <2 x i1> %cmp, %iszero 529 ret <2 x i1> %r 530} 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]], 2 538; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 539; 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, 2 544 %iszero = icmp eq i32 %x, 0 545 %r = or i1 %iszero, %cmp 546 ret i1 %r 547} 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]], 2 553; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 554; 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, 2 559 %iszero = icmp eq i32 %x, 0 560 %r = select i1 %iszero, i1 true, i1 %cmp 561 ret i1 %r 562} 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]], 1 570; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1 571; 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, 1 576 %iszero = icmp eq i32 %x, 1 577 %r = or i1 %iszero, %cmp 578 ret i1 %r 579} 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]], 1 585; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1 586; 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, 1 591 %iszero = icmp eq i32 %x, 1 592 %r = select i1 %iszero, i1 true, i1 %cmp 593 ret i1 %r 594} 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]], 1 602; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0 603; 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, 1 608 %cmp2 = icmp slt i32 %x, 0 609 %r = or i1 %cmp2, %cmp 610 ret i1 %r 611} 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]], 1 617; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0 618; 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, 1 623 %cmp2 = icmp slt i32 %x, 0 624 %r = select i1 %cmp2, i1 true, i1 %cmp 625 ret i1 %r 626} 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]], 1 632; CHECK-NEXT: ret i1 [[R]] 633; 634 %neg = sub i32 0, %x 635 %and = and i32 %neg, %x 636 %cmp = icmp eq i32 %and, %x 637 %notzero = icmp ne i32 %x, 0 638 %r = and i1 %notzero, %cmp 639 ret i1 %r 640} 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]], 1 646; CHECK-NEXT: ret i1 [[R]] 647; 648 %neg = sub i32 0, %x 649 %and = and i32 %neg, %x 650 %cmp = icmp eq i32 %and, %x 651 %notzero = icmp ne i32 %x, 0 652 %r = select i1 %notzero, i1 %cmp, i1 false 653 ret i1 %r 654} 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, %x 663 %and = and <2 x i32> %neg, %x 664 %cmp = icmp eq <2 x i32> %and, %x 665 %notzero = icmp ne <2 x i32> %x, zeroinitializer 666 %r = and <2 x i1> %cmp, %notzero 667 ret <2 x i1> %r 668} 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]], 1 674; CHECK-NEXT: ret i1 [[R]] 675; 676 %dec = add i8 %x, -1 677 %and = and i8 %dec, %x 678 %cmp = icmp eq i8 %and, 0 679 %notzero = icmp ne i8 %x, 0 680 %r = and i1 %cmp, %notzero 681 ret i1 %r 682} 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]], 1 688; CHECK-NEXT: ret i1 [[R]] 689; 690 %dec = add i8 %x, -1 691 %and = and i8 %dec, %x 692 %cmp = icmp eq i8 %and, 0 693 %notzero = icmp ne i8 %x, 0 694 %r = select i1 %cmp, i1 %notzero, i1 false 695 ret i1 %r 696} 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, %x 706 %cmp = icmp eq <2 x i8> %and, zeroinitializer 707 %notzero = icmp ne <2 x i8> %x, zeroinitializer 708 %r = and <2 x i1> %notzero, %cmp 709 ret <2 x i1> %r 710} 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]], 1 716; CHECK-NEXT: ret i1 [[R]] 717; 718 %neg = sub i32 0, %x 719 %and = and i32 %neg, %x 720 %cmp = icmp ne i32 %and, %x 721 %iszero = icmp eq i32 %x, 0 722 %r = or i1 %cmp, %iszero 723 ret i1 %r 724} 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]], 1 730; CHECK-NEXT: ret i1 [[R]] 731; 732 %neg = sub i32 0, %x 733 %and = and i32 %neg, %x 734 %cmp = icmp ne i32 %and, %x 735 %iszero = icmp eq i32 %x, 0 736 %r = select i1 %cmp, i1 true, i1 %iszero 737 ret i1 %r 738} 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, %x 747 %and = and <2 x i32> %neg, %x 748 %cmp = icmp ne <2 x i32> %and, %x 749 %iszero = icmp eq <2 x i32> %x, zeroinitializer 750 %r = or <2 x i1> %iszero, %cmp 751 ret <2 x i1> %r 752} 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]], 1 758; CHECK-NEXT: ret i1 [[R]] 759; 760 %dec = add i8 %x, -1 761 %and = and i8 %dec, %x 762 %cmp = icmp ne i8 %and, 0 763 %iszero = icmp eq i8 %x, 0 764 %r = or i1 %iszero, %cmp 765 ret i1 %r 766} 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]], 1 772; CHECK-NEXT: ret i1 [[R]] 773; 774 %dec = add i8 %x, -1 775 %and = and i8 %dec, %x 776 %cmp = icmp ne i8 %and, 0 777 %iszero = icmp eq i8 %x, 0 778 %r = select i1 %iszero, i1 true, i1 %cmp 779 ret i1 %r 780} 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, %x 790 %cmp = icmp ne <2 x i8> %and, zeroinitializer 791 %iszero = icmp eq <2 x i8> %x, zeroinitializer 792 %r = or <2 x i1> %cmp, %iszero 793 ret <2 x i1> %r 794} 795 796; (ctpop(X) == 1) || (X == 0) --> ctpop(X) u< 2 797 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]], 2 802; CHECK-NEXT: ret i1 [[R]] 803; 804 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 805 %cmp = icmp eq i32 %t0, 1 806 %iszero = icmp eq i32 %x, 0 807 %r = or i1 %iszero, %cmp 808 ret i1 %r 809} 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]], 2 815; CHECK-NEXT: ret i1 [[R]] 816; 817 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 818 %cmp = icmp eq i32 %t0, 1 819 %iszero = icmp eq i32 %x, 0 820 %r = or i1 %cmp, %iszero 821 ret i1 %r 822} 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]], 2 828; CHECK-NEXT: ret i1 [[R]] 829; 830 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 831 %cmp = icmp eq i32 %t0, 1 832 %iszero = icmp eq i32 %x, 0 833 %r = select i1 %iszero, i1 true, i1 %cmp 834 ret i1 %r 835} 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, %cmp 847 ret <2 x i1> %r 848} 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]], 1 857; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 858; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 859; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 860; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2 861; 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, 1 866 call void @use_i1(i1 %cmp) 867 %iszero = icmp eq i32 %x, 0 868 call void @use_i1(i1 %iszero) 869 %r = or i1 %iszero, %cmp 870 ret i1 %r 871} 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]], 1 878; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 879; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 880; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 881; CHECK-NEXT: [[R:%.*]] = icmp samesign ult i32 [[T0]], 2 882; 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, 1 887 call void @use_i1(i1 %cmp) 888 %iszero = icmp eq i32 %x, 0 889 call void @use_i1(i1 %iszero) 890 %r = select i1 %iszero, i1 true, i1 %cmp 891 ret i1 %r 892} 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]], 2 900; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 901; 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, 2 906 %iszero = icmp eq i32 %x, 0 907 %r = or i1 %iszero, %cmp 908 ret i1 %r 909} 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]], 3 915; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 916; 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, 3 921 %iszero = icmp eq i32 %x, 0 922 %r = select i1 %iszero, i1 true, i1 %cmp 923 ret i1 %r 924} 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]], zeroinitializer 931; 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, %iszero 938 ret <2 x i1> %r 939} 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]], 1 947; CHECK-NEXT: ret i1 [[CMP]] 948; 949 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 950 %cmp = icmp ne i32 %t0, 1 951 %iszero = icmp eq i32 %x, 0 952 %r = or i1 %iszero, %cmp 953 ret i1 %r 954} 955 956define i1 @is_pow2or0_ctpop_wrong_pred2(i32 %x) { 957; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2( 958; CHECK-NEXT: ret i1 true 959; 960 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 961 %cmp = icmp ne i32 %t0, 1 962 %iszero = icmp ne i32 %x, 0 963 %r = or i1 %iszero, %cmp 964 ret i1 %r 965} 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 true 970; 971 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 972 %cmp = icmp ne i32 %t0, 1 973 %iszero = icmp ne i32 %x, 0 974 %r = select i1 %iszero, i1 true, i1 %cmp 975 ret i1 %r 976} 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> zeroinitializer 981; 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, %iszero 986 ret <2 x i1> %r 987} 988 989; (ctpop(X) != 1) && (X != 0) --> ctpop(X) u> 1 990 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]], 1 995; CHECK-NEXT: ret i1 [[R]] 996; 997 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 998 %cmp = icmp ne i32 %t0, 1 999 %notzero = icmp ne i32 %x, 0 1000 %r = and i1 %notzero, %cmp 1001 ret i1 %r 1002} 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]], 1 1008; CHECK-NEXT: ret i1 [[R]] 1009; 1010 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1011 %cmp = icmp ne i32 %t0, 1 1012 %notzero = icmp ne i32 %x, 0 1013 %r = and i1 %cmp, %notzero 1014 ret i1 %r 1015} 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]], 1 1021; CHECK-NEXT: ret i1 [[R]] 1022; 1023 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1024 %cmp = icmp ne i32 %t0, 1 1025 %notzero = icmp ne i32 %x, 0 1026 %r = select i1 %notzero, i1 %cmp, i1 false 1027 ret i1 %r 1028} 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, %cmp 1040 ret <2 x i1> %r 1041} 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]], 1 1050; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 1051; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1052; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 1053; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 1 1054; 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, 1 1059 call void @use_i1(i1 %cmp) 1060 %notzero = icmp ne i32 %x, 0 1061 call void @use_i1(i1 %notzero) 1062 %r = and i1 %notzero, %cmp 1063 ret i1 %r 1064} 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]], 1 1071; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 1072; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1073; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 1074; CHECK-NEXT: [[R:%.*]] = icmp samesign ugt i32 [[T0]], 1 1075; 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, 1 1080 call void @use_i1(i1 %cmp) 1081 %notzero = icmp ne i32 %x, 0 1082 call void @use_i1(i1 %notzero) 1083 %r = select i1 %notzero, i1 %cmp, i1 false 1084 ret i1 %r 1085} 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]], 4 1093; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1094; 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, 4 1099 %notzero = icmp ne i32 %x, 0 1100 %r = and i1 %notzero, %cmp 1101 ret i1 %r 1102} 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]], 5 1108; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1109; CHECK-NEXT: [[R:%.*]] = select i1 [[NOTZERO]], i1 [[CMP]], i1 false 1110; CHECK-NEXT: ret i1 [[R]] 1111; 1112 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1113 %cmp = icmp ne i32 %t0, 5 1114 %notzero = icmp ne i32 %x, 0 1115 %r = select i1 %notzero, i1 %cmp, i1 false 1116 ret i1 %r 1117} 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]], zeroinitializer 1124; 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, %notzero 1131 ret <2 x i1> %r 1132} 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]], 1 1140; CHECK-NEXT: ret i1 [[CMP]] 1141; 1142 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1143 %cmp = icmp eq i32 %t0, 1 1144 %notzero = icmp ne i32 %x, 0 1145 %r = and i1 %notzero, %cmp 1146 ret i1 %r 1147} 1148 1149define i1 @isnot_pow2nor0_ctpop_wrong_pred2(i32 %x) { 1150; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2( 1151; CHECK-NEXT: ret i1 false 1152; 1153 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1154 %cmp = icmp eq i32 %t0, 1 1155 %notzero = icmp eq i32 %x, 0 1156 %r = and i1 %notzero, %cmp 1157 ret i1 %r 1158} 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 false 1163; 1164 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1165 %cmp = icmp eq i32 %t0, 1 1166 %notzero = icmp eq i32 %x, 0 1167 %r = select i1 %notzero, i1 %cmp, i1 false 1168 ret i1 %r 1169} 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, %notzero 1179 ret <2 x i1> %r 1180} 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, %x 1190 %x_and_nx = and i32 %x, %nx 1191 %r = icmp sge i32 %x_and_nx, %x 1192 ret i1 %r 1193} 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]], -1 1199; 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, %yy 1204 %xm1 = add i32 %x, -1 1205 %y = xor i32 %x, %xm1 1206 %r = icmp uge i32 %x, %y 1207 ret i1 %r 1208} 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]], 1 1214; CHECK-NEXT: ret i1 [[R]] 1215; 1216 %xm1 = add i32 %x, -1 1217 %y = xor i32 %x, %xm1 1218 %r = icmp ult i32 %y, %x 1219 ret i1 %r 1220} 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]], 1 1227; CHECK-NEXT: ret i1 [[R]] 1228; 1229 %x = or i32 %xx, %yy 1230 %xm1 = add i32 %x, -1 1231 %y = xor i32 %x, %xm1 1232 %r = icmp ugt i32 %x, %y 1233 ret i1 %r 1234} 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:%.*]], -1 1239; 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, -1 1244 %y = xor i32 %x, %xm1 1245 %r = icmp ule i32 %y, %x 1246 ret i1 %r 1247} 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:%.*]], -1 1254; 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, -1 1260 %y = xor i32 %x, %xm1 1261 call void @use.i32(i32 %y) 1262 %r = icmp ult i32 %y, %x 1263 ret i1 %r 1264} 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:%.*]], -1 1269; 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, -1 1274 %y = xor i32 %x, %xm1 1275 %r = icmp ult i32 %y, %x 1276 ret i1 %r 1277} 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:%.*]], -1 1283; 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, -1 1288 %y = xor i32 %z, %xm1 1289 %r = icmp ult i32 %y, %x 1290 ret i1 %r 1291} 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:%.*]], -1 1297; 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, -1 1302 %y = xor i32 %x, %xm1 1303 %r = icmp uge i32 %y, %z 1304 ret i1 %r 1305} 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]], 2 1312; CHECK-NEXT: ret i1 [[R]] 1313; 1314 %x = or i8 %xx, %yy 1315 %xm1 = add i8 %x, -1 1316 %y = xor i8 %x, %xm1 1317 %r = icmp ule i8 %x, %y 1318 ret i1 %r 1319} 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]], -1 1326; 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, %yy 1331 %xm1 = add i8 %x, -1 1332 %y = xor i8 %x, %xm1 1333 %r = icmp ule i8 %y, %x 1334 ret i1 %r 1335} 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]], 2 1343; CHECK-NEXT: ret i1 [[R]] 1344; 1345 %x = or i8 %xx, %yy 1346 %xm1 = add i8 %x, -1 1347 %y = xor i8 %x, %xm1 1348 %r = icmp uge i8 %y, %x 1349 ret i1 %r 1350} 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]], -1 1357; 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, %yy 1362 %xm1 = add i8 %x, -1 1363 %y = xor i8 %x, %xm1 1364 %r = icmp uge i8 %x, %y 1365 ret i1 %r 1366} 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]], 1 1373; CHECK-NEXT: ret i1 [[R]] 1374; 1375 %x = or i8 %xx, %yy 1376 %xm1 = add i8 %x, -1 1377 %y = xor i8 %x, %xm1 1378 %r = icmp ugt i8 %x, %y 1379 ret i1 %r 1380} 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]], -1 1387; 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, %yy 1392 %xm1 = add i8 %x, -1 1393 %y = xor i8 %x, %xm1 1394 %r = icmp ugt i8 %y, %x 1395 ret i1 %r 1396} 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]], 1 1404; CHECK-NEXT: ret i1 [[R]] 1405; 1406 %x = or i8 %xx, %yy 1407 %xm1 = add i8 %x, -1 1408 %y = xor i8 %x, %xm1 1409 %r = icmp ult i8 %y, %x 1410 ret i1 %r 1411} 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]], -1 1418; 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, %yy 1423 %xm1 = add i8 %x, -1 1424 %y = xor i8 %x, %xm1 1425 %r = icmp ult i8 %x, %y 1426 ret i1 %r 1427} 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:%.*]], -65 1433; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0 1434; CHECK-NEXT: ret i1 [[R]] 1435; 1436 %x = or i32 %xin, 64 1437 %cnt = call i32 @llvm.ctpop.i32(i32 %x) 1438 %r = icmp eq i32 %cnt, 1 1439 ret i1 %r 1440} 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:%.*]], 64 1445; 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]], 1 1448; CHECK-NEXT: ret i1 [[R]] 1449; 1450 %x = or i32 %xin, 64 1451 %cnt = call i32 @llvm.ctpop.i32(i32 %x) 1452 call void @use.i32(i32 %cnt) 1453 %r = icmp eq i32 %cnt, 1 1454 ret i1 %r 1455} 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:%.*]], 1 1460; CHECK-NEXT: ret i1 [[R]] 1461; 1462 %x = or i32 %xin, 1 1463 %cnt = call i32 @llvm.ctpop.i32(i32 %x) 1464 %r = icmp ne i32 %cnt, 1 1465 ret i1 %r 1466} 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:%.*]], 1 1471; CHECK-NEXT: [[CNT:%.*]] = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 [[X]]) 1472; CHECK-NEXT: [[R:%.*]] = icmp ne i32 [[CNT]], 2 1473; CHECK-NEXT: ret i1 [[R]] 1474; 1475 %x = or i32 %xin, 1 1476 %cnt = call i32 @llvm.ctpop.i32(i32 %x) 1477 %r = icmp ne i32 %cnt, 2 1478 ret i1 %r 1479} 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:%.*]], 2147483647 1484; CHECK-NEXT: [[R:%.*]] = icmp eq i32 [[TMP1]], 0 1485; CHECK-NEXT: ret i1 [[R]] 1486; 1487 %x = or i32 %xin, 2147483648 1488 %cnt = call i32 @llvm.ctpop.i32(i32 %x) 1489 %r = icmp ult i32 %cnt, 2 1490 ret i1 %r 1491} 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]], zeroinitializer 1497; 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> %r 1503} 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> %r 1516} 1517 1518; Make sure that range attributes on return values are dropped after merging these two icmps 1519 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]], 1 1525; CHECK-NEXT: ret i1 [[SEL]] 1526; 1527entry: 1528 %cmp1 = icmp ne i32 %x, 0 1529 %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x) 1530 %cmp2 = icmp ult i32 %popcnt, 2 1531 %sel = select i1 %cmp1, i1 %cmp2, i1 false 1532 ret i1 %sel 1533} 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]], 1 1540; CHECK-NEXT: ret i1 [[SEL]] 1541; 1542entry: 1543 %cmp1 = icmp eq i32 %x, 0 1544 %popcnt = call range(i32 1, 33) i32 @llvm.ctpop.i32(i32 %x) 1545 %cmp2 = icmp ugt i32 %popcnt, 1 1546 %sel = select i1 %cmp1, i1 true, i1 %cmp2 1547 ret i1 %sel 1548} 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]], 2 1554; 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, 1 1558 %notzero = icmp eq i32 %x, 0 1559 %res = select i1 %notzero, i1 true, i1 %cmp 1560 ret i1 %res 1561} 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]], 1 1567; 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, 1 1571 %notzero = icmp ne i32 %x, 0 1572 %res = select i1 %notzero, i1 %cmp, i1 false 1573 ret i1 %res 1574} 1575