Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- .globl Ax
- Ax:
- .LFB0:
- # A - rdi
- # x - rsi
- # b - rdx
- # n - rcx
- # если n <= 0, то выход
- testl %ecx, %ecx
- jle .L26
- # x -> rax
- movq %rsi, %rax
- pushq %r15
- pushq %r14
- # rax << 60
- salq $60, %rax
- # n -> r14
- movl %ecx, %r14d
- pushq %r13
- # rax >> 63, получение 4-го байта (2^3 = 8)
- # в результате в rax, 1 -- если выравнивание адреса по 8-ми байтам, 0 - по 16
- # некоторые команды из SSE работают лишь с выровненными по 16 байт адресами
- shrq $63, %rax
- pushq %r12
- pushq %rbp
- cmpl %ecx, %eax
- pushq %rbx
- # min(n, eax) -> eax
- # eax всегда <= 1, а n > 0, поэтому бессмысленная операция
- cmova %ecx, %eax
- cmpl $4, %ecx
- # если n <= 4, то n -> eax
- cmovbe %ecx, %eax
- # r11 = 0
- xorl %r11d, %r11d
- # ?
- movl %eax, %eax
- # r14 = n - eax
- # в eax - количество элементов, которые будут просчитаны без распараллеливания
- # r14 -- количество оставшихся элементов, которые можно попытаться распараллелить
- subl %eax, %r14d
- # rax -> rbx
- movq %rax, %rbx
- # rax = 8, если выравнивание по 8 байтам, иначе - 0
- salq $3, %rax
- # ebp = (r14 - 2)
- leal -2(%r14), %ebp
- # r13 = адрес первого элемента в векторе x, который можно попытаться распараллелить
- leaq (%rsi,%rax), %r13
- # rax -> -16(%rsp)
- movq %rax, -16(%rsp)
- # ebp = [r14 / 2] - 1
- shrl %ebp
- # ebp = [r14 / 2]
- addl $1, %ebp
- # r15 = [r14 / 2] * 2
- leal (%rbp,%rbp), %r15d
- .p2align 4,,10
- .p2align 3
- .L6:
- # ebx - количество элементов, которые нужно просчитать без распараллеливания
- testl %ebx, %ebx
- # A[i] -> r10
- movq (%rdi,%r11,8), %r10
- je .L11
- # A[i][0] -> xmm0
- # sd -> single double
- movsd (%r10), %xmm0
- cmpl $1, %ebx
- movl $1, %r8d
- # A[i][0] * x[0] -> xmm0
- mulsd (%rsi), %xmm0
- # если нужно просчитать лишь один элемент без распараллеливания, то выходим на распараллеливание
- je .L8
- # аналогично для j = 1, 2, 3
- movsd 8(%r10), %xmm1
- cmpl $2, %ebx
- movl $2, %r8d
- mulsd 8(%rsi), %xmm1
- addsd %xmm1, %xmm0
- je .L8
- movsd 16(%r10), %xmm1
- cmpl $3, %ebx
- movl $3, %r8d
- mulsd 16(%rsi), %xmm1
- addsd %xmm1, %xmm0
- je .L8
- movsd 24(%rsi), %xmm1
- movl $4, %r8d
- mulsd 24(%r10), %xmm1
- addsd %xmm1, %xmm0
- .L8:
- # если количество посчитанных без распараллеливания чисел == n, то идем на следующий шаг (по i)
- cmpl %ecx, %ebx
- je .L9
- .L7:
- # в r14 -- количество элементов, которые можно попытаться распараллелить
- # если r14 = 1, то сразу переходим на частных случай для нечетного количества
- cmpl $1, %r14d
- je .L10
- # rax = 8, если выравнивание по 8 байтам, иначе - 0
- movq -16(%rsp), %rax
- # xmm2 = 0
- pxor %xmm2, %xmm2
- # r9 = 0
- xorl %r9d, %r9d
- # r12 = &A[i][1], если выравнивание по 8 байтам, иначе - &A[i][0]
- leaq (%r10,%rax), %r12
- # eax = 0
- xorl %eax, %eax
- .L4:
- # Переместить два double (A[i][j], A[i][j + 1]) в xmm1
- # apd - aligned packed double, необходимо выравнивание по 16 байтам
- movapd (%r12,%rax), %xmm1
- # r9 -- количество посчитанных пар
- addl $1, %r9d
- # в r13 - адрес первого элемента в x для распараллеливания
- # умножить A[i][j] * x[j], A[i][j + 1] * x[j + 1]
- mulpd 0(%r13,%rax), %xmm1
- # j += 2
- addq $16, %rax
- # ebp -- количество пар
- cmpl %r9d, %ebp
- # xmm2 + (A[i][j] * x[j], A[i][j + 1] * x[j + 1])
- addpd %xmm1, %xmm2
- # если посчитали еще не все пары, то считаем дальше
- ja .L4
- # сложить горизонтально xmm2
- haddpd %xmm2, %xmm2
- # количество пар * 2 + количество элементов, посчитанных без распараллеливания
- addl %r15d, %r8d
- # если количество пар * 2 == количество элементов, которые пытались распараллелить, то переходим на следующую итерацию
- # иначе, если количество элементов нечетное, то считаем последний отдельно в L9
- cmpl %r15d, %r14d
- # складываем элементы, посчитанные параллельно и отдельно
- addsd %xmm2, %xmm0
- je .L9
- .L10:
- # расширить r8d до r8
- movslq %r8d, %r8
- # считаем для последнего элемента
- movsd (%r10,%r8,8), %xmm1
- mulsd (%rsi,%r8,8), %xmm1
- addsd %xmm1, %xmm0
- .L9:
- # перемещаем результат в b[i]
- movsd %xmm0, (%rdx,%r11,8)
- # i++
- addq $1, %r11
- # если i < n, то идем на следующую итерацию
- cmpl %r11d, %ecx
- jg .L6
- popq %rbx
- popq %rbp
- popq %r12
- popq %r13
- popq %r14
- popq %r15
- ret
- .L11:
- xorl %r8d, %r8d
- pxor %xmm0, %xmm0
- jmp .L7
- .L26:
- rep ret
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement