为什么我的 %xmm3 寄存器使用 vbroadcastsd 中的第一个参数而不是第四个?

问题描述 投票:0回答:1

我正在尝试在汇编中实现一个函数,该函数使用 SIMD 向量指令和寄存器进行一些基本计算。函数签名是

void map_poly_double_vec(double* input, double* output, uint64_t length, double a, double b, double c, double d);

出于某种原因,当我使用

vbroadcastsd %xmm3, %ymm6
double d
参数放入
%ymm6
的所有字段中时,程序会将
double a
参数插入其中。除了最后一个之外,其他
vbroadcastsd
指令都可以正常工作。我已经使用 GDB 尝试找出原因,但指令只是运行并使用第一个双参数而不是第四个。

这是我的汇编函数(AT&T 语法):

map_poly_double_vec:
    mov $0, %rcx

    vbroadcastsd %xmm0, %ymm3 #a
    vbroadcastsd %xmm1, %ymm4 #b
    vbroadcastsd %xmm2, %ymm5 #c
    vbroadcastsd %xmm3, %ymm6 #d

mpdv_loop:
    cmp %rdx, %rcx
    je mpdv_end

    vmovupd (%rdi, %rcx, 8), %ymm0
    vmovupd %ymm0, %ymm1

    vfmadd132pd %ymm3, %ymm4, %ymm1
    vfmadd132pd %ymm0, %ymm5, %ymm1
    vfmadd132pd %ymm1, %ymm6, %ymm0

    vmovupd %ymm0, (%rsi, %rcx, 8)

    add $4, %rcx
    jmp mpdv_loop

mpdv_end:
    ret

这就是我用来测试功能的。

#include <assert.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "lab11.h"

double* create_array(uint64_t length) {
    double* array = (double*)malloc(length * sizeof(double));
    if (array == NULL) {
        return NULL;
    }
    for (uint64_t i = 0; i < length; i++) {
        array[i] = ((double)rand() / RAND_MAX - 0.25);
    }
    return array;
}

void print_double_array(double* array, uint64_t length) {
    printf("{ ");
    for (uint64_t i = 0; i < length; i++) {
        printf("%.6g ", array[i]);
    }
    printf("}\n");
}

int main(void) {
    uint64_t length = 16;
    double* doubles1 = create_array(length);
    double* double_out = (double*)malloc(length * sizeof(double));

    printf("map_poly_double_vec result:\n");
    memset(double_out, 0, length * sizeof(double));
    map_poly_double_vec(doubles1, double_out, length, 4, 5, 6, 7);
    print_double_array(double_out, length);

    free(doubles1);
    free(double_out);
    return 0;
}

我应该得到什么:

{ 13.105 7.98257 12.2256 12.4544 14.3174 6.69849 7.55013 12.0089 7.17059 9.39815 8.66996 10.2085 7.76063 9.0004 15.0642 14.3989 }

我的功能得到了什么:

map_poly_double_vec result:
{ 10.105 4.98257 9.22559 9.45443 11.3174 3.69849 4.55013 9.00889 4.17059 6.39815 5.66996 7.20848 4.76063 6.0004 12.0642 11.3989 }
assembly x86 vectorization simd
1个回答
0
投票

请看第一期广播:

vbroadcastsd %xmm0, %ymm3 #a   <----
vbroadcastsd %xmm1, %ymm4 #b
vbroadcastsd %xmm2, %ymm5 #c
vbroadcastsd %xmm3, %ymm6 #d

现在,曾经保存参数

ymm3
d
已被参数
a
覆盖(已广播)。

所以

vbroadcastsd %xmm3, %ymm6
再次拿起论点
a

如果这是混乱的根源:

xmm
寄存器扩展到AVX中的
ymm
寄存器,
ymm
寄存器不是一组独立的新寄存器。每个256位
ymm
寄存器可以看作是两个128位的块,底部128位是对应的
xmm
寄存器,例如
xmm3
ymm3
的底部128位。

© www.soinside.com 2019 - 2024. All rights reserved.