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