| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py |
| ; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+sse4.2 | FileCheck %s |
| |
| ; widen a v3i1 to v4i1 to do a vector load/store. We would previously |
| ; reconstruct the said v3i1 from the first element of the vector by filling all |
| ; the lanes of the vector with that first element, which was obviously wrong. |
| ; This was done in the type-legalizing of the DAG, when legalizing the load. |
| |
| ; Function Attrs: argmemonly nounwind readonly |
| declare <3 x i32> @llvm.masked.load.v3i32.p1v3i32(<3 x i32> addrspace(1)*, i32, <3 x i1>, <3 x i32>) |
| |
| ; Function Attrs: argmemonly nounwind |
| declare void @llvm.masked.store.v3i32.p1v3i32(<3 x i32>, <3 x i32> addrspace(1)*, i32, <3 x i1>) |
| |
| define <3 x i32> @masked_load_v3(i32 addrspace(1)*, <3 x i1>) { |
| ; CHECK-LABEL: masked_load_v3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: andb $1, %sil |
| ; CHECK-NEXT: andb $1, %dl |
| ; CHECK-NEXT: addb %dl, %dl |
| ; CHECK-NEXT: orb %sil, %dl |
| ; CHECK-NEXT: andb $1, %cl |
| ; CHECK-NEXT: shlb $2, %cl |
| ; CHECK-NEXT: orb %dl, %cl |
| ; CHECK-NEXT: testb $1, %cl |
| ; CHECK-NEXT: # implicit-def: $xmm0 |
| ; CHECK-NEXT: jne .LBB0_1 |
| ; CHECK-NEXT: # %bb.2: # %else |
| ; CHECK-NEXT: testb $2, %cl |
| ; CHECK-NEXT: jne .LBB0_3 |
| ; CHECK-NEXT: .LBB0_4: # %else2 |
| ; CHECK-NEXT: testb $4, %cl |
| ; CHECK-NEXT: jne .LBB0_5 |
| ; CHECK-NEXT: .LBB0_6: # %else5 |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: .LBB0_1: # %cond.load |
| ; CHECK-NEXT: movd {{.*#+}} xmm0 = mem[0],zero,zero,zero |
| ; CHECK-NEXT: testb $2, %cl |
| ; CHECK-NEXT: je .LBB0_4 |
| ; CHECK-NEXT: .LBB0_3: # %cond.load1 |
| ; CHECK-NEXT: pinsrd $1, 4(%rdi), %xmm0 |
| ; CHECK-NEXT: testb $4, %cl |
| ; CHECK-NEXT: je .LBB0_6 |
| ; CHECK-NEXT: .LBB0_5: # %cond.load4 |
| ; CHECK-NEXT: pinsrd $2, 8(%rdi), %xmm0 |
| ; CHECK-NEXT: retq |
| entry: |
| %2 = bitcast i32 addrspace(1)* %0 to <3 x i32> addrspace(1)* |
| %3 = call <3 x i32> @llvm.masked.load.v3i32.p1v3i32(<3 x i32> addrspace(1)* %2, i32 4, <3 x i1> %1, <3 x i32> undef) |
| ret <3 x i32> %3 |
| } |
| |
| define void @masked_store4_v3(<3 x i32>, i32 addrspace(1)*, <3 x i1>) { |
| ; CHECK-LABEL: masked_store4_v3: |
| ; CHECK: # %bb.0: # %entry |
| ; CHECK-NEXT: andb $1, %sil |
| ; CHECK-NEXT: andb $1, %dl |
| ; CHECK-NEXT: addb %dl, %dl |
| ; CHECK-NEXT: orb %sil, %dl |
| ; CHECK-NEXT: andb $1, %cl |
| ; CHECK-NEXT: shlb $2, %cl |
| ; CHECK-NEXT: orb %dl, %cl |
| ; CHECK-NEXT: testb $1, %cl |
| ; CHECK-NEXT: jne .LBB1_1 |
| ; CHECK-NEXT: # %bb.2: # %else |
| ; CHECK-NEXT: testb $2, %cl |
| ; CHECK-NEXT: jne .LBB1_3 |
| ; CHECK-NEXT: .LBB1_4: # %else2 |
| ; CHECK-NEXT: testb $4, %cl |
| ; CHECK-NEXT: jne .LBB1_5 |
| ; CHECK-NEXT: .LBB1_6: # %else4 |
| ; CHECK-NEXT: retq |
| ; CHECK-NEXT: .LBB1_1: # %cond.store |
| ; CHECK-NEXT: movss %xmm0, (%rdi) |
| ; CHECK-NEXT: testb $2, %cl |
| ; CHECK-NEXT: je .LBB1_4 |
| ; CHECK-NEXT: .LBB1_3: # %cond.store1 |
| ; CHECK-NEXT: extractps $1, %xmm0, 4(%rdi) |
| ; CHECK-NEXT: testb $4, %cl |
| ; CHECK-NEXT: je .LBB1_6 |
| ; CHECK-NEXT: .LBB1_5: # %cond.store3 |
| ; CHECK-NEXT: extractps $2, %xmm0, 8(%rdi) |
| ; CHECK-NEXT: retq |
| entry: |
| %3 = bitcast i32 addrspace(1)* %1 to <3 x i32> addrspace(1)* |
| call void @llvm.masked.store.v3i32.p1v3i32(<3 x i32> %0, <3 x i32> addrspace(1)* %3, i32 4, <3 x i1> %2) |
| ret void |
| } |
| |
| define void @local_load_v3i1(i32 addrspace(1)* %out, i32 addrspace(1)* %in, <3 x i1>* %predicate_ptr) nounwind { |
| ; CHECK-LABEL: local_load_v3i1: |
| ; CHECK: # %bb.0: |
| ; CHECK-NEXT: pushq %rbp |
| ; CHECK-NEXT: pushq %r15 |
| ; CHECK-NEXT: pushq %r14 |
| ; CHECK-NEXT: pushq %rbx |
| ; CHECK-NEXT: pushq %rax |
| ; CHECK-NEXT: movq %rdi, %r14 |
| ; CHECK-NEXT: movb (%rdx), %al |
| ; CHECK-NEXT: movl %eax, %ecx |
| ; CHECK-NEXT: shrb %cl |
| ; CHECK-NEXT: andb $1, %cl |
| ; CHECK-NEXT: movl %eax, %edx |
| ; CHECK-NEXT: shrb $2, %dl |
| ; CHECK-NEXT: andb $1, %al |
| ; CHECK-NEXT: movzbl %al, %ebp |
| ; CHECK-NEXT: movzbl %dl, %r15d |
| ; CHECK-NEXT: movzbl %cl, %ebx |
| ; CHECK-NEXT: movq %rsi, %rdi |
| ; CHECK-NEXT: movl %ebp, %esi |
| ; CHECK-NEXT: movl %ebx, %edx |
| ; CHECK-NEXT: movl %r15d, %ecx |
| ; CHECK-NEXT: callq masked_load_v3 |
| ; CHECK-NEXT: movq %r14, %rdi |
| ; CHECK-NEXT: movl %ebp, %esi |
| ; CHECK-NEXT: movl %ebx, %edx |
| ; CHECK-NEXT: movl %r15d, %ecx |
| ; CHECK-NEXT: callq masked_store4_v3 |
| ; CHECK-NEXT: addq $8, %rsp |
| ; CHECK-NEXT: popq %rbx |
| ; CHECK-NEXT: popq %r14 |
| ; CHECK-NEXT: popq %r15 |
| ; CHECK-NEXT: popq %rbp |
| ; CHECK-NEXT: retq |
| %predicate = load <3 x i1>, <3 x i1>* %predicate_ptr |
| %load1 = call <3 x i32> @masked_load_v3(i32 addrspace(1)* %in, <3 x i1> %predicate) |
| call void @masked_store4_v3(<3 x i32> %load1, i32 addrspace(1)* %out, <3 x i1> %predicate) |
| ret void |
| } |