首页 > 解决方案 > 用于堆栈与堆访问的 gcc 程序集

问题描述

这里有两个指向 Godblot 的链接(由实际代码替换),在一种情况下,我将在堆栈上声明的数组的元素相加,第二个和在堆上分配的数组的元素相加(请忽略 malloc 的不正确大小)。

堆(-std=c++17 -O3 -mavx2):

#include <stdio.h>
#include <stdlib.h>
int access(){
    int sum;
    //int vec[10000];
    int *vec = (int*)malloc(10000*sizeof(int));

    for(int i=0;i<10000;i++)
        sum+=vec[i];

    return sum;
}

堆组装:

access():
  push rbp
  mov edi, 10000
  mov rbp, rsp
  and rsp, -32
  call malloc
  vpxor xmm1, xmm1, xmm1
  lea rdx, [rax+40000]
.L2:
  vmovdqu xmm2, XMMWORD PTR [rax]
  vinserti128 ymm0, ymm2, XMMWORD PTR [rax+16], 0x1
  add rax, 32
  vpaddd ymm1, ymm1, ymm0
  cmp rdx, rax
  jne .L2
  vmovdqa xmm0, xmm1
  vextracti128 xmm1, ymm1, 0x1
  vpaddd xmm1, xmm0, xmm1
  vpsrldq xmm0, xmm1, 8
  vpaddd xmm0, xmm1, xmm0
  vpsrldq xmm1, xmm0, 4
  vpaddd xmm0, xmm0, xmm1
  vmovd eax, xmm0
  vzeroupper
  leave
  ret

对于堆栈 C 代码,只需使用在先前 C 代码中注释的堆栈上声明的 vec。

Stack() 汇编代码:

access():
  push rbp
  vpxor xmm0, xmm0, xmm0
  mov rbp, rsp
  and rsp, -32
  sub rsp, 39880
  lea rax, [rsp-120]
  lea rdx, [rsp+39880]
.L2:
  vpaddd ymm0, ymm0, YMMWORD PTR [rax]
  add rax, 32
  cmp rdx, rax
  jne .L2
  vmovdqa xmm1, xmm0
  vextracti128 xmm0, ymm0, 0x1
  vpaddd xmm0, xmm1, xmm0
  vpsrldq xmm1, xmm0, 8
  vpaddd xmm0, xmm0, xmm1
  vpsrldq xmm1, xmm0, 4
  vpaddd xmm0, xmm0, xmm1
  vmovd eax, xmm0
  vzeroupper
  leave
  ret

知道为什么在堆情况下它需要使用更多指令。它似乎也跳过了存储在 xmm2 寄存器中的 16 个字节的数据?

如果我们将编译器参数从 -mavx2 更改为 -mavx512f 或 remove 完全删除它,代码看起来相似。gcc 中继版本有问题吗?

Clang 似乎展开了循环并生成了有意义的代码。

标签: gccassemblymemory-alignment

解决方案


推荐阅读