1 ; RUN: llc < %s -march=x86-64 -mattr=+bmi,+bmi2 | FileCheck %s 2 3 declare i8 @llvm.cttz.i8(i8, i1) nounwind readnone 4 declare i16 @llvm.cttz.i16(i16, i1) nounwind readnone 5 declare i32 @llvm.cttz.i32(i32, i1) nounwind readnone 6 declare i64 @llvm.cttz.i64(i64, i1) nounwind readnone 7 8 define i8 @t1(i8 %x) nounwind { 9 %tmp = tail call i8 @llvm.cttz.i8( i8 %x, i1 false ) 10 ret i8 %tmp 11 ; CHECK-LABEL: t1: 12 ; CHECK: tzcntl 13 } 14 15 define i16 @t2(i16 %x) nounwind { 16 %tmp = tail call i16 @llvm.cttz.i16( i16 %x, i1 false ) 17 ret i16 %tmp 18 ; CHECK-LABEL: t2: 19 ; CHECK: tzcntw 20 } 21 22 define i32 @t3(i32 %x) nounwind { 23 %tmp = tail call i32 @llvm.cttz.i32( i32 %x, i1 false ) 24 ret i32 %tmp 25 ; CHECK-LABEL: t3: 26 ; CHECK: tzcntl 27 } 28 29 define i32 @tzcnt32_load(i32* %x) nounwind { 30 %x1 = load i32, i32* %x 31 %tmp = tail call i32 @llvm.cttz.i32(i32 %x1, i1 false ) 32 ret i32 %tmp 33 ; CHECK-LABEL: tzcnt32_load: 34 ; CHECK: tzcntl ({{.*}}) 35 } 36 37 define i64 @t4(i64 %x) nounwind { 38 %tmp = tail call i64 @llvm.cttz.i64( i64 %x, i1 false ) 39 ret i64 %tmp 40 ; CHECK-LABEL: t4: 41 ; CHECK: tzcntq 42 } 43 44 define i8 @t5(i8 %x) nounwind { 45 %tmp = tail call i8 @llvm.cttz.i8( i8 %x, i1 true ) 46 ret i8 %tmp 47 ; CHECK-LABEL: t5: 48 ; CHECK: tzcntl 49 } 50 51 define i16 @t6(i16 %x) nounwind { 52 %tmp = tail call i16 @llvm.cttz.i16( i16 %x, i1 true ) 53 ret i16 %tmp 54 ; CHECK-LABEL: t6: 55 ; CHECK: tzcntw 56 } 57 58 define i32 @t7(i32 %x) nounwind { 59 %tmp = tail call i32 @llvm.cttz.i32( i32 %x, i1 true ) 60 ret i32 %tmp 61 ; CHECK-LABEL: t7: 62 ; CHECK: tzcntl 63 } 64 65 define i64 @t8(i64 %x) nounwind { 66 %tmp = tail call i64 @llvm.cttz.i64( i64 %x, i1 true ) 67 ret i64 %tmp 68 ; CHECK-LABEL: t8: 69 ; CHECK: tzcntq 70 } 71 72 define i32 @andn32(i32 %x, i32 %y) nounwind readnone { 73 %tmp1 = xor i32 %x, -1 74 %tmp2 = and i32 %y, %tmp1 75 ret i32 %tmp2 76 ; CHECK-LABEL: andn32: 77 ; CHECK: andnl 78 } 79 80 define i32 @andn32_load(i32 %x, i32* %y) nounwind readnone { 81 %y1 = load i32, i32* %y 82 %tmp1 = xor i32 %x, -1 83 %tmp2 = and i32 %y1, %tmp1 84 ret i32 %tmp2 85 ; CHECK-LABEL: andn32_load: 86 ; CHECK: andnl ({{.*}}) 87 } 88 89 define i64 @andn64(i64 %x, i64 %y) nounwind readnone { 90 %tmp1 = xor i64 %x, -1 91 %tmp2 = and i64 %tmp1, %y 92 ret i64 %tmp2 93 ; CHECK-LABEL: andn64: 94 ; CHECK: andnq 95 } 96 97 define i32 @bextr32(i32 %x, i32 %y) nounwind readnone { 98 %tmp = tail call i32 @llvm.x86.bmi.bextr.32(i32 %x, i32 %y) 99 ret i32 %tmp 100 ; CHECK-LABEL: bextr32: 101 ; CHECK: bextrl 102 } 103 104 define i32 @bextr32_load(i32* %x, i32 %y) nounwind readnone { 105 %x1 = load i32, i32* %x 106 %tmp = tail call i32 @llvm.x86.bmi.bextr.32(i32 %x1, i32 %y) 107 ret i32 %tmp 108 ; CHECK-LABEL: bextr32_load: 109 ; CHECK: bextrl {{.*}}, ({{.*}}), {{.*}} 110 } 111 112 declare i32 @llvm.x86.bmi.bextr.32(i32, i32) nounwind readnone 113 114 define i32 @bextr32b(i32 %x) nounwind uwtable readnone ssp { 115 %1 = lshr i32 %x, 4 116 %2 = and i32 %1, 4095 117 ret i32 %2 118 ; CHECK-LABEL: bextr32b: 119 ; CHECK: bextrl 120 } 121 122 define i32 @bextr32b_load(i32* %x) nounwind uwtable readnone ssp { 123 %1 = load i32, i32* %x 124 %2 = lshr i32 %1, 4 125 %3 = and i32 %2, 4095 126 ret i32 %3 127 ; CHECK-LABEL: bextr32b_load: 128 ; CHECK: bextrl {{.*}}, ({{.*}}), {{.*}} 129 } 130 131 define i64 @bextr64(i64 %x, i64 %y) nounwind readnone { 132 %tmp = tail call i64 @llvm.x86.bmi.bextr.64(i64 %x, i64 %y) 133 ret i64 %tmp 134 ; CHECK-LABEL: bextr64: 135 ; CHECK: bextrq 136 } 137 138 declare i64 @llvm.x86.bmi.bextr.64(i64, i64) nounwind readnone 139 140 define i64 @bextr64b(i64 %x) nounwind uwtable readnone ssp { 141 %1 = lshr i64 %x, 4 142 %2 = and i64 %1, 4095 143 ret i64 %2 144 ; CHECK-LABEL: bextr64b: 145 ; CHECK: bextrq 146 } 147 148 define i64 @bextr64b_load(i64* %x) { 149 %1 = load i64, i64* %x, align 8 150 %2 = lshr i64 %1, 4 151 %3 = and i64 %2, 4095 152 ret i64 %3 153 ; CHECK-LABEL: bextr64b_load: 154 ; CHECK: bextrq {{.*}}, ({{.*}}), {{.*}} 155 } 156 157 define i32 @non_bextr32(i32 %x) { 158 entry: 159 %shr = lshr i32 %x, 2 160 %and = and i32 %shr, 111 161 ret i32 %and 162 ; CHECK-LABEL: non_bextr32: 163 ; CHECK: shrl $2 164 ; CHECK: andl $111 165 } 166 167 define i64 @non_bextr64(i64 %x) { 168 entry: 169 %shr = lshr i64 %x, 2 170 %and = and i64 %shr, 8589934590 171 ret i64 %and 172 ; CHECK-LABEL: non_bextr64: 173 ; CHECK: shrq $2 174 ; CHECK: movabsq $8589934590 175 ; CHECK: andq 176 } 177 178 define i32 @bzhi32(i32 %x, i32 %y) nounwind readnone { 179 %tmp = tail call i32 @llvm.x86.bmi.bzhi.32(i32 %x, i32 %y) 180 ret i32 %tmp 181 ; CHECK-LABEL: bzhi32: 182 ; CHECK: bzhil 183 } 184 185 define i32 @bzhi32_load(i32* %x, i32 %y) nounwind readnone { 186 %x1 = load i32, i32* %x 187 %tmp = tail call i32 @llvm.x86.bmi.bzhi.32(i32 %x1, i32 %y) 188 ret i32 %tmp 189 ; CHECK-LABEL: bzhi32_load: 190 ; CHECK: bzhil {{.*}}, ({{.*}}), {{.*}} 191 } 192 193 declare i32 @llvm.x86.bmi.bzhi.32(i32, i32) nounwind readnone 194 195 define i64 @bzhi64(i64 %x, i64 %y) nounwind readnone { 196 %tmp = tail call i64 @llvm.x86.bmi.bzhi.64(i64 %x, i64 %y) 197 ret i64 %tmp 198 ; CHECK-LABEL: bzhi64: 199 ; CHECK: bzhiq 200 } 201 202 declare i64 @llvm.x86.bmi.bzhi.64(i64, i64) nounwind readnone 203 204 define i32 @bzhi32b(i32 %x, i8 zeroext %index) #0 { 205 entry: 206 %conv = zext i8 %index to i32 207 %shl = shl i32 1, %conv 208 %sub = add nsw i32 %shl, -1 209 %and = and i32 %sub, %x 210 ret i32 %and 211 ; CHECK-LABEL: bzhi32b: 212 ; CHECK: bzhil 213 } 214 215 define i32 @bzhi32b_load(i32* %w, i8 zeroext %index) #0 { 216 entry: 217 %x = load i32, i32* %w 218 %conv = zext i8 %index to i32 219 %shl = shl i32 1, %conv 220 %sub = add nsw i32 %shl, -1 221 %and = and i32 %sub, %x 222 ret i32 %and 223 ; CHECK-LABEL: bzhi32b_load: 224 ; CHECK: bzhil {{.*}}, ({{.*}}), {{.*}} 225 } 226 227 define i32 @bzhi32c(i32 %x, i8 zeroext %index) #0 { 228 entry: 229 %conv = zext i8 %index to i32 230 %shl = shl i32 1, %conv 231 %sub = add nsw i32 %shl, -1 232 %and = and i32 %x, %sub 233 ret i32 %and 234 ; CHECK-LABEL: bzhi32c: 235 ; CHECK: bzhil 236 } 237 238 define i64 @bzhi64b(i64 %x, i8 zeroext %index) #0 { 239 entry: 240 %conv = zext i8 %index to i64 241 %shl = shl i64 1, %conv 242 %sub = add nsw i64 %shl, -1 243 %and = and i64 %x, %sub 244 ret i64 %and 245 ; CHECK-LABEL: bzhi64b: 246 ; CHECK: bzhiq 247 } 248 249 define i64 @bzhi64_constant_mask(i64 %x) #0 { 250 entry: 251 %and = and i64 %x, 4611686018427387903 252 ret i64 %and 253 ; CHECK-LABEL: bzhi64_constant_mask: 254 ; CHECK: movb $62, %al 255 ; CHECK: bzhiq %rax, %r[[ARG1:di|cx]], %rax 256 } 257 258 define i64 @bzhi64_small_constant_mask(i64 %x) #0 { 259 entry: 260 %and = and i64 %x, 2147483647 261 ret i64 %and 262 ; CHECK-LABEL: bzhi64_small_constant_mask: 263 ; CHECK: andl $2147483647, %e[[ARG1]] 264 } 265 266 define i32 @blsi32(i32 %x) nounwind readnone { 267 %tmp = sub i32 0, %x 268 %tmp2 = and i32 %x, %tmp 269 ret i32 %tmp2 270 ; CHECK-LABEL: blsi32: 271 ; CHECK: blsil 272 } 273 274 define i32 @blsi32_load(i32* %x) nounwind readnone { 275 %x1 = load i32, i32* %x 276 %tmp = sub i32 0, %x1 277 %tmp2 = and i32 %x1, %tmp 278 ret i32 %tmp2 279 ; CHECK-LABEL: blsi32_load: 280 ; CHECK: blsil ({{.*}}) 281 } 282 283 define i64 @blsi64(i64 %x) nounwind readnone { 284 %tmp = sub i64 0, %x 285 %tmp2 = and i64 %tmp, %x 286 ret i64 %tmp2 287 ; CHECK-LABEL: blsi64: 288 ; CHECK: blsiq 289 } 290 291 define i32 @blsmsk32(i32 %x) nounwind readnone { 292 %tmp = sub i32 %x, 1 293 %tmp2 = xor i32 %x, %tmp 294 ret i32 %tmp2 295 ; CHECK-LABEL: blsmsk32: 296 ; CHECK: blsmskl 297 } 298 299 define i32 @blsmsk32_load(i32* %x) nounwind readnone { 300 %x1 = load i32, i32* %x 301 %tmp = sub i32 %x1, 1 302 %tmp2 = xor i32 %x1, %tmp 303 ret i32 %tmp2 304 ; CHECK-LABEL: blsmsk32_load: 305 ; CHECK: blsmskl ({{.*}}) 306 } 307 308 define i64 @blsmsk64(i64 %x) nounwind readnone { 309 %tmp = sub i64 %x, 1 310 %tmp2 = xor i64 %tmp, %x 311 ret i64 %tmp2 312 ; CHECK-LABEL: blsmsk64: 313 ; CHECK: blsmskq 314 } 315 316 define i32 @blsr32(i32 %x) nounwind readnone { 317 %tmp = sub i32 %x, 1 318 %tmp2 = and i32 %x, %tmp 319 ret i32 %tmp2 320 ; CHECK-LABEL: blsr32: 321 ; CHECK: blsrl 322 } 323 324 define i32 @blsr32_load(i32* %x) nounwind readnone { 325 %x1 = load i32, i32* %x 326 %tmp = sub i32 %x1, 1 327 %tmp2 = and i32 %x1, %tmp 328 ret i32 %tmp2 329 ; CHECK-LABEL: blsr32_load: 330 ; CHECK: blsrl ({{.*}}) 331 } 332 333 define i64 @blsr64(i64 %x) nounwind readnone { 334 %tmp = sub i64 %x, 1 335 %tmp2 = and i64 %tmp, %x 336 ret i64 %tmp2 337 ; CHECK-LABEL: blsr64: 338 ; CHECK: blsrq 339 } 340 341 define i32 @pdep32(i32 %x, i32 %y) nounwind readnone { 342 %tmp = tail call i32 @llvm.x86.bmi.pdep.32(i32 %x, i32 %y) 343 ret i32 %tmp 344 ; CHECK-LABEL: pdep32: 345 ; CHECK: pdepl 346 } 347 348 define i32 @pdep32_load(i32 %x, i32* %y) nounwind readnone { 349 %y1 = load i32, i32* %y 350 %tmp = tail call i32 @llvm.x86.bmi.pdep.32(i32 %x, i32 %y1) 351 ret i32 %tmp 352 ; CHECK-LABEL: pdep32_load: 353 ; CHECK: pdepl ({{.*}}) 354 } 355 356 declare i32 @llvm.x86.bmi.pdep.32(i32, i32) nounwind readnone 357 358 define i64 @pdep64(i64 %x, i64 %y) nounwind readnone { 359 %tmp = tail call i64 @llvm.x86.bmi.pdep.64(i64 %x, i64 %y) 360 ret i64 %tmp 361 ; CHECK-LABEL: pdep64: 362 ; CHECK: pdepq 363 } 364 365 declare i64 @llvm.x86.bmi.pdep.64(i64, i64) nounwind readnone 366 367 define i32 @pext32(i32 %x, i32 %y) nounwind readnone { 368 %tmp = tail call i32 @llvm.x86.bmi.pext.32(i32 %x, i32 %y) 369 ret i32 %tmp 370 ; CHECK-LABEL: pext32: 371 ; CHECK: pextl 372 } 373 374 define i32 @pext32_load(i32 %x, i32* %y) nounwind readnone { 375 %y1 = load i32, i32* %y 376 %tmp = tail call i32 @llvm.x86.bmi.pext.32(i32 %x, i32 %y1) 377 ret i32 %tmp 378 ; CHECK-LABEL: pext32_load: 379 ; CHECK: pextl ({{.*}}) 380 } 381 382 declare i32 @llvm.x86.bmi.pext.32(i32, i32) nounwind readnone 383 384 define i64 @pext64(i64 %x, i64 %y) nounwind readnone { 385 %tmp = tail call i64 @llvm.x86.bmi.pext.64(i64 %x, i64 %y) 386 ret i64 %tmp 387 ; CHECK-LABEL: pext64: 388 ; CHECK: pextq 389 } 390 391 declare i64 @llvm.x86.bmi.pext.64(i64, i64) nounwind readnone 392 393