如何防止gcc优化破坏rep movsb代码? 问题创建我自己的memcpy的动机:用于重现问题的简单代码test.c编译并运行摘要

问题描述

我试图用rep movsb指令创建我的memcpy代码。禁用优化后,它可以与任何大小完美配合。但是,当我启用优化后,它无法按预期运行。

问题

  1. 如何防止gcc优化破坏rep movsb代码
  2. 我的代码是否有问题,导致未定义的行为?

创建我自己的memcpy的动机:

我从Intel® 64 and IA-32 Architectures Optimization Reference Manual 第3.7.6节中了解了用于memcpy的增强型movsb。我来到了libc源代码,我看到来自libc的认memcpy使用SSE而不是movsb

因此,我想比较Memcpy SSE指令 rep movsb 性能。但是现在,我发现它有问题。

用于重现问题的简单代码(test.c)

#include <stdio.h>
#include <string.h>

inline static void *my_memcpy(
  register void *dest,register const void *src,register size_t n
) {
  __asm__ volatile(
    "mov %0,%%rdi;"
    "mov %1,%%rsi;"
    "mov %2,%%rcx;"
    "rep movsb;"
    :
    : "r"(dest),"r"(src),"r"(n)
    : "rdi","rsi","rcx"
  );
  return dest;
}

#define to_boolean_str(A) ((A) ? "true" : "false")

int main()
{
  char src[32];
  char dst[32];

  memset(src,'a',32);
  memset(dst,'b',32);

  my_memcpy(dst,src,1);
  printf("%s\n",to_boolean_str(!memcmp(dst,1)));

  my_memcpy(dst,2);
  printf("%s\n",2)));

  my_memcpy(dst,3);
  printf("%s\n",3)));

  return 0;
}

编译并运行

ammarfaizi2@integral:~$ gcc --version
gcc (Ubuntu 9.3.0-10ubuntu2) 9.3.0
copyright (C) 2019 Free Software Foundation,Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or fitness FOR A PARTIculaR PURPOSE.

ammarfaizi2@integral:~$ gcc -O0 test.c -o test && ./test
true
true
true
ammarfaizi2@integral:~$ gcc -O1 test.c -o test && ./test
false
true
true
ammarfaizi2@integral:~$ gcc -O2 test.c -o test && ./test
false
true
true
ammarfaizi2@integral:~$ gcc -O3 test.c -o test && ./test
false
true
true
ammarfaizi2@integral:~$ 

摘要

如果启用了优化,则

my_memcpy(dst,1);会导致错误的行为。

解决方法

按照书面规定,您的asm约束并不反映asm语句可以修改内存,因此编译器可以针对在destsrc上读取或写入内存的操作自由地对其进行重新排序。您需要将"memory"添加到清单列表中。

正如其他人所述,您还应该编辑约束以避免mov。如果这样做的话,您还需要在约束条件中表示事实,即asm现在修改了其参数(例如,使它们成为双重输入/输出)并备份了dest的值,以便您可以返回它。因此,您可能会跳过此改进,直到您开始进行改进并了解约束的工作原理为止。