1; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI 2; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT 3; RUN: opt -S -codegenprepare -mtriple=x86_64-unknown-unknown < %s | FileCheck %s --check-prefix=ALL --check-prefix=GENERIC 4 5 6define i64 @test1(i64 %A) { 7; ALL-LABEL: @test1( 8; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i64 @llvm.ctlz.i64(i64 %A, i1 false) 9; LZCNT-NEXT: ret i64 [[CTLZ]] 10; BMI: icmp eq i64 %A, 0 11; BMI: call i64 @llvm.ctlz.i64(i64 %A, i1 true) 12; GENERIC: icmp eq i64 %A, 0 13; GENERIC: call i64 @llvm.ctlz.i64(i64 %A, i1 true) 14entry: 15 %tobool = icmp eq i64 %A, 0 16 br i1 %tobool, label %cond.end, label %cond.true 17 18cond.true: ; preds = %entry 19 %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) 20 br label %cond.end 21 22cond.end: ; preds = %entry, %cond.true 23 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] 24 ret i64 %cond 25} 26 27 28define i32 @test2(i32 %A) { 29; ALL-LABEL: @test2( 30; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i32 @llvm.ctlz.i32(i32 %A, i1 false) 31; LZCNT-NEXT: ret i32 [[CTLZ]] 32; BMI: icmp eq i32 %A, 0 33; BMI: call i32 @llvm.ctlz.i32(i32 %A, i1 true) 34; GENERIC: icmp eq i32 %A, 0 35; GENERIC: call i32 @llvm.ctlz.i32(i32 %A, i1 true) 36entry: 37 %tobool = icmp eq i32 %A, 0 38 br i1 %tobool, label %cond.end, label %cond.true 39 40cond.true: ; preds = %entry 41 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 42 br label %cond.end 43 44cond.end: ; preds = %entry, %cond.true 45 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 46 ret i32 %cond 47} 48 49 50define signext i16 @test3(i16 signext %A) { 51; ALL-LABEL: @test3( 52; LZCNT: [[CTLZ:%[A-Za-z0-9]+]] = call i16 @llvm.ctlz.i16(i16 %A, i1 false) 53; LZCNT-NEXT: ret i16 [[CTLZ]] 54; BMI: icmp eq i16 %A, 0 55; BMI: call i16 @llvm.ctlz.i16(i16 %A, i1 true) 56; GENERIC: icmp eq i16 %A, 0 57; GENERIC: call i16 @llvm.ctlz.i16(i16 %A, i1 true) 58entry: 59 %tobool = icmp eq i16 %A, 0 60 br i1 %tobool, label %cond.end, label %cond.true 61 62cond.true: ; preds = %entry 63 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 64 br label %cond.end 65 66cond.end: ; preds = %entry, %cond.true 67 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 68 ret i16 %cond 69} 70 71 72define i64 @test1b(i64 %A) { 73; ALL-LABEL: @test1b( 74; LZCNT: icmp eq i64 %A, 0 75; LZCNT: call i64 @llvm.cttz.i64(i64 %A, i1 true) 76; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i64 @llvm.cttz.i64(i64 %A, i1 false) 77; BMI-NEXT: ret i64 [[CTTZ]] 78; GENERIC: icmp eq i64 %A, 0 79; GENERIC: call i64 @llvm.cttz.i64(i64 %A, i1 true) 80entry: 81 %tobool = icmp eq i64 %A, 0 82 br i1 %tobool, label %cond.end, label %cond.true 83 84cond.true: ; preds = %entry 85 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 86 br label %cond.end 87 88cond.end: ; preds = %entry, %cond.true 89 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] 90 ret i64 %cond 91} 92 93 94define i32 @test2b(i32 %A) { 95; ALL-LABEL: @test2b( 96; LZCNT: icmp eq i32 %A, 0 97; LZCNT: call i32 @llvm.cttz.i32(i32 %A, i1 true) 98; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i32 @llvm.cttz.i32(i32 %A, i1 false) 99; BMI-NEXT: ret i32 [[CTTZ]] 100; GENERIC: icmp eq i32 %A, 0 101; GENERIC: call i32 @llvm.cttz.i32(i32 %A, i1 true) 102entry: 103 %tobool = icmp eq i32 %A, 0 104 br i1 %tobool, label %cond.end, label %cond.true 105 106cond.true: ; preds = %entry 107 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 108 br label %cond.end 109 110cond.end: ; preds = %entry, %cond.true 111 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 112 ret i32 %cond 113} 114 115 116define signext i16 @test3b(i16 signext %A) { 117; ALL-LABEL: @test3b( 118; LZCNT: icmp eq i16 %A, 0 119; LZCNT: call i16 @llvm.cttz.i16(i16 %A, i1 true) 120; BMI: [[CTTZ:%[A-Za-z0-9]+]] = call i16 @llvm.cttz.i16(i16 %A, i1 false) 121; BMI-NEXT: ret i16 [[CTTZ]] 122; GENERIC: icmp eq i16 %A, 0 123; GENERIC: call i16 @llvm.cttz.i16(i16 %A, i1 true) 124entry: 125 %tobool = icmp eq i16 %A, 0 126 br i1 %tobool, label %cond.end, label %cond.true 127 128cond.true: ; preds = %entry 129 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 130 br label %cond.end 131 132cond.end: ; preds = %entry, %cond.true 133 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 134 ret i16 %cond 135} 136 137 138define i64 @test1c(i64 %A) { 139; ALL-LABEL: @test1c( 140; ALL: icmp eq i64 %A, 0 141; ALL: call i64 @llvm.ctlz.i64(i64 %A, i1 true) 142entry: 143 %tobool = icmp eq i64 %A, 0 144 br i1 %tobool, label %cond.end, label %cond.true 145 146cond.true: ; preds = %entry 147 %0 = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) 148 br label %cond.end 149 150cond.end: ; preds = %entry, %cond.true 151 %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] 152 ret i64 %cond 153} 154 155define i32 @test2c(i32 %A) { 156; ALL-LABEL: @test2c( 157; ALL: icmp eq i32 %A, 0 158; ALL: call i32 @llvm.ctlz.i32(i32 %A, i1 true) 159entry: 160 %tobool = icmp eq i32 %A, 0 161 br i1 %tobool, label %cond.end, label %cond.true 162 163cond.true: ; preds = %entry 164 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 165 br label %cond.end 166 167cond.end: ; preds = %entry, %cond.true 168 %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] 169 ret i32 %cond 170} 171 172 173define signext i16 @test3c(i16 signext %A) { 174; ALL-LABEL: @test3c( 175; ALL: icmp eq i16 %A, 0 176; ALL: call i16 @llvm.ctlz.i16(i16 %A, i1 true) 177entry: 178 %tobool = icmp eq i16 %A, 0 179 br i1 %tobool, label %cond.end, label %cond.true 180 181cond.true: ; preds = %entry 182 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 183 br label %cond.end 184 185cond.end: ; preds = %entry, %cond.true 186 %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] 187 ret i16 %cond 188} 189 190 191define i64 @test1d(i64 %A) { 192; ALL-LABEL: @test1d( 193; ALL: icmp eq i64 %A, 0 194; ALL: call i64 @llvm.cttz.i64(i64 %A, i1 true) 195entry: 196 %tobool = icmp eq i64 %A, 0 197 br i1 %tobool, label %cond.end, label %cond.true 198 199cond.true: ; preds = %entry 200 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 201 br label %cond.end 202 203cond.end: ; preds = %entry, %cond.true 204 %cond = phi i64 [ %0, %cond.true ], [ 63, %entry ] 205 ret i64 %cond 206} 207 208 209define i32 @test2d(i32 %A) { 210; ALL-LABEL: @test2d( 211; ALL: icmp eq i32 %A, 0 212; ALL: call i32 @llvm.cttz.i32(i32 %A, i1 true) 213entry: 214 %tobool = icmp eq i32 %A, 0 215 br i1 %tobool, label %cond.end, label %cond.true 216 217cond.true: ; preds = %entry 218 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 219 br label %cond.end 220 221cond.end: ; preds = %entry, %cond.true 222 %cond = phi i32 [ %0, %cond.true ], [ 31, %entry ] 223 ret i32 %cond 224} 225 226 227define signext i16 @test3d(i16 signext %A) { 228; ALL-LABEL: @test3d( 229; ALL: icmp eq i16 %A, 0 230; ALL: call i16 @llvm.cttz.i16(i16 %A, i1 true) 231entry: 232 %tobool = icmp eq i16 %A, 0 233 br i1 %tobool, label %cond.end, label %cond.true 234 235cond.true: ; preds = %entry 236 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 237 br label %cond.end 238 239cond.end: ; preds = %entry, %cond.true 240 %cond = phi i16 [ %0, %cond.true ], [ 15, %entry ] 241 ret i16 %cond 242} 243 244; The following tests verify that calls to cttz/ctlz are speculated even if 245; basic block %cond.true has an extra zero extend/truncate which is "free" 246; for the target. 247 248define i64 @test1e(i32 %x) { 249; ALL-LABEL: @test1e( 250; LZCNT: icmp eq i32 %x, 0 251; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true) 252; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false) 253; GENERIC: icmp eq i32 %x, 0 254; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true) 255entry: 256 %tobool = icmp eq i32 %x, 0 257 br i1 %tobool, label %cond.end, label %cond.true 258 259cond.true: ; preds = %entry 260 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 261 %phitmp2 = zext i32 %0 to i64 262 br label %cond.end 263 264cond.end: ; preds = %entry, %cond.true 265 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 266 ret i64 %cond 267} 268 269define i32 @test2e(i64 %x) { 270; ALL-LABEL: @test2e( 271; LZCNT: icmp eq i64 %x, 0 272; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true) 273; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false) 274; GENERIC: icmp eq i64 %x, 0 275; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true) 276entry: 277 %tobool = icmp eq i64 %x, 0 278 br i1 %tobool, label %cond.end, label %cond.true 279 280cond.true: ; preds = %entry 281 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 282 %cast = trunc i64 %0 to i32 283 br label %cond.end 284 285cond.end: ; preds = %entry, %cond.true 286 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 287 ret i32 %cond 288} 289 290define i64 @test3e(i32 %x) { 291; ALL-LABEL: @test3e( 292; BMI: icmp eq i32 %x, 0 293; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true) 294; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false) 295; GENERIC: icmp eq i32 %x, 0 296; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true) 297entry: 298 %tobool = icmp eq i32 %x, 0 299 br i1 %tobool, label %cond.end, label %cond.true 300 301cond.true: ; preds = %entry 302 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 303 %phitmp2 = zext i32 %0 to i64 304 br label %cond.end 305 306cond.end: ; preds = %entry, %cond.true 307 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 308 ret i64 %cond 309} 310 311define i32 @test4e(i64 %x) { 312; ALL-LABEL: @test4e( 313; BMI: icmp eq i64 %x, 0 314; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true) 315; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false) 316; GENERIC: icmp eq i64 %x, 0 317; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true) 318entry: 319 %tobool = icmp eq i64 %x, 0 320 br i1 %tobool, label %cond.end, label %cond.true 321 322cond.true: ; preds = %entry 323 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 324 %cast = trunc i64 %0 to i32 325 br label %cond.end 326 327cond.end: ; preds = %entry, %cond.true 328 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 329 ret i32 %cond 330} 331 332define i16 @test5e(i64 %x) { 333; ALL-LABEL: @test5e( 334; BMI: icmp eq i64 %x, 0 335; BMI: call i64 @llvm.ctlz.i64(i64 %x, i1 true) 336; LZCNT: call i64 @llvm.ctlz.i64(i64 %x, i1 false) 337; GENERIC: icmp eq i64 %x, 0 338; GENERIC: call i64 @llvm.ctlz.i64(i64 %x, i1 true) 339entry: 340 %tobool = icmp eq i64 %x, 0 341 br i1 %tobool, label %cond.end, label %cond.true 342 343cond.true: ; preds = %entry 344 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 345 %cast = trunc i64 %0 to i16 346 br label %cond.end 347 348cond.end: ; preds = %entry, %cond.true 349 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 350 ret i16 %cond 351} 352 353define i16 @test6e(i32 %x) { 354; ALL-LABEL: @test6e( 355; BMI: icmp eq i32 %x, 0 356; BMI: call i32 @llvm.ctlz.i32(i32 %x, i1 true) 357; LZCNT: call i32 @llvm.ctlz.i32(i32 %x, i1 false) 358; GENERIC: icmp eq i32 %x, 0 359; GENERIC: call i32 @llvm.ctlz.i32(i32 %x, i1 true) 360entry: 361 %tobool = icmp eq i32 %x, 0 362 br i1 %tobool, label %cond.end, label %cond.true 363 364cond.true: ; preds = %entry 365 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 366 %cast = trunc i32 %0 to i16 367 br label %cond.end 368 369cond.end: ; preds = %entry, %cond.true 370 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 371 ret i16 %cond 372} 373 374define i16 @test7e(i64 %x) { 375; ALL-LABEL: @test7e( 376; LZCNT: icmp eq i64 %x, 0 377; LZCNT: call i64 @llvm.cttz.i64(i64 %x, i1 true) 378; BMI: call i64 @llvm.cttz.i64(i64 %x, i1 false) 379; GENERIC: icmp eq i64 %x, 0 380; GENERIC: call i64 @llvm.cttz.i64(i64 %x, i1 true) 381entry: 382 %tobool = icmp eq i64 %x, 0 383 br i1 %tobool, label %cond.end, label %cond.true 384 385cond.true: ; preds = %entry 386 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 387 %cast = trunc i64 %0 to i16 388 br label %cond.end 389 390cond.end: ; preds = %entry, %cond.true 391 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 392 ret i16 %cond 393} 394 395define i16 @test8e(i32 %x) { 396; ALL-LABEL: @test8e( 397; LZCNT: icmp eq i32 %x, 0 398; LZCNT: call i32 @llvm.cttz.i32(i32 %x, i1 true) 399; BMI: call i32 @llvm.cttz.i32(i32 %x, i1 false) 400; GENERIC: icmp eq i32 %x, 0 401; GENERIC: call i32 @llvm.cttz.i32(i32 %x, i1 true) 402entry: 403 %tobool = icmp eq i32 %x, 0 404 br i1 %tobool, label %cond.end, label %cond.true 405 406cond.true: ; preds = %entry 407 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 408 %cast = trunc i32 %0 to i16 409 br label %cond.end 410 411cond.end: ; preds = %entry, %cond.true 412 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 413 ret i16 %cond 414} 415 416 417declare i64 @llvm.ctlz.i64(i64, i1) 418declare i32 @llvm.ctlz.i32(i32, i1) 419declare i16 @llvm.ctlz.i16(i16, i1) 420declare i64 @llvm.cttz.i64(i64, i1) 421declare i32 @llvm.cttz.i32(i32, i1) 422declare i16 @llvm.cttz.i16(i16, i1) 423