1; RUN: llc < %s -mtriple=x86_64-pc-linux -mattr=+bmi,+lzcnt | FileCheck %s 2 3; LZCNT and TZCNT will always produce the operand size when the input operand 4; is zero. This test is to verify that we efficiently select LZCNT/TZCNT 5; based on the fact that the 'icmp+select' sequence is always redundant 6; in every function defined below. 7 8 9define i16 @test1_ctlz(i16 %v) { 10 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 11 %tobool = icmp eq i16 %v, 0 12 %cond = select i1 %tobool, i16 16, i16 %cnt 13 ret i16 %cond 14} 15; CHECK-LABEL: test1_ctlz 16; CHECK: lzcnt 17; CHECK-NEXT: ret 18 19 20define i32 @test2_ctlz(i32 %v) { 21 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 22 %tobool = icmp eq i32 %v, 0 23 %cond = select i1 %tobool, i32 32, i32 %cnt 24 ret i32 %cond 25} 26; CHECK-LABEL: test2_ctlz 27; CHECK: lzcnt 28; CHECK-NEXT: ret 29 30 31define i64 @test3_ctlz(i64 %v) { 32 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 33 %tobool = icmp eq i64 %v, 0 34 %cond = select i1 %tobool, i64 64, i64 %cnt 35 ret i64 %cond 36} 37; CHECK-LABEL: test3_ctlz 38; CHECK: lzcnt 39; CHECK-NEXT: ret 40 41 42define i16 @test4_ctlz(i16 %v) { 43 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 44 %tobool = icmp eq i16 0, %v 45 %cond = select i1 %tobool, i16 16, i16 %cnt 46 ret i16 %cond 47} 48; CHECK-LABEL: test4_ctlz 49; CHECK: lzcnt 50; CHECK-NEXT: ret 51 52 53define i32 @test5_ctlz(i32 %v) { 54 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 55 %tobool = icmp eq i32 0, %v 56 %cond = select i1 %tobool, i32 32, i32 %cnt 57 ret i32 %cond 58} 59; CHECK-LABEL: test5_ctlz 60; CHECK: lzcnt 61; CHECK-NEXT: ret 62 63 64define i64 @test6_ctlz(i64 %v) { 65 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 66 %tobool = icmp eq i64 0, %v 67 %cond = select i1 %tobool, i64 64, i64 %cnt 68 ret i64 %cond 69} 70; CHECK-LABEL: test6_ctlz 71; CHECK: lzcnt 72; CHECK-NEXT: ret 73 74 75define i16 @test10_ctlz(i16* %ptr) { 76 %v = load i16, i16* %ptr 77 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 78 %tobool = icmp eq i16 %v, 0 79 %cond = select i1 %tobool, i16 16, i16 %cnt 80 ret i16 %cond 81} 82; CHECK-LABEL: test10_ctlz 83; CHECK-NOT: movw 84; CHECK: lzcnt 85; CHECK-NEXT: ret 86 87 88define i32 @test11_ctlz(i32* %ptr) { 89 %v = load i32, i32* %ptr 90 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 91 %tobool = icmp eq i32 %v, 0 92 %cond = select i1 %tobool, i32 32, i32 %cnt 93 ret i32 %cond 94} 95; CHECK-LABEL: test11_ctlz 96; CHECK-NOT: movd 97; CHECK: lzcnt 98; CHECK-NEXT: ret 99 100 101define i64 @test12_ctlz(i64* %ptr) { 102 %v = load i64, i64* %ptr 103 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 104 %tobool = icmp eq i64 %v, 0 105 %cond = select i1 %tobool, i64 64, i64 %cnt 106 ret i64 %cond 107} 108; CHECK-LABEL: test12_ctlz 109; CHECK-NOT: movq 110; CHECK: lzcnt 111; CHECK-NEXT: ret 112 113 114define i16 @test13_ctlz(i16* %ptr) { 115 %v = load i16, i16* %ptr 116 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 117 %tobool = icmp eq i16 0, %v 118 %cond = select i1 %tobool, i16 16, i16 %cnt 119 ret i16 %cond 120} 121; CHECK-LABEL: test13_ctlz 122; CHECK-NOT: movw 123; CHECK: lzcnt 124; CHECK-NEXT: ret 125 126 127define i32 @test14_ctlz(i32* %ptr) { 128 %v = load i32, i32* %ptr 129 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 130 %tobool = icmp eq i32 0, %v 131 %cond = select i1 %tobool, i32 32, i32 %cnt 132 ret i32 %cond 133} 134; CHECK-LABEL: test14_ctlz 135; CHECK-NOT: movd 136; CHECK: lzcnt 137; CHECK-NEXT: ret 138 139 140define i64 @test15_ctlz(i64* %ptr) { 141 %v = load i64, i64* %ptr 142 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 143 %tobool = icmp eq i64 0, %v 144 %cond = select i1 %tobool, i64 64, i64 %cnt 145 ret i64 %cond 146} 147; CHECK-LABEL: test15_ctlz 148; CHECK-NOT: movq 149; CHECK: lzcnt 150; CHECK-NEXT: ret 151 152 153define i16 @test1_cttz(i16 %v) { 154 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 155 %tobool = icmp eq i16 %v, 0 156 %cond = select i1 %tobool, i16 16, i16 %cnt 157 ret i16 %cond 158} 159; CHECK-LABEL: test1_cttz 160; CHECK: tzcnt 161; CHECK-NEXT: ret 162 163 164define i32 @test2_cttz(i32 %v) { 165 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 166 %tobool = icmp eq i32 %v, 0 167 %cond = select i1 %tobool, i32 32, i32 %cnt 168 ret i32 %cond 169} 170; CHECK-LABEL: test2_cttz 171; CHECK: tzcnt 172; CHECK-NEXT: ret 173 174 175define i64 @test3_cttz(i64 %v) { 176 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 177 %tobool = icmp eq i64 %v, 0 178 %cond = select i1 %tobool, i64 64, i64 %cnt 179 ret i64 %cond 180} 181; CHECK-LABEL: test3_cttz 182; CHECK: tzcnt 183; CHECK-NEXT: ret 184 185 186define i16 @test4_cttz(i16 %v) { 187 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 188 %tobool = icmp eq i16 0, %v 189 %cond = select i1 %tobool, i16 16, i16 %cnt 190 ret i16 %cond 191} 192; CHECK-LABEL: test4_cttz 193; CHECK: tzcnt 194; CHECK-NEXT: ret 195 196 197define i32 @test5_cttz(i32 %v) { 198 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 199 %tobool = icmp eq i32 0, %v 200 %cond = select i1 %tobool, i32 32, i32 %cnt 201 ret i32 %cond 202} 203; CHECK-LABEL: test5_cttz 204; CHECK: tzcnt 205; CHECK-NEXT: ret 206 207 208define i64 @test6_cttz(i64 %v) { 209 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 210 %tobool = icmp eq i64 0, %v 211 %cond = select i1 %tobool, i64 64, i64 %cnt 212 ret i64 %cond 213} 214; CHECK-LABEL: test6_cttz 215; CHECK: tzcnt 216; CHECK-NEXT: ret 217 218 219define i16 @test10_cttz(i16* %ptr) { 220 %v = load i16, i16* %ptr 221 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 222 %tobool = icmp eq i16 %v, 0 223 %cond = select i1 %tobool, i16 16, i16 %cnt 224 ret i16 %cond 225} 226; CHECK-LABEL: test10_cttz 227; CHECK-NOT: movw 228; CHECK: tzcnt 229; CHECK-NEXT: ret 230 231 232define i32 @test11_cttz(i32* %ptr) { 233 %v = load i32, i32* %ptr 234 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 235 %tobool = icmp eq i32 %v, 0 236 %cond = select i1 %tobool, i32 32, i32 %cnt 237 ret i32 %cond 238} 239; CHECK-LABEL: test11_cttz 240; CHECK-NOT: movd 241; CHECK: tzcnt 242; CHECK-NEXT: ret 243 244 245define i64 @test12_cttz(i64* %ptr) { 246 %v = load i64, i64* %ptr 247 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 248 %tobool = icmp eq i64 %v, 0 249 %cond = select i1 %tobool, i64 64, i64 %cnt 250 ret i64 %cond 251} 252; CHECK-LABEL: test12_cttz 253; CHECK-NOT: movq 254; CHECK: tzcnt 255; CHECK-NEXT: ret 256 257 258define i16 @test13_cttz(i16* %ptr) { 259 %v = load i16, i16* %ptr 260 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 261 %tobool = icmp eq i16 0, %v 262 %cond = select i1 %tobool, i16 16, i16 %cnt 263 ret i16 %cond 264} 265; CHECK-LABEL: test13_cttz 266; CHECK-NOT: movw 267; CHECK: tzcnt 268; CHECK-NEXT: ret 269 270 271define i32 @test14_cttz(i32* %ptr) { 272 %v = load i32, i32* %ptr 273 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 274 %tobool = icmp eq i32 0, %v 275 %cond = select i1 %tobool, i32 32, i32 %cnt 276 ret i32 %cond 277} 278; CHECK-LABEL: test14_cttz 279; CHECK-NOT: movd 280; CHECK: tzcnt 281; CHECK-NEXT: ret 282 283 284define i64 @test15_cttz(i64* %ptr) { 285 %v = load i64, i64* %ptr 286 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 287 %tobool = icmp eq i64 0, %v 288 %cond = select i1 %tobool, i64 64, i64 %cnt 289 ret i64 %cond 290} 291; CHECK-LABEL: test15_cttz 292; CHECK-NOT: movq 293; CHECK: tzcnt 294; CHECK-NEXT: ret 295 296 297define i16 @test4b_ctlz(i16 %v) { 298 %cnt = tail call i16 @llvm.ctlz.i16(i16 %v, i1 true) 299 %tobool = icmp ne i16 %v, 0 300 %cond = select i1 %tobool, i16 %cnt, i16 16 301 ret i16 %cond 302} 303; CHECK-LABEL: test4b_ctlz 304; CHECK: lzcnt 305; CHECK-NEXT: ret 306 307 308define i32 @test5b_ctlz(i32 %v) { 309 %cnt = tail call i32 @llvm.ctlz.i32(i32 %v, i1 true) 310 %tobool = icmp ne i32 %v, 0 311 %cond = select i1 %tobool, i32 %cnt, i32 32 312 ret i32 %cond 313} 314; CHECK-LABEL: test5b_ctlz 315; CHECK: lzcnt 316; CHECK-NEXT: ret 317 318 319define i64 @test6b_ctlz(i64 %v) { 320 %cnt = tail call i64 @llvm.ctlz.i64(i64 %v, i1 true) 321 %tobool = icmp ne i64 %v, 0 322 %cond = select i1 %tobool, i64 %cnt, i64 64 323 ret i64 %cond 324} 325; CHECK-LABEL: test6b_ctlz 326; CHECK: lzcnt 327; CHECK-NEXT: ret 328 329 330define i16 @test4b_cttz(i16 %v) { 331 %cnt = tail call i16 @llvm.cttz.i16(i16 %v, i1 true) 332 %tobool = icmp ne i16 %v, 0 333 %cond = select i1 %tobool, i16 %cnt, i16 16 334 ret i16 %cond 335} 336; CHECK-LABEL: test4b_cttz 337; CHECK: tzcnt 338; CHECK-NEXT: ret 339 340 341define i32 @test5b_cttz(i32 %v) { 342 %cnt = tail call i32 @llvm.cttz.i32(i32 %v, i1 true) 343 %tobool = icmp ne i32 %v, 0 344 %cond = select i1 %tobool, i32 %cnt, i32 32 345 ret i32 %cond 346} 347; CHECK-LABEL: test5b_cttz 348; CHECK: tzcnt 349; CHECK-NEXT: ret 350 351 352define i64 @test6b_cttz(i64 %v) { 353 %cnt = tail call i64 @llvm.cttz.i64(i64 %v, i1 true) 354 %tobool = icmp ne i64 %v, 0 355 %cond = select i1 %tobool, i64 %cnt, i64 64 356 ret i64 %cond 357} 358; CHECK-LABEL: test6b_cttz 359; CHECK: tzcnt 360; CHECK-NEXT: ret 361 362 363declare i64 @llvm.cttz.i64(i64, i1) 364declare i32 @llvm.cttz.i32(i32, i1) 365declare i16 @llvm.cttz.i16(i16, i1) 366declare i64 @llvm.ctlz.i64(i64, i1) 367declare i32 @llvm.ctlz.i32(i32, i1) 368declare i16 @llvm.ctlz.i16(i16, i1) 369 370