1; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+bmi < %s | FileCheck %s --check-prefix=ALL --check-prefix=BMI 2; RUN: opt -S -simplifycfg -mtriple=x86_64-unknown-unknown -mattr=+lzcnt < %s | FileCheck %s --check-prefix=ALL --check-prefix=LZCNT 3; RUN: opt -S -simplifycfg -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; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 9; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %A, i1 true) 10; LZCNT-NEXT: select i1 [[COND]], i64 64, i64 [[CTLZ]] 11; BMI-NOT: select 12; GENERIC-NOT: select 13; ALL: ret 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 27define i32 @test2(i32 %A) { 28; ALL-LABEL: @test2( 29; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 30; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 31; LZCNT-NEXT: select i1 [[COND]], i32 32, i32 [[CTLZ]] 32; BMI-NOT: select 33; GENERIC-NOT: select 34; ALL: ret 35entry: 36 %tobool = icmp eq i32 %A, 0 37 br i1 %tobool, label %cond.end, label %cond.true 38 39cond.true: ; preds = %entry 40 %0 = tail call i32 @llvm.ctlz.i32(i32 %A, i1 true) 41 br label %cond.end 42 43cond.end: ; preds = %entry, %cond.true 44 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 45 ret i32 %cond 46} 47 48 49define signext i16 @test3(i16 signext %A) { 50; ALL-LABEL: @test3( 51; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 52; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 53; LZCNT-NEXT: select i1 [[COND]], i16 16, i16 [[CTLZ]] 54; BMI-NOT: select 55; GENERIC-NOT: select 56; ALL: ret 57entry: 58 %tobool = icmp eq i16 %A, 0 59 br i1 %tobool, label %cond.end, label %cond.true 60 61cond.true: ; preds = %entry 62 %0 = tail call i16 @llvm.ctlz.i16(i16 %A, i1 true) 63 br label %cond.end 64 65cond.end: ; preds = %entry, %cond.true 66 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 67 ret i16 %cond 68} 69 70 71define i64 @test1b(i64 %A) { 72; ALL-LABEL: @test1b( 73; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %A, 0 74; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 75; BMI-NEXT: select i1 [[COND]], i64 64, i64 [[CTTZ]] 76; LZCNT-NOT: select 77; GENERIC-NOT: select 78; ALL: ret 79entry: 80 %tobool = icmp eq i64 %A, 0 81 br i1 %tobool, label %cond.end, label %cond.true 82 83cond.true: ; preds = %entry 84 %0 = tail call i64 @llvm.cttz.i64(i64 %A, i1 true) 85 br label %cond.end 86 87cond.end: ; preds = %entry, %cond.true 88 %cond = phi i64 [ %0, %cond.true ], [ 64, %entry ] 89 ret i64 %cond 90} 91 92 93define i32 @test2b(i32 %A) { 94; ALL-LABEL: @test2b( 95; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %A, 0 96; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 97; BMI-NEXT: select i1 [[COND]], i32 32, i32 [[CTTZ]] 98; LZCNT-NOT: select 99; GENERIC-NOT: select 100; ALL: ret 101entry: 102 %tobool = icmp eq i32 %A, 0 103 br i1 %tobool, label %cond.end, label %cond.true 104 105cond.true: ; preds = %entry 106 %0 = tail call i32 @llvm.cttz.i32(i32 %A, i1 true) 107 br label %cond.end 108 109cond.end: ; preds = %entry, %cond.true 110 %cond = phi i32 [ %0, %cond.true ], [ 32, %entry ] 111 ret i32 %cond 112} 113 114 115define signext i16 @test3b(i16 signext %A) { 116; ALL-LABEL: @test3b( 117; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i16 %A, 0 118; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 119; BMI-NEXT: select i1 [[COND]], i16 16, i16 [[CTTZ]] 120; LZCNT-NOT: select 121; GENERIC-NOT: select 122; ALL: ret 123entry: 124 %tobool = icmp eq i16 %A, 0 125 br i1 %tobool, label %cond.end, label %cond.true 126 127cond.true: ; preds = %entry 128 %0 = tail call i16 @llvm.cttz.i16(i16 %A, i1 true) 129 br label %cond.end 130 131cond.end: ; preds = %entry, %cond.true 132 %cond = phi i16 [ %0, %cond.true ], [ 16, %entry ] 133 ret i16 %cond 134} 135 136; The following tests verify that calls to cttz/ctlz are speculated even if 137; basic block %cond.true has an extra zero extend/truncate which is "free" 138; for the target. 139 140define i64 @test1e(i32 %x) { 141; ALL-LABEL: @test1e( 142; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 143; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 144; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTTZ]] to i64 145; BMI-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] 146; LZCNT-NOT: select 147; GENERIC-NOT: select 148; ALL: ret 149entry: 150 %tobool = icmp eq i32 %x, 0 151 br i1 %tobool, label %cond.end, label %cond.true 152 153cond.true: ; preds = %entry 154 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 155 %phitmp2 = zext i32 %0 to i64 156 br label %cond.end 157 158cond.end: ; preds = %entry, %cond.true 159 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 160 ret i64 %cond 161} 162 163define i32 @test2e(i64 %x) { 164; ALL-LABEL: @test2e( 165; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 166; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 167; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i32 168; BMI-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] 169; LZCNT-NOT: select 170; GENERIC-NOT: select 171; ALL: ret 172entry: 173 %tobool = icmp eq i64 %x, 0 174 br i1 %tobool, label %cond.end, label %cond.true 175 176cond.true: ; preds = %entry 177 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 178 %cast = trunc i64 %0 to i32 179 br label %cond.end 180 181cond.end: ; preds = %entry, %cond.true 182 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 183 ret i32 %cond 184} 185 186define i64 @test3e(i32 %x) { 187; ALL-LABEL: @test3e( 188; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 189; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 190; ALL: [[ZEXT:%[A-Za-z0-9]+]] = zext i32 [[CTLZ]] to i64 191; LZCNT-NEXT: select i1 [[COND]], i64 32, i64 [[ZEXT]] 192; BMI-NOT: select 193; GENERIC-NOT: select 194; ALL: ret 195entry: 196 %tobool = icmp eq i32 %x, 0 197 br i1 %tobool, label %cond.end, label %cond.true 198 199cond.true: ; preds = %entry 200 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 201 %phitmp2 = zext i32 %0 to i64 202 br label %cond.end 203 204cond.end: ; preds = %entry, %cond.true 205 %cond = phi i64 [ %phitmp2, %cond.true ], [ 32, %entry ] 206 ret i64 %cond 207} 208 209define i32 @test4e(i64 %x) { 210; ALL-LABEL: @test4e( 211; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 212; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 213; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i32 214; LZCNT-NEXT: select i1 [[COND]], i32 64, i32 [[TRUNC]] 215; BMI-NOT: select 216; GENERIC-NOT: select 217; ALL: ret 218entry: 219 %tobool = icmp eq i64 %x, 0 220 br i1 %tobool, label %cond.end, label %cond.true 221 222cond.true: ; preds = %entry 223 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 224 %cast = trunc i64 %0 to i32 225 br label %cond.end 226 227cond.end: ; preds = %entry, %cond.true 228 %cond = phi i32 [ %cast, %cond.true ], [ 64, %entry ] 229 ret i32 %cond 230} 231 232define i16 @test5e(i64 %x) { 233; ALL-LABEL: @test5e( 234; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 235; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 236; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTLZ]] to i16 237; LZCNT-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] 238; BMI-NOT: select 239; GENERIC-NOT: select 240; ALL: ret 241entry: 242 %tobool = icmp eq i64 %x, 0 243 br i1 %tobool, label %cond.end, label %cond.true 244 245cond.true: ; preds = %entry 246 %0 = tail call i64 @llvm.ctlz.i64(i64 %x, i1 true) 247 %cast = trunc i64 %0 to i16 248 br label %cond.end 249 250cond.end: ; preds = %entry, %cond.true 251 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 252 ret i16 %cond 253} 254 255define i16 @test6e(i32 %x) { 256; ALL-LABEL: @test6e( 257; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 258; ALL: [[CTLZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 259; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTLZ]] to i16 260; LZCNT-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] 261; BMI-NOT: select 262; GENERIC-NOT: select 263; ALL: ret 264entry: 265 %tobool = icmp eq i32 %x, 0 266 br i1 %tobool, label %cond.end, label %cond.true 267 268cond.true: ; preds = %entry 269 %0 = tail call i32 @llvm.ctlz.i32(i32 %x, i1 true) 270 %cast = trunc i32 %0 to i16 271 br label %cond.end 272 273cond.end: ; preds = %entry, %cond.true 274 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 275 ret i16 %cond 276} 277 278define i16 @test7e(i64 %x) { 279; ALL-LABEL: @test7e( 280; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i64 %x, 0 281; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 282; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i64 [[CTTZ]] to i16 283; BMI-NEXT: select i1 [[COND]], i16 64, i16 [[TRUNC]] 284; LZCNT-NOT: select 285; GENERIC-NOT: select 286; ALL: ret 287entry: 288 %tobool = icmp eq i64 %x, 0 289 br i1 %tobool, label %cond.end, label %cond.true 290 291cond.true: ; preds = %entry 292 %0 = tail call i64 @llvm.cttz.i64(i64 %x, i1 true) 293 %cast = trunc i64 %0 to i16 294 br label %cond.end 295 296cond.end: ; preds = %entry, %cond.true 297 %cond = phi i16 [ %cast, %cond.true ], [ 64, %entry ] 298 ret i16 %cond 299} 300 301define i16 @test8e(i32 %x) { 302; ALL-LABEL: @test8e( 303; ALL: [[COND:%[A-Za-z0-9]+]] = icmp eq i32 %x, 0 304; ALL: [[CTTZ:%[A-Za-z0-9]+]] = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 305; ALL: [[TRUNC:%[A-Za-z0-9]+]] = trunc i32 [[CTTZ]] to i16 306; BMI-NEXT: select i1 [[COND]], i16 32, i16 [[TRUNC]] 307; LZCNT-NOT: select 308; GENERIC-NOT: select 309; ALL: ret 310entry: 311 %tobool = icmp eq i32 %x, 0 312 br i1 %tobool, label %cond.end, label %cond.true 313 314cond.true: ; preds = %entry 315 %0 = tail call i32 @llvm.cttz.i32(i32 %x, i1 true) 316 %cast = trunc i32 %0 to i16 317 br label %cond.end 318 319cond.end: ; preds = %entry, %cond.true 320 %cond = phi i16 [ %cast, %cond.true ], [ 32, %entry ] 321 ret i16 %cond 322} 323 324 325declare i64 @llvm.ctlz.i64(i64, i1) 326declare i32 @llvm.ctlz.i32(i32, i1) 327declare i16 @llvm.ctlz.i16(i16, i1) 328declare i64 @llvm.cttz.i64(i64, i1) 329declare i32 @llvm.cttz.i32(i32, i1) 330declare i16 @llvm.cttz.i16(i16, i1) 331