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