1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=instcombine -S < %s | FileCheck %s 3 4; This test is to verify that the instruction combiner is able to fold 5; a cttz/ctlz followed by a icmp + select into a single cttz/ctlz with 6; the 'is_zero_undef' flag cleared. 7 8define i16 @test1(i16 %x) { 9; CHECK-LABEL: @test1( 10; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false) 11; CHECK-NEXT: ret i16 [[CT]] 12; 13 %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 14 %tobool = icmp ne i16 %x, 0 15 %cond = select i1 %tobool, i16 %ct, i16 16 16 ret i16 %cond 17} 18 19define i32 @test2(i32 %x) { 20; CHECK-LABEL: @test2( 21; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 22; CHECK-NEXT: ret i32 [[CT]] 23; 24 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 25 %tobool = icmp ne i32 %x, 0 26 %cond = select i1 %tobool, i32 %ct, i32 32 27 ret i32 %cond 28} 29 30define i64 @test3(i64 %x) { 31; CHECK-LABEL: @test3( 32; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false) 33; CHECK-NEXT: ret i64 [[CT]] 34; 35 %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 36 %tobool = icmp ne i64 %x, 0 37 %cond = select i1 %tobool, i64 %ct, i64 64 38 ret i64 %cond 39} 40 41define i16 @test4(i16 %x) { 42; CHECK-LABEL: @test4( 43; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false) 44; CHECK-NEXT: ret i16 [[CT]] 45; 46 %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 47 %tobool = icmp eq i16 %x, 0 48 %cond = select i1 %tobool, i16 16, i16 %ct 49 ret i16 %cond 50} 51 52define i16 @test4_with_range(i16 %x) { 53; CHECK-LABEL: @test4_with_range( 54; CHECK-NEXT: [[CT:%.*]] = call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false) 55; CHECK-NEXT: ret i16 [[CT]] 56; 57 %ct = call range(i16 0, 16) i16 @llvm.ctlz.i16(i16 %x, i1 true) 58 %tobool = icmp eq i16 %x, 0 59 %cond = select i1 %tobool, i16 16, i16 %ct 60 ret i16 %cond 61} 62 63define i32 @test5(i32 %x) { 64; CHECK-LABEL: @test5( 65; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 66; CHECK-NEXT: ret i32 [[CT]] 67; 68 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 69 %tobool = icmp eq i32 %x, 0 70 %cond = select i1 %tobool, i32 32, i32 %ct 71 ret i32 %cond 72} 73 74define i64 @test6(i64 %x) { 75; CHECK-LABEL: @test6( 76; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false) 77; CHECK-NEXT: ret i64 [[CT]] 78; 79 %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 80 %tobool = icmp eq i64 %x, 0 81 %cond = select i1 %tobool, i64 64, i64 %ct 82 ret i64 %cond 83} 84 85define i16 @test1b(i16 %x) { 86; CHECK-LABEL: @test1b( 87; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false) 88; CHECK-NEXT: ret i16 [[CT]] 89; 90 %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 91 %tobool = icmp ne i16 %x, 0 92 %cond = select i1 %tobool, i16 %ct, i16 16 93 ret i16 %cond 94} 95 96define i32 @test2b(i32 %x) { 97; CHECK-LABEL: @test2b( 98; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 99; CHECK-NEXT: ret i32 [[CT]] 100; 101 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 102 %tobool = icmp ne i32 %x, 0 103 %cond = select i1 %tobool, i32 %ct, i32 32 104 ret i32 %cond 105} 106 107define i64 @test3b(i64 %x) { 108; CHECK-LABEL: @test3b( 109; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 110; CHECK-NEXT: ret i64 [[CT]] 111; 112 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 113 %tobool = icmp ne i64 %x, 0 114 %cond = select i1 %tobool, i64 %ct, i64 64 115 ret i64 %cond 116} 117 118define i16 @test4b(i16 %x) { 119; CHECK-LABEL: @test4b( 120; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false) 121; CHECK-NEXT: ret i16 [[CT]] 122; 123 %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 124 %tobool = icmp eq i16 %x, 0 125 %cond = select i1 %tobool, i16 16, i16 %ct 126 ret i16 %cond 127} 128 129define i16 @test4b_with_range(i16 %x) { 130; CHECK-LABEL: @test4b_with_range( 131; CHECK-NEXT: [[CT:%.*]] = call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false) 132; CHECK-NEXT: ret i16 [[CT]] 133; 134 %ct = call range(i16 0, 16) i16 @llvm.cttz.i16(i16 %x, i1 true) 135 %tobool = icmp eq i16 %x, 0 136 %cond = select i1 %tobool, i16 16, i16 %ct 137 ret i16 %cond 138} 139 140define i32 @test5b(i32 %x) { 141; CHECK-LABEL: @test5b( 142; CHECK-NEXT: entry: 143; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 144; CHECK-NEXT: ret i32 [[CT]] 145; 146entry: 147 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 148 %tobool = icmp eq i32 %x, 0 149 %cond = select i1 %tobool, i32 32, i32 %ct 150 ret i32 %cond 151} 152 153define i64 @test6b(i64 %x) { 154; CHECK-LABEL: @test6b( 155; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 156; CHECK-NEXT: ret i64 [[CT]] 157; 158 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 159 %tobool = icmp eq i64 %x, 0 160 %cond = select i1 %tobool, i64 64, i64 %ct 161 ret i64 %cond 162} 163 164define i32 @test1c(i16 %x) { 165; CHECK-LABEL: @test1c( 166; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false) 167; CHECK-NEXT: [[CAST2:%.*]] = zext nneg i16 [[CT]] to i32 168; CHECK-NEXT: ret i32 [[CAST2]] 169; 170 %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 171 %cast2 = zext i16 %ct to i32 172 %tobool = icmp ne i16 %x, 0 173 %cond = select i1 %tobool, i32 %cast2, i32 16 174 ret i32 %cond 175} 176 177define i64 @test2c(i16 %x) { 178; CHECK-LABEL: @test2c( 179; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.cttz.i16(i16 [[X:%.*]], i1 false) 180; CHECK-NEXT: [[CONV:%.*]] = zext nneg i16 [[CT]] to i64 181; CHECK-NEXT: ret i64 [[CONV]] 182; 183 %ct = tail call i16 @llvm.cttz.i16(i16 %x, i1 true) 184 %conv = zext i16 %ct to i64 185 %tobool = icmp ne i16 %x, 0 186 %cond = select i1 %tobool, i64 %conv, i64 16 187 ret i64 %cond 188} 189 190define i64 @test3c(i32 %x) { 191; CHECK-LABEL: @test3c( 192; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 193; CHECK-NEXT: [[CONV:%.*]] = zext nneg i32 [[CT]] to i64 194; CHECK-NEXT: ret i64 [[CONV]] 195; 196 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 197 %conv = zext i32 %ct to i64 198 %tobool = icmp ne i32 %x, 0 199 %cond = select i1 %tobool, i64 %conv, i64 32 200 ret i64 %cond 201} 202 203define i32 @test4c(i16 %x) { 204; CHECK-LABEL: @test4c( 205; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false) 206; CHECK-NEXT: [[CAST:%.*]] = zext nneg i16 [[CT]] to i32 207; CHECK-NEXT: ret i32 [[CAST]] 208; 209 %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 210 %cast = zext i16 %ct to i32 211 %tobool = icmp ne i16 %x, 0 212 %cond = select i1 %tobool, i32 %cast, i32 16 213 ret i32 %cond 214} 215 216define i64 @test5c(i16 %x) { 217; CHECK-LABEL: @test5c( 218; CHECK-NEXT: [[CT:%.*]] = tail call range(i16 0, 17) i16 @llvm.ctlz.i16(i16 [[X:%.*]], i1 false) 219; CHECK-NEXT: [[CAST:%.*]] = zext nneg i16 [[CT]] to i64 220; CHECK-NEXT: ret i64 [[CAST]] 221; 222 %ct = tail call i16 @llvm.ctlz.i16(i16 %x, i1 true) 223 %cast = zext i16 %ct to i64 224 %tobool = icmp ne i16 %x, 0 225 %cond = select i1 %tobool, i64 %cast, i64 16 226 ret i64 %cond 227} 228 229define i64 @test6c(i32 %x) { 230; CHECK-LABEL: @test6c( 231; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 232; CHECK-NEXT: [[CAST:%.*]] = zext nneg i32 [[CT]] to i64 233; CHECK-NEXT: ret i64 [[CAST]] 234; 235 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 236 %cast = zext i32 %ct to i64 237 %tobool = icmp ne i32 %x, 0 238 %cond = select i1 %tobool, i64 %cast, i64 32 239 ret i64 %cond 240} 241 242define i16 @test1d(i64 %x) { 243; CHECK-LABEL: @test1d( 244; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 245; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16 246; CHECK-NEXT: ret i16 [[CONV]] 247; 248 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 249 %conv = trunc i64 %ct to i16 250 %tobool = icmp ne i64 %x, 0 251 %cond = select i1 %tobool, i16 %conv, i16 64 252 ret i16 %cond 253} 254 255define i32 @test2d(i64 %x) { 256; CHECK-LABEL: @test2d( 257; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 258; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 259; CHECK-NEXT: ret i32 [[CAST]] 260; 261 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 262 %cast = trunc i64 %ct to i32 263 %tobool = icmp ne i64 %x, 0 264 %cond = select i1 %tobool, i32 %cast, i32 64 265 ret i32 %cond 266} 267 268define i16 @test3d(i32 %x) { 269; CHECK-LABEL: @test3d( 270; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 271; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i32 [[CT]] to i16 272; CHECK-NEXT: ret i16 [[CAST]] 273; 274 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 275 %cast = trunc i32 %ct to i16 276 %tobool = icmp ne i32 %x, 0 277 %cond = select i1 %tobool, i16 %cast, i16 32 278 ret i16 %cond 279} 280 281define i16 @test4d(i64 %x) { 282; CHECK-LABEL: @test4d( 283; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false) 284; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i16 285; CHECK-NEXT: ret i16 [[CAST]] 286; 287 %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 288 %cast = trunc i64 %ct to i16 289 %tobool = icmp ne i64 %x, 0 290 %cond = select i1 %tobool, i16 %cast, i16 64 291 ret i16 %cond 292} 293 294define i32 @test5d(i64 %x) { 295; CHECK-LABEL: @test5d( 296; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[X:%.*]], i1 false) 297; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 298; CHECK-NEXT: ret i32 [[CAST]] 299; 300 %ct = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 301 %cast = trunc i64 %ct to i32 302 %tobool = icmp ne i64 %x, 0 303 %cond = select i1 %tobool, i32 %cast, i32 64 304 ret i32 %cond 305} 306 307; Same as above, but the counting zeros on an inverted operand with opposite compare. 308 309define i32 @not_op_ctlz(i64 %x) { 310; CHECK-LABEL: @not_op_ctlz( 311; CHECK-NEXT: [[N:%.*]] = xor i64 [[X:%.*]], -1 312; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 false) 313; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 314; CHECK-NEXT: ret i32 [[CAST]] 315; 316 %n = xor i64 %x, -1 317 %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true) 318 %cast = trunc i64 %ct to i32 319 %tobool = icmp eq i64 %x, -1 320 %r = select i1 %tobool, i32 64, i32 %cast 321 ret i32 %r 322} 323 324define i32 @not_op_cttz(i64 %x) { 325; CHECK-LABEL: @not_op_cttz( 326; CHECK-NEXT: [[N:%.*]] = xor i64 [[X:%.*]], -1 327; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[N]], i1 false) 328; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 329; CHECK-NEXT: ret i32 [[CAST]] 330; 331 %n = xor i64 %x, -1 332 %ct = tail call i64 @llvm.cttz.i64(i64 %n, i1 true) 333 %cast = trunc i64 %ct to i32 334 %tobool = icmp eq i64 %x, -1 335 %r = select i1 %tobool, i32 64, i32 %cast 336 ret i32 %r 337} 338 339; negative test 340 341define i32 @not_op_ctlz_wrong_xor_op1(i64 %x) { 342; CHECK-LABEL: @not_op_ctlz_wrong_xor_op1( 343; CHECK-NEXT: [[N:%.*]] = xor i64 [[X:%.*]], -2 344; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 true) 345; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 346; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X]], -1 347; CHECK-NEXT: [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]] 348; CHECK-NEXT: ret i32 [[R]] 349; 350 %n = xor i64 %x, -2 351 %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true) 352 %cast = trunc i64 %ct to i32 353 %tobool = icmp eq i64 %x, -1 354 %r = select i1 %tobool, i32 64, i32 %cast 355 ret i32 %r 356} 357 358; negative test 359 360define i32 @not_op_ctlz_wrong_xor_op0(i64 %x, i64 %y) { 361; CHECK-LABEL: @not_op_ctlz_wrong_xor_op0( 362; CHECK-NEXT: [[N:%.*]] = xor i64 [[Y:%.*]], -1 363; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.ctlz.i64(i64 [[N]], i1 true) 364; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 365; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X:%.*]], -1 366; CHECK-NEXT: [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]] 367; CHECK-NEXT: ret i32 [[R]] 368; 369 %n = xor i64 %y, -1 370 %ct = tail call i64 @llvm.ctlz.i64(i64 %n, i1 true) 371 %cast = trunc i64 %ct to i32 372 %tobool = icmp eq i64 %x, -1 373 %r = select i1 %tobool, i32 64, i32 %cast 374 ret i32 %r 375} 376 377; negative test 378 379define i32 @not_op_cttz_wrong_cmp(i64 %x) { 380; CHECK-LABEL: @not_op_cttz_wrong_cmp( 381; CHECK-NEXT: [[N:%.*]] = xor i64 [[X:%.*]], -1 382; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[N]], i1 true) 383; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i64 [[CT]] to i32 384; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[X]], 0 385; CHECK-NEXT: [[R:%.*]] = select i1 [[TOBOOL]], i32 64, i32 [[CAST]] 386; CHECK-NEXT: ret i32 [[R]] 387; 388 %n = xor i64 %x, -1 389 %ct = tail call i64 @llvm.cttz.i64(i64 %n, i1 true) 390 %cast = trunc i64 %ct to i32 391 %tobool = icmp eq i64 %x, 0 392 %r = select i1 %tobool, i32 64, i32 %cast 393 ret i32 %r 394} 395 396define i16 @test6d(i32 %x) { 397; CHECK-LABEL: @test6d( 398; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 399; CHECK-NEXT: [[CAST:%.*]] = trunc nuw nsw i32 [[CT]] to i16 400; CHECK-NEXT: ret i16 [[CAST]] 401; 402 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 403 %cast = trunc i32 %ct to i16 404 %tobool = icmp ne i32 %x, 0 405 %cond = select i1 %tobool, i16 %cast, i16 32 406 ret i16 %cond 407} 408 409define i64 @select_bug1(i32 %x) { 410; CHECK-LABEL: @select_bug1( 411; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 412; CHECK-NEXT: [[CONV:%.*]] = zext nneg i32 [[CT]] to i64 413; CHECK-NEXT: ret i64 [[CONV]] 414; 415 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 416 %conv = zext i32 %ct to i64 417 %tobool = icmp ne i32 %x, 0 418 %cond = select i1 %tobool, i64 %conv, i64 32 419 ret i64 %cond 420} 421 422define i16 @select_bug2(i32 %x) { 423; CHECK-LABEL: @select_bug2( 424; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 425; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i32 [[CT]] to i16 426; CHECK-NEXT: ret i16 [[CONV]] 427; 428 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 429 %conv = trunc i32 %ct to i16 430 %tobool = icmp ne i32 %x, 0 431 %cond = select i1 %tobool, i16 %conv, i16 32 432 ret i16 %cond 433} 434 435define i128 @test7(i128 %x) { 436; CHECK-LABEL: @test7( 437; CHECK-NEXT: [[CT:%.*]] = tail call range(i128 0, 129) i128 @llvm.ctlz.i128(i128 [[X:%.*]], i1 false) 438; CHECK-NEXT: ret i128 [[CT]] 439; 440 %ct = tail call i128 @llvm.ctlz.i128(i128 %x, i1 true) 441 %tobool = icmp ne i128 %x, 0 442 %cond = select i1 %tobool, i128 %ct, i128 128 443 ret i128 %cond 444} 445 446define i128 @test8(i128 %x) { 447; CHECK-LABEL: @test8( 448; CHECK-NEXT: [[CT:%.*]] = tail call range(i128 0, 129) i128 @llvm.cttz.i128(i128 [[X:%.*]], i1 false) 449; CHECK-NEXT: ret i128 [[CT]] 450; 451 %ct = tail call i128 @llvm.cttz.i128(i128 %x, i1 true) 452 %tobool = icmp ne i128 %x, 0 453 %cond = select i1 %tobool, i128 %ct, i128 128 454 ret i128 %cond 455} 456 457define i32 @test_ctlz_not_bw(i32 %x) { 458; CHECK-LABEL: @test_ctlz_not_bw( 459; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 true) 460; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0 461; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]] 462; CHECK-NEXT: ret i32 [[RES]] 463; 464 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 465 %cmp = icmp ne i32 %x, 0 466 %res = select i1 %cmp, i32 %ct, i32 123 467 ret i32 %res 468} 469 470define i32 @test_ctlz_not_bw_multiuse(i32 %x) { 471; CHECK-LABEL: @test_ctlz_not_bw_multiuse( 472; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 473; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0 474; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]] 475; CHECK-NEXT: [[RES:%.*]] = or i32 [[SEL]], [[CT]] 476; CHECK-NEXT: ret i32 [[RES]] 477; 478 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 479 %cmp = icmp ne i32 %x, 0 480 %sel = select i1 %cmp, i32 %ct, i32 123 481 %res = or i32 %sel, %ct 482 ret i32 %res 483} 484 485define i32 @test_cttz_not_bw(i32 %x) { 486; CHECK-LABEL: @test_cttz_not_bw( 487; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true) 488; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0 489; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]] 490; CHECK-NEXT: ret i32 [[RES]] 491; 492 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 493 %cmp = icmp ne i32 %x, 0 494 %res = select i1 %cmp, i32 %ct, i32 123 495 ret i32 %res 496} 497 498define i32 @test_cttz_not_bw_noundef(i32 %x) { 499; CHECK-LABEL: @test_cttz_not_bw_noundef( 500; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 true) 501; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0 502; CHECK-NEXT: [[RES:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]] 503; CHECK-NEXT: ret i32 [[RES]] 504; 505 %ct = tail call noundef i32 @llvm.cttz.i32(i32 %x, i1 false) 506 %cmp = icmp ne i32 %x, 0 507 %res = select i1 %cmp, i32 %ct, i32 123 508 ret i32 %res 509} 510 511define i32 @test_cttz_not_bw_multiuse(i32 %x) { 512; CHECK-LABEL: @test_cttz_not_bw_multiuse( 513; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 514; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq i32 [[X]], 0 515; CHECK-NEXT: [[SEL:%.*]] = select i1 [[CMP_NOT]], i32 123, i32 [[CT]] 516; CHECK-NEXT: [[RES:%.*]] = or i32 [[SEL]], [[CT]] 517; CHECK-NEXT: ret i32 [[RES]] 518; 519 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 520 %cmp = icmp ne i32 %x, 0 521 %sel = select i1 %cmp, i32 %ct, i32 123 522 %res = or i32 %sel, %ct 523 ret i32 %res 524} 525 526define <2 x i32> @test_ctlz_bw_vec(<2 x i32> %x) { 527; CHECK-LABEL: @test_ctlz_bw_vec( 528; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X:%.*]], i1 false) 529; CHECK-NEXT: ret <2 x i32> [[CT]] 530; 531 %ct = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 true) 532 %cmp = icmp ne <2 x i32> %x, zeroinitializer 533 %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 32, i32 32> 534 ret <2 x i32> %res 535} 536 537define <2 x i32> @test_ctlz_not_bw_vec(<2 x i32> %x) { 538; CHECK-LABEL: @test_ctlz_not_bw_vec( 539; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.ctlz.v2i32(<2 x i32> [[X:%.*]], i1 true) 540; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer 541; CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[CT]] 542; CHECK-NEXT: ret <2 x i32> [[RES]] 543; 544 %ct = tail call <2 x i32> @llvm.ctlz.v2i32(<2 x i32> %x, i1 false) 545 %cmp = icmp ne <2 x i32> %x, zeroinitializer 546 %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 0, i32 0> 547 ret <2 x i32> %res 548} 549 550define <2 x i32> @test_cttz_bw_vec(<2 x i32> %x) { 551; CHECK-LABEL: @test_cttz_bw_vec( 552; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 false) 553; CHECK-NEXT: ret <2 x i32> [[CT]] 554; 555 %ct = tail call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %x, i1 true) 556 %cmp = icmp ne <2 x i32> %x, zeroinitializer 557 %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 32, i32 32> 558 ret <2 x i32> %res 559} 560 561define <2 x i32> @test_cttz_not_bw_vec(<2 x i32> %x) { 562; CHECK-LABEL: @test_cttz_not_bw_vec( 563; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) <2 x i32> @llvm.cttz.v2i32(<2 x i32> [[X:%.*]], i1 true) 564; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp eq <2 x i32> [[X]], zeroinitializer 565; CHECK-NEXT: [[RES:%.*]] = select <2 x i1> [[CMP_NOT]], <2 x i32> zeroinitializer, <2 x i32> [[CT]] 566; CHECK-NEXT: ret <2 x i32> [[RES]] 567; 568 %ct = tail call <2 x i32> @llvm.cttz.v2i32(<2 x i32> %x, i1 false) 569 %cmp = icmp ne <2 x i32> %x, zeroinitializer 570 %res = select <2 x i1> %cmp, <2 x i32> %ct, <2 x i32> <i32 0, i32 0> 571 ret <2 x i32> %res 572} 573 574define i32 @test_multiuse_def(i32 %x, ptr %p) { 575; CHECK-LABEL: @test_multiuse_def( 576; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 577; CHECK-NEXT: store i32 [[CT]], ptr [[P:%.*]], align 4 578; CHECK-NEXT: ret i32 [[CT]] 579; 580 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 false) 581 %tobool = icmp ne i32 %x, 0 582 %cond = select i1 %tobool, i32 %ct, i32 32 583 store i32 %ct, ptr %p 584 ret i32 %cond 585} 586 587define i32 @test_multiuse_undef(i32 %x, ptr %p) { 588; CHECK-LABEL: @test_multiuse_undef( 589; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.ctlz.i32(i32 [[X:%.*]], i1 false) 590; CHECK-NEXT: store i32 [[CT]], ptr [[P:%.*]], align 4 591; CHECK-NEXT: ret i32 [[CT]] 592; 593 %ct = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 594 %tobool = icmp ne i32 %x, 0 595 %cond = select i1 %tobool, i32 %ct, i32 32 596 store i32 %ct, ptr %p 597 ret i32 %cond 598} 599 600define i64 @test_multiuse_zext_def(i32 %x, ptr %p) { 601; CHECK-LABEL: @test_multiuse_zext_def( 602; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 603; CHECK-NEXT: [[CONV:%.*]] = zext nneg i32 [[CT]] to i64 604; CHECK-NEXT: store i64 [[CONV]], ptr [[P:%.*]], align 4 605; CHECK-NEXT: ret i64 [[CONV]] 606; 607 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 false) 608 %conv = zext i32 %ct to i64 609 %tobool = icmp ne i32 %x, 0 610 %cond = select i1 %tobool, i64 %conv, i64 32 611 store i64 %conv, ptr %p 612 ret i64 %cond 613} 614 615define i64 @test_multiuse_zext_undef(i32 %x, ptr %p) { 616; CHECK-LABEL: @test_multiuse_zext_undef( 617; CHECK-NEXT: [[CT:%.*]] = tail call range(i32 0, 33) i32 @llvm.cttz.i32(i32 [[X:%.*]], i1 false) 618; CHECK-NEXT: [[CONV:%.*]] = zext nneg i32 [[CT]] to i64 619; CHECK-NEXT: store i64 [[CONV]], ptr [[P:%.*]], align 4 620; CHECK-NEXT: ret i64 [[CONV]] 621; 622 %ct = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 623 %conv = zext i32 %ct to i64 624 %tobool = icmp ne i32 %x, 0 625 %cond = select i1 %tobool, i64 %conv, i64 32 626 store i64 %conv, ptr %p 627 ret i64 %cond 628} 629 630define i16 @test_multiuse_trunc_def(i64 %x, ptr %p) { 631; CHECK-LABEL: @test_multiuse_trunc_def( 632; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 633; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16 634; CHECK-NEXT: store i16 [[CONV]], ptr [[P:%.*]], align 2 635; CHECK-NEXT: ret i16 [[CONV]] 636; 637 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 false) 638 %conv = trunc i64 %ct to i16 639 %tobool = icmp ne i64 %x, 0 640 %cond = select i1 %tobool, i16 %conv, i16 64 641 store i16 %conv, ptr %p 642 ret i16 %cond 643} 644 645define i16 @test_multiuse_trunc_undef(i64 %x, ptr %p) { 646; CHECK-LABEL: @test_multiuse_trunc_undef( 647; CHECK-NEXT: [[CT:%.*]] = tail call range(i64 0, 65) i64 @llvm.cttz.i64(i64 [[X:%.*]], i1 false) 648; CHECK-NEXT: [[CONV:%.*]] = trunc nuw nsw i64 [[CT]] to i16 649; CHECK-NEXT: store i16 [[CONV]], ptr [[P:%.*]], align 2 650; CHECK-NEXT: ret i16 [[CONV]] 651; 652 %ct = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 653 %conv = trunc i64 %ct to i16 654 %tobool = icmp ne i64 %x, 0 655 %cond = select i1 %tobool, i16 %conv, i16 64 656 store i16 %conv, ptr %p 657 ret i16 %cond 658} 659 660declare i16 @llvm.ctlz.i16(i16, i1) 661declare i32 @llvm.ctlz.i32(i32, i1) 662declare i64 @llvm.ctlz.i64(i64, i1) 663declare i128 @llvm.ctlz.i128(i128, i1) 664declare <2 x i32> @llvm.ctlz.v2i32(<2 x i32>, i1) 665declare i16 @llvm.cttz.i16(i16, i1) 666declare i32 @llvm.cttz.i32(i32, i1) 667declare i64 @llvm.cttz.i64(i64, i1) 668declare i128 @llvm.cttz.i128(i128, i1) 669declare <2 x i32> @llvm.cttz.v2i32(<2 x i32>, i1) 670