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 9 define 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 20 define 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 31 define 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 42 define 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 53 define 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 64 define 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 75 define 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 88 define 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 101 define 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 114 define 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 127 define 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 140 define 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 153 define 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 164 define 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 175 define 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 186 define 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 197 define 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 208 define 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 219 define 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 232 define 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 245 define 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 258 define 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 271 define 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 284 define 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 297 define 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 308 define 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 319 define 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 330 define 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 341 define 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 352 define 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 363 declare i64 @llvm.cttz.i64(i64, i1) 364 declare i32 @llvm.cttz.i32(i32, i1) 365 declare i16 @llvm.cttz.i16(i16, i1) 366 declare i64 @llvm.ctlz.i64(i64, i1) 367 declare i32 @llvm.ctlz.i32(i32, i1) 368 declare i16 @llvm.ctlz.i16(i16, i1) 369 370