1 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=-bmi < %s | FileCheck %s --check-prefix=CHECK-NOBMI 3 ; RUN: llc -mtriple=x86_64-unknown-linux-gnu -mattr=+bmi < %s | FileCheck %s --check-prefix=CHECK-BMI 4 5 ; https://bugs.llvm.org/show_bug.cgi?id=37104 6 7 ; X: [byte1][byte0] 8 ; Y: [byte3][byte2] 9 10 define i8 @out8_constmask(i8 %x, i8 %y) { 11 ; CHECK-NOBMI-LABEL: out8_constmask: 12 ; CHECK-NOBMI: # %bb.0: 13 ; CHECK-NOBMI-NEXT: andb $15, %dil 14 ; CHECK-NOBMI-NEXT: andb $-16, %sil 15 ; CHECK-NOBMI-NEXT: orb %dil, %sil 16 ; CHECK-NOBMI-NEXT: movl %esi, %eax 17 ; CHECK-NOBMI-NEXT: retq 18 ; 19 ; CHECK-BMI-LABEL: out8_constmask: 20 ; CHECK-BMI: # %bb.0: 21 ; CHECK-BMI-NEXT: andb $15, %dil 22 ; CHECK-BMI-NEXT: andb $-16, %sil 23 ; CHECK-BMI-NEXT: orb %dil, %sil 24 ; CHECK-BMI-NEXT: movl %esi, %eax 25 ; CHECK-BMI-NEXT: retq 26 %mx = and i8 %x, 15 27 %my = and i8 %y, -16 28 %r = or i8 %mx, %my 29 ret i8 %r 30 } 31 32 define i16 @out16_constmask(i16 %x, i16 %y) { 33 ; CHECK-NOBMI-LABEL: out16_constmask: 34 ; CHECK-NOBMI: # %bb.0: 35 ; CHECK-NOBMI-NEXT: movzbl %dil, %eax 36 ; CHECK-NOBMI-NEXT: andl $-256, %esi 37 ; CHECK-NOBMI-NEXT: orl %esi, %eax 38 ; CHECK-NOBMI-NEXT: # kill: def $ax killed $ax killed $eax 39 ; CHECK-NOBMI-NEXT: retq 40 ; 41 ; CHECK-BMI-LABEL: out16_constmask: 42 ; CHECK-BMI: # %bb.0: 43 ; CHECK-BMI-NEXT: movzbl %dil, %eax 44 ; CHECK-BMI-NEXT: andl $-256, %esi 45 ; CHECK-BMI-NEXT: orl %esi, %eax 46 ; CHECK-BMI-NEXT: # kill: def $ax killed $ax killed $eax 47 ; CHECK-BMI-NEXT: retq 48 %mx = and i16 %x, 255 49 %my = and i16 %y, -256 50 %r = or i16 %mx, %my 51 ret i16 %r 52 } 53 54 define i32 @out32_constmask(i32 %x, i32 %y) { 55 ; CHECK-NOBMI-LABEL: out32_constmask: 56 ; CHECK-NOBMI: # %bb.0: 57 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 58 ; CHECK-NOBMI-NEXT: andl $-65536, %esi # imm = 0xFFFF0000 59 ; CHECK-NOBMI-NEXT: orl %esi, %eax 60 ; CHECK-NOBMI-NEXT: retq 61 ; 62 ; CHECK-BMI-LABEL: out32_constmask: 63 ; CHECK-BMI: # %bb.0: 64 ; CHECK-BMI-NEXT: movzwl %di, %eax 65 ; CHECK-BMI-NEXT: andl $-65536, %esi # imm = 0xFFFF0000 66 ; CHECK-BMI-NEXT: orl %esi, %eax 67 ; CHECK-BMI-NEXT: retq 68 %mx = and i32 %x, 65535 69 %my = and i32 %y, -65536 70 %r = or i32 %mx, %my 71 ret i32 %r 72 } 73 74 define i64 @out64_constmask(i64 %x, i64 %y) { 75 ; CHECK-NOBMI-LABEL: out64_constmask: 76 ; CHECK-NOBMI: # %bb.0: 77 ; CHECK-NOBMI-NEXT: movl %edi, %ecx 78 ; CHECK-NOBMI-NEXT: movabsq $-4294967296, %rax # imm = 0xFFFFFFFF00000000 79 ; CHECK-NOBMI-NEXT: andq %rsi, %rax 80 ; CHECK-NOBMI-NEXT: orq %rcx, %rax 81 ; CHECK-NOBMI-NEXT: retq 82 ; 83 ; CHECK-BMI-LABEL: out64_constmask: 84 ; CHECK-BMI: # %bb.0: 85 ; CHECK-BMI-NEXT: movl %edi, %ecx 86 ; CHECK-BMI-NEXT: movabsq $-4294967296, %rax # imm = 0xFFFFFFFF00000000 87 ; CHECK-BMI-NEXT: andq %rsi, %rax 88 ; CHECK-BMI-NEXT: orq %rcx, %rax 89 ; CHECK-BMI-NEXT: retq 90 %mx = and i64 %x, 4294967295 91 %my = and i64 %y, -4294967296 92 %r = or i64 %mx, %my 93 ret i64 %r 94 } 95 96 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 97 ; Should be the same as the previous one. 98 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 99 100 define i8 @in8_constmask(i8 %x, i8 %y) { 101 ; CHECK-NOBMI-LABEL: in8_constmask: 102 ; CHECK-NOBMI: # %bb.0: 103 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 104 ; CHECK-NOBMI-NEXT: andb $15, %dil 105 ; CHECK-NOBMI-NEXT: xorb %dil, %sil 106 ; CHECK-NOBMI-NEXT: movl %esi, %eax 107 ; CHECK-NOBMI-NEXT: retq 108 ; 109 ; CHECK-BMI-LABEL: in8_constmask: 110 ; CHECK-BMI: # %bb.0: 111 ; CHECK-BMI-NEXT: xorl %esi, %edi 112 ; CHECK-BMI-NEXT: andb $15, %dil 113 ; CHECK-BMI-NEXT: xorb %dil, %sil 114 ; CHECK-BMI-NEXT: movl %esi, %eax 115 ; CHECK-BMI-NEXT: retq 116 %n0 = xor i8 %x, %y 117 %n1 = and i8 %n0, 15 118 %r = xor i8 %n1, %y 119 ret i8 %r 120 } 121 122 define i16 @in16_constmask(i16 %x, i16 %y) { 123 ; CHECK-NOBMI-LABEL: in16_constmask: 124 ; CHECK-NOBMI: # %bb.0: 125 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 126 ; CHECK-NOBMI-NEXT: movzbl %dil, %eax 127 ; CHECK-NOBMI-NEXT: xorl %esi, %eax 128 ; CHECK-NOBMI-NEXT: # kill: def $ax killed $ax killed $eax 129 ; CHECK-NOBMI-NEXT: retq 130 ; 131 ; CHECK-BMI-LABEL: in16_constmask: 132 ; CHECK-BMI: # %bb.0: 133 ; CHECK-BMI-NEXT: xorl %esi, %edi 134 ; CHECK-BMI-NEXT: movzbl %dil, %eax 135 ; CHECK-BMI-NEXT: xorl %esi, %eax 136 ; CHECK-BMI-NEXT: # kill: def $ax killed $ax killed $eax 137 ; CHECK-BMI-NEXT: retq 138 %n0 = xor i16 %x, %y 139 %n1 = and i16 %n0, 255 140 %r = xor i16 %n1, %y 141 ret i16 %r 142 } 143 144 define i32 @in32_constmask(i32 %x, i32 %y) { 145 ; CHECK-NOBMI-LABEL: in32_constmask: 146 ; CHECK-NOBMI: # %bb.0: 147 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 148 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 149 ; CHECK-NOBMI-NEXT: xorl %esi, %eax 150 ; CHECK-NOBMI-NEXT: retq 151 ; 152 ; CHECK-BMI-LABEL: in32_constmask: 153 ; CHECK-BMI: # %bb.0: 154 ; CHECK-BMI-NEXT: xorl %esi, %edi 155 ; CHECK-BMI-NEXT: movzwl %di, %eax 156 ; CHECK-BMI-NEXT: xorl %esi, %eax 157 ; CHECK-BMI-NEXT: retq 158 %n0 = xor i32 %x, %y 159 %n1 = and i32 %n0, 65535 160 %r = xor i32 %n1, %y 161 ret i32 %r 162 } 163 164 define i64 @in64_constmask(i64 %x, i64 %y) { 165 ; CHECK-NOBMI-LABEL: in64_constmask: 166 ; CHECK-NOBMI: # %bb.0: 167 ; CHECK-NOBMI-NEXT: movl %esi, %eax 168 ; CHECK-NOBMI-NEXT: xorl %edi, %eax 169 ; CHECK-NOBMI-NEXT: xorq %rsi, %rax 170 ; CHECK-NOBMI-NEXT: retq 171 ; 172 ; CHECK-BMI-LABEL: in64_constmask: 173 ; CHECK-BMI: # %bb.0: 174 ; CHECK-BMI-NEXT: movl %esi, %eax 175 ; CHECK-BMI-NEXT: xorl %edi, %eax 176 ; CHECK-BMI-NEXT: xorq %rsi, %rax 177 ; CHECK-BMI-NEXT: retq 178 %n0 = xor i64 %x, %y 179 %n1 = and i64 %n0, 4294967295 180 %r = xor i64 %n1, %y 181 ret i64 %r 182 } 183 184 ; ============================================================================ ; 185 ; Constant Commutativity tests. 186 ; ============================================================================ ; 187 188 define i32 @in_constmask_commutativity_0_1(i32 %x, i32 %y) { 189 ; CHECK-NOBMI-LABEL: in_constmask_commutativity_0_1: 190 ; CHECK-NOBMI: # %bb.0: 191 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 192 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 193 ; CHECK-NOBMI-NEXT: xorl %esi, %eax 194 ; CHECK-NOBMI-NEXT: retq 195 ; 196 ; CHECK-BMI-LABEL: in_constmask_commutativity_0_1: 197 ; CHECK-BMI: # %bb.0: 198 ; CHECK-BMI-NEXT: xorl %esi, %edi 199 ; CHECK-BMI-NEXT: movzwl %di, %eax 200 ; CHECK-BMI-NEXT: xorl %esi, %eax 201 ; CHECK-BMI-NEXT: retq 202 %n0 = xor i32 %x, %y 203 %n1 = and i32 %n0, 65535 204 %r = xor i32 %y, %n1 ; swapped 205 ret i32 %r 206 } 207 208 define i32 @in_constmask_commutativity_1_0(i32 %x, i32 %y) { 209 ; CHECK-NOBMI-LABEL: in_constmask_commutativity_1_0: 210 ; CHECK-NOBMI: # %bb.0: 211 ; CHECK-NOBMI-NEXT: xorl %edi, %esi 212 ; CHECK-NOBMI-NEXT: movzwl %si, %eax 213 ; CHECK-NOBMI-NEXT: xorl %edi, %eax 214 ; CHECK-NOBMI-NEXT: retq 215 ; 216 ; CHECK-BMI-LABEL: in_constmask_commutativity_1_0: 217 ; CHECK-BMI: # %bb.0: 218 ; CHECK-BMI-NEXT: xorl %edi, %esi 219 ; CHECK-BMI-NEXT: movzwl %si, %eax 220 ; CHECK-BMI-NEXT: xorl %edi, %eax 221 ; CHECK-BMI-NEXT: retq 222 %n0 = xor i32 %x, %y 223 %n1 = and i32 %n0, 65535 224 %r = xor i32 %n1, %x ; %x instead of %y 225 ret i32 %r 226 } 227 228 define i32 @in_constmask_commutativity_1_1(i32 %x, i32 %y) { 229 ; CHECK-NOBMI-LABEL: in_constmask_commutativity_1_1: 230 ; CHECK-NOBMI: # %bb.0: 231 ; CHECK-NOBMI-NEXT: xorl %edi, %esi 232 ; CHECK-NOBMI-NEXT: movzwl %si, %eax 233 ; CHECK-NOBMI-NEXT: xorl %edi, %eax 234 ; CHECK-NOBMI-NEXT: retq 235 ; 236 ; CHECK-BMI-LABEL: in_constmask_commutativity_1_1: 237 ; CHECK-BMI: # %bb.0: 238 ; CHECK-BMI-NEXT: xorl %edi, %esi 239 ; CHECK-BMI-NEXT: movzwl %si, %eax 240 ; CHECK-BMI-NEXT: xorl %edi, %eax 241 ; CHECK-BMI-NEXT: retq 242 %n0 = xor i32 %x, %y 243 %n1 = and i32 %n0, 65535 244 %r = xor i32 %x, %n1 ; swapped, %x instead of %y 245 ret i32 %r 246 } 247 248 ; ============================================================================ ; 249 ; Y is an 'and' too. 250 ; ============================================================================ ; 251 252 define i32 @in_complex_y0_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 253 ; CHECK-NOBMI-LABEL: in_complex_y0_constmask: 254 ; CHECK-NOBMI: # %bb.0: 255 ; CHECK-NOBMI-NEXT: andl %edx, %esi 256 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 257 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 258 ; CHECK-NOBMI-NEXT: xorl %esi, %eax 259 ; CHECK-NOBMI-NEXT: retq 260 ; 261 ; CHECK-BMI-LABEL: in_complex_y0_constmask: 262 ; CHECK-BMI: # %bb.0: 263 ; CHECK-BMI-NEXT: andl %edx, %esi 264 ; CHECK-BMI-NEXT: xorl %esi, %edi 265 ; CHECK-BMI-NEXT: movzwl %di, %eax 266 ; CHECK-BMI-NEXT: xorl %esi, %eax 267 ; CHECK-BMI-NEXT: retq 268 %y = and i32 %y_hi, %y_low 269 %n0 = xor i32 %x, %y 270 %n1 = and i32 %n0, 65535 271 %r = xor i32 %n1, %y 272 ret i32 %r 273 } 274 275 define i32 @in_complex_y1_constmask(i32 %x, i32 %y_hi, i32 %y_low) { 276 ; CHECK-NOBMI-LABEL: in_complex_y1_constmask: 277 ; CHECK-NOBMI: # %bb.0: 278 ; CHECK-NOBMI-NEXT: andl %edx, %esi 279 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 280 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 281 ; CHECK-NOBMI-NEXT: xorl %esi, %eax 282 ; CHECK-NOBMI-NEXT: retq 283 ; 284 ; CHECK-BMI-LABEL: in_complex_y1_constmask: 285 ; CHECK-BMI: # %bb.0: 286 ; CHECK-BMI-NEXT: andl %edx, %esi 287 ; CHECK-BMI-NEXT: xorl %esi, %edi 288 ; CHECK-BMI-NEXT: movzwl %di, %eax 289 ; CHECK-BMI-NEXT: xorl %esi, %eax 290 ; CHECK-BMI-NEXT: retq 291 %y = and i32 %y_hi, %y_low 292 %n0 = xor i32 %x, %y 293 %n1 = and i32 %n0, 65535 294 %r = xor i32 %y, %n1 295 ret i32 %r 296 } 297 298 ; ============================================================================ ; 299 ; Negative tests. Should not be folded. 300 ; ============================================================================ ; 301 302 ; Multi-use tests. 303 304 declare void @use32(i32) nounwind 305 306 define i32 @in_multiuse_A_constmask(i32 %x, i32 %y, i32 %z) nounwind { 307 ; CHECK-NOBMI-LABEL: in_multiuse_A_constmask: 308 ; CHECK-NOBMI: # %bb.0: 309 ; CHECK-NOBMI-NEXT: pushq %rbp 310 ; CHECK-NOBMI-NEXT: pushq %rbx 311 ; CHECK-NOBMI-NEXT: pushq %rax 312 ; CHECK-NOBMI-NEXT: movl %esi, %ebx 313 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 314 ; CHECK-NOBMI-NEXT: movzwl %di, %ebp 315 ; CHECK-NOBMI-NEXT: movl %ebp, %edi 316 ; CHECK-NOBMI-NEXT: callq use32 317 ; CHECK-NOBMI-NEXT: xorl %ebx, %ebp 318 ; CHECK-NOBMI-NEXT: movl %ebp, %eax 319 ; CHECK-NOBMI-NEXT: addq $8, %rsp 320 ; CHECK-NOBMI-NEXT: popq %rbx 321 ; CHECK-NOBMI-NEXT: popq %rbp 322 ; CHECK-NOBMI-NEXT: retq 323 ; 324 ; CHECK-BMI-LABEL: in_multiuse_A_constmask: 325 ; CHECK-BMI: # %bb.0: 326 ; CHECK-BMI-NEXT: pushq %rbp 327 ; CHECK-BMI-NEXT: pushq %rbx 328 ; CHECK-BMI-NEXT: pushq %rax 329 ; CHECK-BMI-NEXT: movl %esi, %ebx 330 ; CHECK-BMI-NEXT: xorl %esi, %edi 331 ; CHECK-BMI-NEXT: movzwl %di, %ebp 332 ; CHECK-BMI-NEXT: movl %ebp, %edi 333 ; CHECK-BMI-NEXT: callq use32 334 ; CHECK-BMI-NEXT: xorl %ebx, %ebp 335 ; CHECK-BMI-NEXT: movl %ebp, %eax 336 ; CHECK-BMI-NEXT: addq $8, %rsp 337 ; CHECK-BMI-NEXT: popq %rbx 338 ; CHECK-BMI-NEXT: popq %rbp 339 ; CHECK-BMI-NEXT: retq 340 %n0 = xor i32 %x, %y 341 %n1 = and i32 %n0, 65535 342 call void @use32(i32 %n1) 343 %r = xor i32 %n1, %y 344 ret i32 %r 345 } 346 347 define i32 @in_multiuse_B_constmask(i32 %x, i32 %y, i32 %z) nounwind { 348 ; CHECK-NOBMI-LABEL: in_multiuse_B_constmask: 349 ; CHECK-NOBMI: # %bb.0: 350 ; CHECK-NOBMI-NEXT: pushq %rbp 351 ; CHECK-NOBMI-NEXT: pushq %rbx 352 ; CHECK-NOBMI-NEXT: pushq %rax 353 ; CHECK-NOBMI-NEXT: movl %esi, %ebx 354 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 355 ; CHECK-NOBMI-NEXT: movzwl %di, %ebp 356 ; CHECK-NOBMI-NEXT: callq use32 357 ; CHECK-NOBMI-NEXT: xorl %ebx, %ebp 358 ; CHECK-NOBMI-NEXT: movl %ebp, %eax 359 ; CHECK-NOBMI-NEXT: addq $8, %rsp 360 ; CHECK-NOBMI-NEXT: popq %rbx 361 ; CHECK-NOBMI-NEXT: popq %rbp 362 ; CHECK-NOBMI-NEXT: retq 363 ; 364 ; CHECK-BMI-LABEL: in_multiuse_B_constmask: 365 ; CHECK-BMI: # %bb.0: 366 ; CHECK-BMI-NEXT: pushq %rbp 367 ; CHECK-BMI-NEXT: pushq %rbx 368 ; CHECK-BMI-NEXT: pushq %rax 369 ; CHECK-BMI-NEXT: movl %esi, %ebx 370 ; CHECK-BMI-NEXT: xorl %esi, %edi 371 ; CHECK-BMI-NEXT: movzwl %di, %ebp 372 ; CHECK-BMI-NEXT: callq use32 373 ; CHECK-BMI-NEXT: xorl %ebx, %ebp 374 ; CHECK-BMI-NEXT: movl %ebp, %eax 375 ; CHECK-BMI-NEXT: addq $8, %rsp 376 ; CHECK-BMI-NEXT: popq %rbx 377 ; CHECK-BMI-NEXT: popq %rbp 378 ; CHECK-BMI-NEXT: retq 379 %n0 = xor i32 %x, %y 380 %n1 = and i32 %n0, 65535 381 call void @use32(i32 %n0) 382 %r = xor i32 %n1, %y 383 ret i32 %r 384 } 385 386 ; Various bad variants 387 388 define i32 @n0_badconstmask(i32 %x, i32 %y) { 389 ; CHECK-NOBMI-LABEL: n0_badconstmask: 390 ; CHECK-NOBMI: # %bb.0: 391 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 392 ; CHECK-NOBMI-NEXT: andl $-65535, %esi # imm = 0xFFFF0001 393 ; CHECK-NOBMI-NEXT: orl %esi, %eax 394 ; CHECK-NOBMI-NEXT: retq 395 ; 396 ; CHECK-BMI-LABEL: n0_badconstmask: 397 ; CHECK-BMI: # %bb.0: 398 ; CHECK-BMI-NEXT: movzwl %di, %eax 399 ; CHECK-BMI-NEXT: andl $-65535, %esi # imm = 0xFFFF0001 400 ; CHECK-BMI-NEXT: orl %esi, %eax 401 ; CHECK-BMI-NEXT: retq 402 %mx = and i32 %x, 65535 403 %my = and i32 %y, -65535 ; instead of -65536 404 %r = or i32 %mx, %my 405 ret i32 %r 406 } 407 408 define i32 @n1_thirdvar_constmask(i32 %x, i32 %y, i32 %z) { 409 ; CHECK-NOBMI-LABEL: n1_thirdvar_constmask: 410 ; CHECK-NOBMI: # %bb.0: 411 ; CHECK-NOBMI-NEXT: xorl %esi, %edi 412 ; CHECK-NOBMI-NEXT: movzwl %di, %eax 413 ; CHECK-NOBMI-NEXT: xorl %edx, %eax 414 ; CHECK-NOBMI-NEXT: retq 415 ; 416 ; CHECK-BMI-LABEL: n1_thirdvar_constmask: 417 ; CHECK-BMI: # %bb.0: 418 ; CHECK-BMI-NEXT: xorl %esi, %edi 419 ; CHECK-BMI-NEXT: movzwl %di, %eax 420 ; CHECK-BMI-NEXT: xorl %edx, %eax 421 ; CHECK-BMI-NEXT: retq 422 %n0 = xor i32 %x, %y 423 %n1 = and i32 %n0, 65535 424 %r = xor i32 %n1, %z ; instead of %y 425 ret i32 %r 426 } 427