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 i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0:![0-9]+]] 7; CHECK-NEXT: [[CMP:%.*]] = icmp 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 <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) 19; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i32> [[TMP1]], <i32 2, 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 i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1:![0-9]+]] 31; CHECK-NEXT: [[CMP:%.*]] = icmp 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 <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 43; CHECK-NEXT: [[CMP:%.*]] = icmp ult <2 x i8> [[TMP1]], <i8 2, 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 i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 55; CHECK-NEXT: [[CMP:%.*]] = icmp 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 <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) 67; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i32> [[TMP1]], <i32 1, 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 i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]] 79; CHECK-NEXT: [[CMP:%.*]] = icmp 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 <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 91; CHECK-NEXT: [[CMP:%.*]] = icmp ugt <2 x i8> [[TMP1]], <i8 1, 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 i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2:![0-9]+]] 104; CHECK-NEXT: [[CMP:%.*]] = icmp 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 i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2]] 120; CHECK-NEXT: [[CMP:%.*]] = icmp 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 i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG2]] 134; CHECK-NEXT: [[CMP:%.*]] = icmp 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 i32 @llvm.ctpop.i32(i32 [[X]]), !range [[RNG0]] 151; CHECK-NEXT: [[CMP:%.*]] = icmp 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 [[NEG]], [[X]] 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>) 178 179; (X != 0) && (ctpop(X) u< 2) --> ctpop(X) == 1 180 181define i1 @is_pow2_ctpop(i32 %x) { 182; CHECK-LABEL: @is_pow2_ctpop( 183; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 184; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1 185; CHECK-NEXT: ret i1 [[TMP1]] 186; 187 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 188 %cmp = icmp ult i32 %t0, 2 189 %notzero = icmp ne i32 %x, 0 190 %r = and i1 %notzero, %cmp 191 ret i1 %r 192} 193 194define i1 @is_pow2_ctpop_logical(i32 %x) { 195; CHECK-LABEL: @is_pow2_ctpop_logical( 196; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 197; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1 198; CHECK-NEXT: ret i1 [[TMP1]] 199; 200 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 201 %cmp = icmp ult i32 %t0, 2 202 %notzero = icmp ne i32 %x, 0 203 %r = select i1 %notzero, i1 %cmp, i1 false 204 ret i1 %r 205} 206 207; Extra uses don't change the fold. 208declare void @use_i1(i1) 209 210define i1 @is_pow2_ctpop_extra_uses(i32 %x) { 211; CHECK-LABEL: @is_pow2_ctpop_extra_uses( 212; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 213; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 214; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 215; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 216; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 217; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1 218; CHECK-NEXT: ret i1 [[TMP1]] 219; 220 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 221 %cmp = icmp ult i32 %t0, 2 222 call void @use_i1(i1 %cmp) 223 %notzero = icmp ne i32 %x, 0 224 call void @use_i1(i1 %notzero) 225 %r = and i1 %notzero, %cmp 226 ret i1 %r 227} 228 229define i1 @is_pow2_ctpop_extra_uses_logical(i32 %x) { 230; CHECK-LABEL: @is_pow2_ctpop_extra_uses_logical( 231; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 232; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 233; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 234; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 235; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 236; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[T0]], 1 237; CHECK-NEXT: ret i1 [[TMP1]] 238; 239 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 240 %cmp = icmp ult i32 %t0, 2 241 call void @use_i1(i1 %cmp) 242 %notzero = icmp ne i32 %x, 0 243 call void @use_i1(i1 %notzero) 244 %r = select i1 %notzero, i1 %cmp, i1 false 245 ret i1 %r 246} 247 248; Test vector type and commuted 'and' operands. 249 250define <2 x i1> @is_pow2_ctpop_commute_vec(<2 x i8> %x) { 251; CHECK-LABEL: @is_pow2_ctpop_commute_vec( 252; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 253; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1> 254; CHECK-NEXT: ret <2 x i1> [[TMP1]] 255; 256 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 257 %cmp = icmp ult <2 x i8> %t0, <i8 2, i8 2> 258 %notzero = icmp ne <2 x i8> %x, zeroinitializer 259 %r = and <2 x i1> %cmp, %notzero 260 ret <2 x i1> %r 261} 262 263; Negative test - wrong constant. 264 265define i1 @is_pow2_ctpop_wrong_cmp_op1(i32 %x) { 266; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1( 267; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 268; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3 269; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 270; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 271; CHECK-NEXT: ret i1 [[R]] 272; 273 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 274 %cmp = icmp ult i32 %t0, 3 275 %notzero = icmp ne i32 %x, 0 276 %r = and i1 %notzero, %cmp 277 ret i1 %r 278} 279 280define i1 @is_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) { 281; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op1_logical( 282; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 283; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 3 284; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 285; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 286; CHECK-NEXT: ret i1 [[R]] 287; 288 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 289 %cmp = icmp ult i32 %t0, 3 290 %notzero = icmp ne i32 %x, 0 291 %r = select i1 %notzero, i1 %cmp, i1 false 292 ret i1 %r 293} 294 295; Negative test - wrong constant. 296 297define i1 @is_pow2_ctpop_wrong_cmp_op2(i32 %x) { 298; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2( 299; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 300; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 301; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1 302; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 303; CHECK-NEXT: ret i1 [[R]] 304; 305 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 306 %cmp = icmp ult i32 %t0, 2 307 %notzero = icmp ne i32 %x, 1 308 %r = and i1 %notzero, %cmp 309 ret i1 %r 310} 311 312define i1 @is_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) { 313; CHECK-LABEL: @is_pow2_ctpop_wrong_cmp_op2_logical( 314; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 315; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 316; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 1 317; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 318; CHECK-NEXT: ret i1 [[R]] 319; 320 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 321 %cmp = icmp ult i32 %t0, 2 322 %notzero = icmp ne i32 %x, 1 323 %r = select i1 %notzero, i1 %cmp, i1 false 324 ret i1 %r 325} 326 327; Negative test - wrong predicate. 328 329define i1 @is_pow2_ctpop_wrong_pred1(i32 %x) { 330; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1( 331; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 332; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2 333; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 334; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 335; CHECK-NEXT: ret i1 [[R]] 336; 337 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 338 %cmp = icmp ugt i32 %t0, 2 339 %notzero = icmp ne i32 %x, 0 340 %r = and i1 %notzero, %cmp 341 ret i1 %r 342} 343 344define i1 @is_pow2_ctpop_wrong_pred1_logical(i32 %x) { 345; CHECK-LABEL: @is_pow2_ctpop_wrong_pred1_logical( 346; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 347; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2 348; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 349; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 350; CHECK-NEXT: ret i1 [[R]] 351; 352 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 353 %cmp = icmp ugt i32 %t0, 2 354 %notzero = icmp ne i32 %x, 0 355 %r = select i1 %notzero, i1 %cmp, i1 false 356 ret i1 %r 357} 358 359; Negative test - wrong predicate. 360 361define i1 @is_pow2_ctpop_wrong_pred2(i32 %x) { 362; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2( 363; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 364; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 365; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0 366; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]] 367; CHECK-NEXT: ret i1 [[R]] 368; 369 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 370 %cmp = icmp ult i32 %t0, 2 371 %cmp2 = icmp sgt i32 %x, 0 372 %r = and i1 %cmp2, %cmp 373 ret i1 %r 374} 375 376define i1 @is_pow2_ctpop_wrong_pred2_logical(i32 %x) { 377; CHECK-LABEL: @is_pow2_ctpop_wrong_pred2_logical( 378; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 379; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[T0]], 2 380; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i32 [[X]], 0 381; CHECK-NEXT: [[R:%.*]] = and i1 [[CMP2]], [[CMP]] 382; CHECK-NEXT: ret i1 [[R]] 383; 384 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 385 %cmp = icmp ult i32 %t0, 2 386 %cmp2 = icmp sgt i32 %x, 0 387 %r = select i1 %cmp2, i1 %cmp, i1 false 388 ret i1 %r 389} 390 391; (X == 0) || (ctpop(X) u> 1) --> ctpop(X) != 1 392 393define i1 @isnot_pow2_ctpop(i32 %x) { 394; CHECK-LABEL: @isnot_pow2_ctpop( 395; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 396; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1 397; CHECK-NEXT: ret i1 [[TMP1]] 398; 399 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 400 %cmp = icmp ugt i32 %t0, 1 401 %iszero = icmp eq i32 %x, 0 402 %r = or i1 %iszero, %cmp 403 ret i1 %r 404} 405 406define i1 @isnot_pow2_ctpop_logical(i32 %x) { 407; CHECK-LABEL: @isnot_pow2_ctpop_logical( 408; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 409; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1 410; CHECK-NEXT: ret i1 [[TMP1]] 411; 412 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 413 %cmp = icmp ugt i32 %t0, 1 414 %iszero = icmp eq i32 %x, 0 415 %r = select i1 %iszero, i1 true, i1 %cmp 416 ret i1 %r 417} 418 419; Extra uses don't change the fold. 420 421define i1 @isnot_pow2_ctpop_extra_uses(i32 %x) { 422; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses( 423; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 424; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 425; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 426; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 427; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 428; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1 429; CHECK-NEXT: ret i1 [[TMP1]] 430; 431 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 432 %cmp = icmp ugt i32 %t0, 1 433 call void @use_i1(i1 %cmp) 434 %iszero = icmp eq i32 %x, 0 435 call void @use_i1(i1 %iszero) 436 %r = or i1 %iszero, %cmp 437 ret i1 %r 438} 439 440define i1 @isnot_pow2_ctpop_extra_uses_logical(i32 %x) { 441; CHECK-LABEL: @isnot_pow2_ctpop_extra_uses_logical( 442; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 443; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 444; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 445; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 446; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 447; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[T0]], 1 448; CHECK-NEXT: ret i1 [[TMP1]] 449; 450 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 451 %cmp = icmp ugt i32 %t0, 1 452 call void @use_i1(i1 %cmp) 453 %iszero = icmp eq i32 %x, 0 454 call void @use_i1(i1 %iszero) 455 %r = select i1 %iszero, i1 true, i1 %cmp 456 ret i1 %r 457} 458 459; Test vector type and commuted 'or' operands. 460 461define <2 x i1> @isnot_pow2_ctpop_commute_vec(<2 x i8> %x) { 462; CHECK-LABEL: @isnot_pow2_ctpop_commute_vec( 463; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 464; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1> 465; CHECK-NEXT: ret <2 x i1> [[TMP1]] 466; 467 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 468 %cmp = icmp ugt <2 x i8> %t0, <i8 1, i8 1> 469 %iszero = icmp eq <2 x i8> %x, zeroinitializer 470 %r = or <2 x i1> %cmp, %iszero 471 ret <2 x i1> %r 472} 473 474; Negative test - wrong constant. 475 476define i1 @isnot_pow2_ctpop_wrong_cmp_op1(i32 %x) { 477; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1( 478; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 479; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2 480; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 481; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 482; CHECK-NEXT: ret i1 [[R]] 483; 484 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 485 %cmp = icmp ugt i32 %t0, 2 486 %iszero = icmp eq i32 %x, 0 487 %r = or i1 %iszero, %cmp 488 ret i1 %r 489} 490 491define i1 @isnot_pow2_ctpop_wrong_cmp_op1_logical(i32 %x) { 492; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op1_logical( 493; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 494; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 2 495; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 496; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 497; CHECK-NEXT: ret i1 [[R]] 498; 499 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 500 %cmp = icmp ugt i32 %t0, 2 501 %iszero = icmp eq i32 %x, 0 502 %r = select i1 %iszero, i1 true, i1 %cmp 503 ret i1 %r 504} 505 506; Negative test - wrong constant. 507 508define i1 @isnot_pow2_ctpop_wrong_cmp_op2(i32 %x) { 509; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2( 510; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 511; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 512; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1 513; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 514; CHECK-NEXT: ret i1 [[R]] 515; 516 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 517 %cmp = icmp ugt i32 %t0, 1 518 %iszero = icmp eq i32 %x, 1 519 %r = or i1 %iszero, %cmp 520 ret i1 %r 521} 522 523define i1 @isnot_pow2_ctpop_wrong_cmp_op2_logical(i32 %x) { 524; CHECK-LABEL: @isnot_pow2_ctpop_wrong_cmp_op2_logical( 525; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 526; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 527; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 1 528; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 529; CHECK-NEXT: ret i1 [[R]] 530; 531 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 532 %cmp = icmp ugt i32 %t0, 1 533 %iszero = icmp eq i32 %x, 1 534 %r = select i1 %iszero, i1 true, i1 %cmp 535 ret i1 %r 536} 537 538; Negative test - wrong predicate. 539 540define i1 @isnot_pow2_ctpop_wrong_pred2(i32 %x) { 541; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2( 542; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 543; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 544; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0 545; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]] 546; CHECK-NEXT: ret i1 [[R]] 547; 548 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 549 %cmp = icmp ugt i32 %t0, 1 550 %cmp2 = icmp slt i32 %x, 0 551 %r = or i1 %cmp2, %cmp 552 ret i1 %r 553} 554 555define i1 @isnot_pow2_ctpop_wrong_pred2_logical(i32 %x) { 556; CHECK-LABEL: @isnot_pow2_ctpop_wrong_pred2_logical( 557; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 558; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[T0]], 1 559; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 [[X]], 0 560; CHECK-NEXT: [[R:%.*]] = or i1 [[CMP2]], [[CMP]] 561; CHECK-NEXT: ret i1 [[R]] 562; 563 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 564 %cmp = icmp ugt i32 %t0, 1 565 %cmp2 = icmp slt i32 %x, 0 566 %r = select i1 %cmp2, i1 true, i1 %cmp 567 ret i1 %r 568} 569 570define i1 @is_pow2_negate_op(i32 %x) { 571; CHECK-LABEL: @is_pow2_negate_op( 572; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 573; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 574; CHECK-NEXT: ret i1 [[TMP2]] 575; 576 %neg = sub i32 0, %x 577 %and = and i32 %neg, %x 578 %cmp = icmp eq i32 %and, %x 579 %notzero = icmp ne i32 %x, 0 580 %r = and i1 %notzero, %cmp 581 ret i1 %r 582} 583 584define i1 @is_pow2_negate_op_logical(i32 %x) { 585; CHECK-LABEL: @is_pow2_negate_op_logical( 586; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 587; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 1 588; CHECK-NEXT: ret i1 [[TMP2]] 589; 590 %neg = sub i32 0, %x 591 %and = and i32 %neg, %x 592 %cmp = icmp eq i32 %and, %x 593 %notzero = icmp ne i32 %x, 0 594 %r = select i1 %notzero, i1 %cmp, i1 false 595 ret i1 %r 596} 597 598define <2 x i1> @is_pow2_negate_op_vec(<2 x i32> %x) { 599; CHECK-LABEL: @is_pow2_negate_op_vec( 600; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) 601; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i32> [[TMP1]], <i32 1, i32 1> 602; CHECK-NEXT: ret <2 x i1> [[TMP2]] 603; 604 %neg = sub <2 x i32> zeroinitializer, %x 605 %and = and <2 x i32> %neg, %x 606 %cmp = icmp eq <2 x i32> %and, %x 607 %notzero = icmp ne <2 x i32> %x, zeroinitializer 608 %r = and <2 x i1> %cmp, %notzero 609 ret <2 x i1> %r 610} 611 612define i1 @is_pow2_decrement_op(i8 %x) { 613; CHECK-LABEL: @is_pow2_decrement_op( 614; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]] 615; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1 616; CHECK-NEXT: ret i1 [[TMP2]] 617; 618 %dec = add i8 %x, -1 619 %and = and i8 %dec, %x 620 %cmp = icmp eq i8 %and, 0 621 %notzero = icmp ne i8 %x, 0 622 %r = and i1 %cmp, %notzero 623 ret i1 %r 624} 625 626define i1 @is_pow2_decrement_op_logical(i8 %x) { 627; CHECK-LABEL: @is_pow2_decrement_op_logical( 628; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]] 629; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i8 [[TMP1]], 1 630; CHECK-NEXT: ret i1 [[TMP2]] 631; 632 %dec = add i8 %x, -1 633 %and = and i8 %dec, %x 634 %cmp = icmp eq i8 %and, 0 635 %notzero = icmp ne i8 %x, 0 636 %r = select i1 %cmp, i1 %notzero, i1 false 637 ret i1 %r 638} 639 640define <2 x i1> @is_pow2_decrement_op_vec(<2 x i8> %x) { 641; CHECK-LABEL: @is_pow2_decrement_op_vec( 642; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 643; CHECK-NEXT: [[TMP2:%.*]] = icmp eq <2 x i8> [[TMP1]], <i8 1, i8 1> 644; CHECK-NEXT: ret <2 x i1> [[TMP2]] 645; 646 %dec = add <2 x i8> %x, <i8 -1, i8 -1> 647 %and = and <2 x i8> %dec, %x 648 %cmp = icmp eq <2 x i8> %and, zeroinitializer 649 %notzero = icmp ne <2 x i8> %x, zeroinitializer 650 %r = and <2 x i1> %notzero, %cmp 651 ret <2 x i1> %r 652} 653 654define i1 @isnot_pow2_negate_op(i32 %x) { 655; CHECK-LABEL: @isnot_pow2_negate_op( 656; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 657; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 1 658; CHECK-NEXT: ret i1 [[TMP2]] 659; 660 %neg = sub i32 0, %x 661 %and = and i32 %neg, %x 662 %cmp = icmp ne i32 %and, %x 663 %iszero = icmp eq i32 %x, 0 664 %r = or i1 %cmp, %iszero 665 ret i1 %r 666} 667 668define i1 @isnot_pow2_negate_op_logical(i32 %x) { 669; CHECK-LABEL: @isnot_pow2_negate_op_logical( 670; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 671; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i32 [[TMP1]], 1 672; CHECK-NEXT: ret i1 [[TMP2]] 673; 674 %neg = sub i32 0, %x 675 %and = and i32 %neg, %x 676 %cmp = icmp ne i32 %and, %x 677 %iszero = icmp eq i32 %x, 0 678 %r = select i1 %cmp, i1 true, i1 %iszero 679 ret i1 %r 680} 681 682define <2 x i1> @isnot_pow2_negate_op_vec(<2 x i32> %x) { 683; CHECK-LABEL: @isnot_pow2_negate_op_vec( 684; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i32> @llvm.ctpop.v2i32(<2 x i32> [[X:%.*]]) 685; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i32> [[TMP1]], <i32 1, i32 1> 686; CHECK-NEXT: ret <2 x i1> [[TMP2]] 687; 688 %neg = sub <2 x i32> zeroinitializer, %x 689 %and = and <2 x i32> %neg, %x 690 %cmp = icmp ne <2 x i32> %and, %x 691 %iszero = icmp eq <2 x i32> %x, zeroinitializer 692 %r = or <2 x i1> %iszero, %cmp 693 ret <2 x i1> %r 694} 695 696define i1 @isnot_pow2_decrement_op(i8 %x) { 697; CHECK-LABEL: @isnot_pow2_decrement_op( 698; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]] 699; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 1 700; CHECK-NEXT: ret i1 [[TMP2]] 701; 702 %dec = add i8 %x, -1 703 %and = and i8 %dec, %x 704 %cmp = icmp ne i8 %and, 0 705 %iszero = icmp eq i8 %x, 0 706 %r = or i1 %iszero, %cmp 707 ret i1 %r 708} 709 710define i1 @isnot_pow2_decrement_op_logical(i8 %x) { 711; CHECK-LABEL: @isnot_pow2_decrement_op_logical( 712; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.ctpop.i8(i8 [[X:%.*]]), !range [[RNG1]] 713; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 1 714; CHECK-NEXT: ret i1 [[TMP2]] 715; 716 %dec = add i8 %x, -1 717 %and = and i8 %dec, %x 718 %cmp = icmp ne i8 %and, 0 719 %iszero = icmp eq i8 %x, 0 720 %r = select i1 %iszero, i1 true, i1 %cmp 721 ret i1 %r 722} 723 724define <2 x i1> @isnot_pow2_decrement_op_vec(<2 x i8> %x) { 725; CHECK-LABEL: @isnot_pow2_decrement_op_vec( 726; CHECK-NEXT: [[TMP1:%.*]] = call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 727; CHECK-NEXT: [[TMP2:%.*]] = icmp ne <2 x i8> [[TMP1]], <i8 1, i8 1> 728; CHECK-NEXT: ret <2 x i1> [[TMP2]] 729; 730 %dec = add <2 x i8> %x, <i8 -1, i8 -1> 731 %and = and <2 x i8> %dec, %x 732 %cmp = icmp ne <2 x i8> %and, zeroinitializer 733 %iszero = icmp eq <2 x i8> %x, zeroinitializer 734 %r = or <2 x i1> %cmp, %iszero 735 ret <2 x i1> %r 736} 737 738; (ctpop(X) == 1) || (X == 0) --> ctpop(X) u< 2 739 740define i1 @is_pow2or0_ctpop(i32 %x) { 741; CHECK-LABEL: @is_pow2or0_ctpop( 742; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 743; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[T0]], 2 744; CHECK-NEXT: ret i1 [[TMP1]] 745; 746 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 747 %cmp = icmp eq i32 %t0, 1 748 %iszero = icmp eq i32 %x, 0 749 %r = or i1 %iszero, %cmp 750 ret i1 %r 751} 752 753define i1 @is_pow2or0_ctpop_swap_cmp(i32 %x) { 754; CHECK-LABEL: @is_pow2or0_ctpop_swap_cmp( 755; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 756; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[T0]], 2 757; CHECK-NEXT: ret i1 [[TMP1]] 758; 759 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 760 %cmp = icmp eq i32 %t0, 1 761 %iszero = icmp eq i32 %x, 0 762 %r = or i1 %cmp, %iszero 763 ret i1 %r 764} 765 766define i1 @is_pow2or0_ctpop_logical(i32 %x) { 767; CHECK-LABEL: @is_pow2or0_ctpop_logical( 768; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 769; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[T0]], 2 770; CHECK-NEXT: ret i1 [[TMP1]] 771; 772 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 773 %cmp = icmp eq i32 %t0, 1 774 %iszero = icmp eq i32 %x, 0 775 %r = select i1 %iszero, i1 true, i1 %cmp 776 ret i1 %r 777} 778 779define <2 x i1> @is_pow2or0_ctpop_commute_vec(<2 x i8> %x) { 780; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec( 781; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 782; CHECK-NEXT: [[TMP1:%.*]] = icmp ult <2 x i8> [[T0]], <i8 2, i8 2> 783; CHECK-NEXT: ret <2 x i1> [[TMP1]] 784; 785 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 786 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1> 787 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0> 788 %r = or <2 x i1> %iszero, %cmp 789 ret <2 x i1> %r 790} 791 792; Extra uses don't change the fold. 793 794define i1 @is_pow2or0_ctpop_extra_uses(i32 %x) { 795; CHECK-LABEL: @is_pow2or0_ctpop_extra_uses( 796; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 797; CHECK-NEXT: call void @use(i32 [[T0]]) 798; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1 799; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 800; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 801; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 802; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[T0]], 2 803; CHECK-NEXT: ret i1 [[TMP1]] 804; 805 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 806 call void @use(i32 %t0) 807 %cmp = icmp eq i32 %t0, 1 808 call void @use_i1(i1 %cmp) 809 %iszero = icmp eq i32 %x, 0 810 call void @use_i1(i1 %iszero) 811 %r = or i1 %iszero, %cmp 812 ret i1 %r 813} 814 815define i1 @is_pow2or0_ctpop_logical_extra_uses(i32 %x) { 816; CHECK-LABEL: @is_pow2or0_ctpop_logical_extra_uses( 817; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 818; CHECK-NEXT: call void @use(i32 [[T0]]) 819; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1 820; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 821; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 822; CHECK-NEXT: call void @use_i1(i1 [[ISZERO]]) 823; CHECK-NEXT: [[TMP1:%.*]] = icmp ult i32 [[T0]], 2 824; CHECK-NEXT: ret i1 [[TMP1]] 825; 826 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 827 call void @use(i32 %t0) 828 %cmp = icmp eq i32 %t0, 1 829 call void @use_i1(i1 %cmp) 830 %iszero = icmp eq i32 %x, 0 831 call void @use_i1(i1 %iszero) 832 %r = select i1 %iszero, i1 true, i1 %cmp 833 ret i1 %r 834} 835 836; Negative test - wrong constant. 837 838define i1 @is_pow2or0_ctpop_wrong_cmp_op1(i32 %x) { 839; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1( 840; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 841; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 2 842; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 843; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 844; CHECK-NEXT: ret i1 [[R]] 845; 846 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 847 %cmp = icmp eq i32 %t0, 2 848 %iszero = icmp eq i32 %x, 0 849 %r = or i1 %iszero, %cmp 850 ret i1 %r 851} 852 853define i1 @is_pow2or0_ctpop_wrong_cmp_op1_logical(i32 %x) { 854; CHECK-LABEL: @is_pow2or0_ctpop_wrong_cmp_op1_logical( 855; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 856; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 3 857; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 858; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 859; CHECK-NEXT: ret i1 [[R]] 860; 861 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 862 %cmp = icmp eq i32 %t0, 3 863 %iszero = icmp eq i32 %x, 0 864 %r = select i1 %iszero, i1 true, i1 %cmp 865 ret i1 %r 866} 867 868define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) { 869; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_cmp_op1( 870; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 871; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 -1, i8 1> 872; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer 873; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[ISZERO]] 874; CHECK-NEXT: ret <2 x i1> [[R]] 875; 876 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 877 %cmp = icmp eq <2 x i8> %t0, <i8 -1, i8 1> 878 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0> 879 %r = or <2 x i1> %cmp, %iszero 880 ret <2 x i1> %r 881} 882 883; Negative test - wrong predicate. 884 885define i1 @is_pow2or0_ctpop_wrong_pred1(i32 %x) { 886; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred1( 887; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 888; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1 889; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq i32 [[X]], 0 890; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 891; CHECK-NEXT: ret i1 [[R]] 892; 893 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 894 %cmp = icmp ne i32 %t0, 1 895 %iszero = icmp eq i32 %x, 0 896 %r = or i1 %iszero, %cmp 897 ret i1 %r 898} 899 900define i1 @is_pow2or0_ctpop_wrong_pred2_logical(i32 %x) { 901; CHECK-LABEL: @is_pow2or0_ctpop_wrong_pred2_logical( 902; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 903; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1 904; CHECK-NEXT: [[ISZERO:%.*]] = icmp ne i32 [[X]], 0 905; CHECK-NEXT: [[R:%.*]] = or i1 [[ISZERO]], [[CMP]] 906; CHECK-NEXT: ret i1 [[R]] 907; 908 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 909 %cmp = icmp ne i32 %t0, 1 910 %iszero = icmp ne i32 %x, 0 911 %r = select i1 %iszero, i1 true, i1 %cmp 912 ret i1 %r 913} 914 915define <2 x i1> @is_pow2or0_ctpop_commute_vec_wrong_pred3(<2 x i8> %x) { 916; CHECK-LABEL: @is_pow2or0_ctpop_commute_vec_wrong_pred3( 917; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 918; CHECK-NEXT: [[CMP:%.*]] = icmp eq <2 x i8> [[T0]], <i8 1, i8 1> 919; CHECK-NEXT: [[ISZERO:%.*]] = icmp eq <2 x i8> [[X]], zeroinitializer 920; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[ISZERO]] 921; CHECK-NEXT: ret <2 x i1> [[R]] 922; 923 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 924 %cmp = icmp eq <2 x i8> %t0, <i8 1, i8 1> 925 %iszero = icmp eq <2 x i8> %x, <i8 0, i8 0> 926 %r = and <2 x i1> %cmp, %iszero 927 ret <2 x i1> %r 928} 929 930; (ctpop(X) != 1) && (X != 0) --> ctpop(X) u> 1 931 932define i1 @isnot_pow2nor0_ctpop(i32 %x) { 933; CHECK-LABEL: @isnot_pow2nor0_ctpop( 934; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 935; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[T0]], 1 936; CHECK-NEXT: ret i1 [[TMP1]] 937; 938 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 939 %cmp = icmp ne i32 %t0, 1 940 %notzero = icmp ne i32 %x, 0 941 %r = and i1 %notzero, %cmp 942 ret i1 %r 943} 944 945define i1 @isnot_pow2nor0_ctpop_swap_cmp(i32 %x) { 946; CHECK-LABEL: @isnot_pow2nor0_ctpop_swap_cmp( 947; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 948; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[T0]], 1 949; CHECK-NEXT: ret i1 [[TMP1]] 950; 951 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 952 %cmp = icmp ne i32 %t0, 1 953 %notzero = icmp ne i32 %x, 0 954 %r = and i1 %cmp, %notzero 955 ret i1 %r 956} 957 958define i1 @isnot_pow2nor0_ctpop_logical(i32 %x) { 959; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical( 960; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 961; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[T0]], 1 962; CHECK-NEXT: ret i1 [[TMP1]] 963; 964 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 965 %cmp = icmp ne i32 %t0, 1 966 %notzero = icmp ne i32 %x, 0 967 %r = select i1 %notzero, i1 %cmp, i1 false 968 ret i1 %r 969} 970 971define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec(<2 x i8> %x) { 972; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec( 973; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 974; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt <2 x i8> [[T0]], <i8 1, i8 1> 975; CHECK-NEXT: ret <2 x i1> [[TMP1]] 976; 977 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 978 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1> 979 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0> 980 %r = and <2 x i1> %notzero, %cmp 981 ret <2 x i1> %r 982} 983 984; Extra uses don't change the fold. 985 986define i1 @isnot_pow2nor0_ctpop_extra_uses(i32 %x) { 987; CHECK-LABEL: @isnot_pow2nor0_ctpop_extra_uses( 988; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 989; CHECK-NEXT: call void @use(i32 [[T0]]) 990; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1 991; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 992; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 993; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 994; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[T0]], 1 995; CHECK-NEXT: ret i1 [[TMP1]] 996; 997 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 998 call void @use(i32 %t0) 999 %cmp = icmp ne i32 %t0, 1 1000 call void @use_i1(i1 %cmp) 1001 %notzero = icmp ne i32 %x, 0 1002 call void @use_i1(i1 %notzero) 1003 %r = and i1 %notzero, %cmp 1004 ret i1 %r 1005} 1006 1007define i1 @isnot_pow2nor0_ctpop_logical_extra_uses(i32 %x) { 1008; CHECK-LABEL: @isnot_pow2nor0_ctpop_logical_extra_uses( 1009; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 1010; CHECK-NEXT: call void @use(i32 [[T0]]) 1011; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 1 1012; CHECK-NEXT: call void @use_i1(i1 [[CMP]]) 1013; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1014; CHECK-NEXT: call void @use_i1(i1 [[NOTZERO]]) 1015; CHECK-NEXT: [[TMP1:%.*]] = icmp ugt i32 [[T0]], 1 1016; CHECK-NEXT: ret i1 [[TMP1]] 1017; 1018 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1019 call void @use(i32 %t0) 1020 %cmp = icmp ne i32 %t0, 1 1021 call void @use_i1(i1 %cmp) 1022 %notzero = icmp ne i32 %x, 0 1023 call void @use_i1(i1 %notzero) 1024 %r = select i1 %notzero, i1 %cmp, i1 false 1025 ret i1 %r 1026} 1027 1028; Negative test - wrong constant. 1029 1030define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1(i32 %x) { 1031; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1( 1032; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 1033; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 4 1034; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1035; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 1036; CHECK-NEXT: ret i1 [[R]] 1037; 1038 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1039 %cmp = icmp ne i32 %t0, 4 1040 %notzero = icmp ne i32 %x, 0 1041 %r = and i1 %notzero, %cmp 1042 ret i1 %r 1043} 1044 1045define i1 @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical(i32 %x) { 1046; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_cmp_op1_logical( 1047; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 1048; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[T0]], 5 1049; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1050; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 1051; CHECK-NEXT: ret i1 [[R]] 1052; 1053 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1054 %cmp = icmp ne i32 %t0, 5 1055 %notzero = icmp ne i32 %x, 0 1056 %r = select i1 %notzero, i1 %cmp, i1 false 1057 ret i1 %r 1058} 1059 1060define <2 x i1> @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1(<2 x i8> %x) { 1061; CHECK-LABEL: @isnot_pow2nor0_ctpop_commute_vec_wrong_cmp_op1( 1062; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 1063; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 0, i8 -1> 1064; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer 1065; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[CMP]], [[NOTZERO]] 1066; CHECK-NEXT: ret <2 x i1> [[R]] 1067; 1068 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 1069 %cmp = icmp ne <2 x i8> %t0, <i8 0, i8 -1> 1070 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0> 1071 %r = and <2 x i1> %cmp, %notzero 1072 ret <2 x i1> %r 1073} 1074 1075; Negative test - wrong predicate. 1076 1077define i1 @isnot_pow2nor0_ctpop_wrong_pred1(i32 %x) { 1078; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred1( 1079; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 1080; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1 1081; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne i32 [[X]], 0 1082; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 1083; CHECK-NEXT: ret i1 [[R]] 1084; 1085 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1086 %cmp = icmp eq i32 %t0, 1 1087 %notzero = icmp ne i32 %x, 0 1088 %r = and i1 %notzero, %cmp 1089 ret i1 %r 1090} 1091 1092define i1 @isnot_pow2nor0_ctpop_wrong_pred2_logical(i32 %x) { 1093; CHECK-LABEL: @isnot_pow2nor0_ctpop_wrong_pred2_logical( 1094; CHECK-NEXT: [[T0:%.*]] = tail call i32 @llvm.ctpop.i32(i32 [[X:%.*]]), !range [[RNG0]] 1095; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[T0]], 1 1096; CHECK-NEXT: [[NOTZERO:%.*]] = icmp eq i32 [[X]], 0 1097; CHECK-NEXT: [[R:%.*]] = and i1 [[NOTZERO]], [[CMP]] 1098; CHECK-NEXT: ret i1 [[R]] 1099; 1100 %t0 = tail call i32 @llvm.ctpop.i32(i32 %x) 1101 %cmp = icmp eq i32 %t0, 1 1102 %notzero = icmp eq i32 %x, 0 1103 %r = select i1 %notzero, i1 %cmp, i1 false 1104 ret i1 %r 1105} 1106 1107define <2 x i1> @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec(<2 x i8> %x) { 1108; CHECK-LABEL: @isnot_pow2nor0_wrong_pred3_ctpop_commute_vec( 1109; CHECK-NEXT: [[T0:%.*]] = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> [[X:%.*]]) 1110; CHECK-NEXT: [[CMP:%.*]] = icmp ne <2 x i8> [[T0]], <i8 1, i8 1> 1111; CHECK-NEXT: [[NOTZERO:%.*]] = icmp ne <2 x i8> [[X]], zeroinitializer 1112; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[CMP]], [[NOTZERO]] 1113; CHECK-NEXT: ret <2 x i1> [[R]] 1114; 1115 %t0 = tail call <2 x i8> @llvm.ctpop.v2i8(<2 x i8> %x) 1116 %cmp = icmp ne <2 x i8> %t0, <i8 1, i8 1> 1117 %notzero = icmp ne <2 x i8> %x, <i8 0, i8 0> 1118 %r = or <2 x i1> %cmp, %notzero 1119 ret <2 x i1> %r 1120} 1121