【问题标题】:AVX2 support in GCC 5 and laterGCC 5 及更高版本中的 AVX2 支持
【发布时间】:2017-08-26 10:33:42
【问题描述】:

我写了下面的“T”类来加速对 使用 AVX2 的“字符集”。然后我发现它不起作用 当我使用“-O3”时,gcc 5 及更高版本。 任何人都可以帮助我将其追溯到一些编程结构 已知不能在最新的编译器/系统上工作?

这段代码的工作原理:底层结构(“_bits”)是一个 256 字节的块(对齐并分配给 AVX2),可以作为 char[256] 或 AVX2 元素访问,具体取决于元素是否为访问或整个事物用于向量操作。似乎它应该在 AVX2 平台上运行良好。没有?

这真的很难调试,因为“valgrind”说它是干净的, 而且我不能使用调试器(由于问题消失时 我删除“-O3”)。但我不满意只使用“|=” 解决方法,因为如果这段代码真的错了,那么我可能是 在其他地方犯同样的错误并搞砸一切 我开发!

有趣的是,“|”运营商有问题,但 “|=”没有。问题是否与从 一个函数?但我认为返回结构自 1990 年以来一直有效 什么的。

// g++ -std=c++11 -mavx2 -O3 gcc_fail.cpp

#include "assert.h"
#include "immintrin.h" // AVX

class T {
public:
  __m256i _bits[8];
  inline bool& operator[](unsigned char c)       {return ((bool*)_bits)[c];}
  inline bool  operator[](unsigned char c) const {return ((bool*)_bits)[c];}
  inline          T()                   {}
  inline explicit T(char const*);
  inline T     operator| (T const& b) const;
  inline T &   operator|=(T const& b);
  inline bool  operator! ()           const;
};

T::T(char const* s)
{
  _bits[0] = _bits[1] = _bits[2] = _bits[3] = _mm256_set1_epi32(0);
  _bits[4] = _bits[5] = _bits[6] = _bits[7] = _mm256_set1_epi32(0);
  char c;
  while ((c = *s++))
    (*this)[c] = true;
}

T T::operator| (T const& b) const
{
  T res;
  for (int i = 0; i < 8; i++)
    res._bits[i] = _mm256_or_si256(_bits[i], b._bits[i]);


  // FIXME why does the above code fail with -O3 in new gcc?
  for (int i=0; i<256; i++)
    assert(res[i] == ((*this)[i] || b[i]));
  // gcc 4.7.0 - PASS
  // gcc 4.7.2 - PASS
  // gcc 4.8.0 - PASS
  // gcc 4.9.2 - PASS
  // gcc 5.2.0 - FAIL
  // gcc 5.3.0 - FAIL
  // gcc 5.3.1 - FAIL
  // gcc 6.1.0 - FAIL


  return res;
}

T & T::operator|=(T const& b)
{
  for (int i = 0; i < 8; i++)
    _bits[i] = _mm256_or_si256(_bits[i], b._bits[i]);
  return *this;
}

bool T::operator! () const
{
  for (int i = 0; i < 8; i++)
    if (!_mm256_testz_si256(_bits[i], _bits[i]))
      return false;
  return true;
}

int Main()
{
  T sep (" ,\t\n");
  T end ("");
  return !(sep|end);
}

int main()
{
  return Main();
}

【问题讨论】:

  • 不知道是不是“bool*”?如果我将其更改为“char *”,它就可以工作。我没有意识到他们是不同的。正在研究...
  • 我正要说将bool 更改为unsigned char 可以解决您的问题。请记住,bool 只能保证能够保存 truefalse(通常为 01),并且允许编译器假设这样的变量不会保存任何其他内容。
  • @personal_cloud unsigned/signed char* 被编译器以bool* 没有的方式特殊处理。 char* 类型指针可以给任何东西起别名; bool* 指针没有。因此,当您将_bits(衰减为__m256d*)转换为bool* 时,编译器有权相信这个新指针实际上并不指向_bits,因为这两个指针并不相同类型。
  • 另外,我在 gdb 中看到的(当我最初追踪这个时)是 (bool*) 的东西工作得很好,但 AVX2 操作却没有。我将两个集合(其中一个非空)组合在一起,然后结果(通过编译单元传递,因此 gdb 可以看到它)为零。所以整个 bool* 事情可能是一个红鲱鱼(如果我可以仔细检查我在说什么的话)。
  • @IwillnotexistIdonotexist 我会接受你最后的解释。考虑到这一点,“bool*”的显着问题解释了我迄今为止看到的所有观察结果。鉴于启用了 -O3,发生的事情是我正在观察我认为是 operator| 的“输入”和“输出”,但实际上输出完全折叠为常数,以利用我拥有的 bool 属性不打算。所以AVX2没有错。 bool* 是。

标签: c++ gcc avx2


【解决方案1】:

您的代码的问题是使用bool*,而您应该使用unsigned char*,这允许GCC 5 继续进行指针别名优化。

由 GCC 4.8.5 和 5.3.1 生成的函数 Main() 的机器代码的两个转储位于附录中此答案的末尾以供参考。

看代码:

反编译

在序幕之后,T sep_bits 被初始化为零...

  _bits[0] = _bits[1] = _bits[2] = _bits[3] = _mm256_set1_epi32(0);
  _bits[4] = _bits[5] = _bits[6] = _bits[7] = _mm256_set1_epi32(0);

  40063d:       c5 fd 7f 44 24 60               vmovdqa %ymm0,0x60(%rsp)
  400643:       c5 fd 7f 44 24 40               vmovdqa %ymm0,0x40(%rsp)
  400649:       c5 fd 7f 44 24 20               vmovdqa %ymm0,0x20(%rsp)
  40064f:       c5 fd 7f 04 24                  vmovdqa %ymm0,(%rsp)
  400654:       c5 fd 7f 84 24 e0 00 00 00      vmovdqa %ymm0,0xe0(%rsp)
  40065d:       c5 fd 7f 84 24 c0 00 00 00      vmovdqa %ymm0,0xc0(%rsp)
  400666:       c5 fd 7f 84 24 a0 00 00 00      vmovdqa %ymm0,0xa0(%rsp)
  40066f:       c5 fd 7f 84 24 80 00 00 00      vmovdqa %ymm0,0x80(%rsp)

然后根据char* s循环写入。

  char c;
  while ((c = *s++))
    (*this)[c] = true;

  400680:       48 83 c2 01                     add    $0x1,%rdx
  400684:       c6 04 04 01                     movb   $0x1,(%rsp,%rax,1)
  400688:       0f b6 42 ff                     movzbl -0x1(%rdx),%eax
  40068c:       84 c0                           test   %al,%al
  40068e:       75 f0                           jne    400680 <_Z4Mainv+0x60>

然后,两个编译器都将T end 初始化为 0:

  400690:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  400694:       31 c0                           xor    %eax,%eax
  400696:       c5 fd 7f 84 24 60 01 00 00      vmovdqa %ymm0,0x160(%rsp)
  40069f:       c5 fd 7f 84 24 40 01 00 00      vmovdqa %ymm0,0x140(%rsp)
  4006a8:       c5 fd 7f 84 24 20 01 00 00      vmovdqa %ymm0,0x120(%rsp)
  4006b1:       c5 fd 7f 84 24 00 01 00 00      vmovdqa %ymm0,0x100(%rsp)
  4006ba:       c5 fd 7f 84 24 e0 01 00 00      vmovdqa %ymm0,0x1e0(%rsp)
  4006c3:       c5 fd 7f 84 24 c0 01 00 00      vmovdqa %ymm0,0x1c0(%rsp)
  4006cc:       c5 fd 7f 84 24 a0 01 00 00      vmovdqa %ymm0,0x1a0(%rsp)
  4006d5:       c5 fd 7f 84 24 80 01 00 00      vmovdqa %ymm0,0x180(%rsp)

然后,两个编译器都优化了 _mm256_or_si256() 操作,因为已知 T end0。但是,GCC 4.8.5 T sep 复制到T res(这在计算上是当你将任何东西或任何东西变成零变量时会发生什么),而 GCC 5.3.1 初始化@987654336 @ 到0。它有权这样做,因为在您的operator [] 方法中,您将__m256i* 类型的指针转​​换为bool*,并且允许编译器假定指针不别名。因此,在 GCC 4.8.5 中您会看到

  4006de:       c5 fd 6f 04 24                  vmovdqa (%rsp),%ymm0
  4006e3:       c5 fd 7f 84 24 00 02 00 00      vmovdqa %ymm0,0x200(%rsp)
  4006ec:       c5 fd 6f 44 24 20               vmovdqa 0x20(%rsp),%ymm0
  4006f2:       c5 fd 7f 84 24 20 02 00 00      vmovdqa %ymm0,0x220(%rsp)
  4006fb:       c5 fd 6f 44 24 40               vmovdqa 0x40(%rsp),%ymm0
  400701:       c5 fd 7f 84 24 40 02 00 00      vmovdqa %ymm0,0x240(%rsp)
  40070a:       c5 fd 6f 44 24 60               vmovdqa 0x60(%rsp),%ymm0
  400710:       c5 fd 7f 84 24 60 02 00 00      vmovdqa %ymm0,0x260(%rsp)
  400719:       c5 fd 6f 84 24 80 00 00 00      vmovdqa 0x80(%rsp),%ymm0
  400722:       c5 fd 7f 84 24 80 02 00 00      vmovdqa %ymm0,0x280(%rsp)
  40072b:       c5 fd 6f 84 24 a0 00 00 00      vmovdqa 0xa0(%rsp),%ymm0
  400734:       c5 fd 7f 84 24 a0 02 00 00      vmovdqa %ymm0,0x2a0(%rsp)
  40073d:       c5 fd 6f 84 24 c0 00 00 00      vmovdqa 0xc0(%rsp),%ymm0
  400746:       c5 fd 7f 84 24 c0 02 00 00      vmovdqa %ymm0,0x2c0(%rsp)
  40074f:       c5 fd 6f 84 24 e0 00 00 00      vmovdqa 0xe0(%rsp),%ymm0
  400758:       c5 fd 7f 84 24 e0 02 00 00      vmovdqa %ymm0,0x2e0(%rsp)

在 GCC 5.3.1 中您会看到

  4006fa:       c5 fd 7f 85 f0 fe ff ff         vmovdqa %ymm0,-0x110(%rbp)
  400702:       c5 fd 7f 85 10 ff ff ff         vmovdqa %ymm0,-0xf0(%rbp)
  40070a:       c5 fd 7f 85 30 ff ff ff         vmovdqa %ymm0,-0xd0(%rbp)
  400712:       c5 fd 7f 85 50 ff ff ff         vmovdqa %ymm0,-0xb0(%rbp)
  40071a:       c5 fd 7f 85 70 ff ff ff         vmovdqa %ymm0,-0x90(%rbp)
  400722:       c5 fd 7f 45 90                  vmovdqa %ymm0,-0x70(%rbp)
  400727:       c5 fd 7f 45 b0                  vmovdqa %ymm0,-0x50(%rbp)
  40072c:       c5 fd 7f 45 d0                  vmovdqa %ymm0,-0x30(%rbp)

因此,assert() 的读取失败。

标准对指针别名的规定:

ISO C++11 在下一节中提到了别名,它明确了__m256i* 类型的变量不能使用bool* 访问,但可以使用char*/unsigned char* 访问:

§ 3.10 左值和右值 [basic.lval]

[...]

如果程序尝试通过以下类型之一以外的左值访问对象的存储值,则行为未定义:[52]

  • 对象的动态类型,
  • 对象动态类型的 cv 限定版本,
  • 与对象的动态类型类似(如 4.4 中定义)的类型,
  • 对应于对象动态类型的有符号或无符号类型,
  • 一种有符号或无符号类型,对应于对象动态类型的 cv 限定版本,
  • 一种聚合或联合类型,在其元素或非静态数据成员(递归地包括子聚合或包含联合的元素或非静态数据成员)中包含上述类型之一,
  • 一种类型,它是对象动态类型的(可能是 cv 限定的)基类类型,
  • charunsigned char 类型。

52) 此列表的目的是指定对象可能或可能不具有别名的情况。

附录

GCC 4.8.5:

0000000000400620 <_Z4Mainv>:
  400620:       55                              push   %rbp
  400621:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  400625:       ba e5 08 40 00                  mov    $0x4008e5,%edx
  40062a:       b8 20 00 00 00                  mov    $0x20,%eax
  40062f:       48 89 e5                        mov    %rsp,%rbp
  400632:       48 83 e4 e0                     and    $0xffffffffffffffe0,%rsp
  400636:       48 81 ec 00 03 00 00            sub    $0x300,%rsp
  40063d:       c5 fd 7f 44 24 60               vmovdqa %ymm0,0x60(%rsp)
  400643:       c5 fd 7f 44 24 40               vmovdqa %ymm0,0x40(%rsp)
  400649:       c5 fd 7f 44 24 20               vmovdqa %ymm0,0x20(%rsp)
  40064f:       c5 fd 7f 04 24                  vmovdqa %ymm0,(%rsp)
  400654:       c5 fd 7f 84 24 e0 00 00 00      vmovdqa %ymm0,0xe0(%rsp)
  40065d:       c5 fd 7f 84 24 c0 00 00 00      vmovdqa %ymm0,0xc0(%rsp)
  400666:       c5 fd 7f 84 24 a0 00 00 00      vmovdqa %ymm0,0xa0(%rsp)
  40066f:       c5 fd 7f 84 24 80 00 00 00      vmovdqa %ymm0,0x80(%rsp)
  400678:       0f 1f 84 00 00 00 00 00         nopl   0x0(%rax,%rax,1)
  400680:       48 83 c2 01                     add    $0x1,%rdx
  400684:       c6 04 04 01                     movb   $0x1,(%rsp,%rax,1)
  400688:       0f b6 42 ff                     movzbl -0x1(%rdx),%eax
  40068c:       84 c0                           test   %al,%al
  40068e:       75 f0                           jne    400680 <_Z4Mainv+0x60>
  400690:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  400694:       31 c0                           xor    %eax,%eax
  400696:       c5 fd 7f 84 24 60 01 00 00      vmovdqa %ymm0,0x160(%rsp)
  40069f:       c5 fd 7f 84 24 40 01 00 00      vmovdqa %ymm0,0x140(%rsp)
  4006a8:       c5 fd 7f 84 24 20 01 00 00      vmovdqa %ymm0,0x120(%rsp)
  4006b1:       c5 fd 7f 84 24 00 01 00 00      vmovdqa %ymm0,0x100(%rsp)
  4006ba:       c5 fd 7f 84 24 e0 01 00 00      vmovdqa %ymm0,0x1e0(%rsp)
  4006c3:       c5 fd 7f 84 24 c0 01 00 00      vmovdqa %ymm0,0x1c0(%rsp)
  4006cc:       c5 fd 7f 84 24 a0 01 00 00      vmovdqa %ymm0,0x1a0(%rsp)
  4006d5:       c5 fd 7f 84 24 80 01 00 00      vmovdqa %ymm0,0x180(%rsp)
  4006de:       c5 fd 6f 04 24                  vmovdqa (%rsp),%ymm0
  4006e3:       c5 fd 7f 84 24 00 02 00 00      vmovdqa %ymm0,0x200(%rsp)
  4006ec:       c5 fd 6f 44 24 20               vmovdqa 0x20(%rsp),%ymm0
  4006f2:       c5 fd 7f 84 24 20 02 00 00      vmovdqa %ymm0,0x220(%rsp)
  4006fb:       c5 fd 6f 44 24 40               vmovdqa 0x40(%rsp),%ymm0
  400701:       c5 fd 7f 84 24 40 02 00 00      vmovdqa %ymm0,0x240(%rsp)
  40070a:       c5 fd 6f 44 24 60               vmovdqa 0x60(%rsp),%ymm0
  400710:       c5 fd 7f 84 24 60 02 00 00      vmovdqa %ymm0,0x260(%rsp)
  400719:       c5 fd 6f 84 24 80 00 00 00      vmovdqa 0x80(%rsp),%ymm0
  400722:       c5 fd 7f 84 24 80 02 00 00      vmovdqa %ymm0,0x280(%rsp)
  40072b:       c5 fd 6f 84 24 a0 00 00 00      vmovdqa 0xa0(%rsp),%ymm0
  400734:       c5 fd 7f 84 24 a0 02 00 00      vmovdqa %ymm0,0x2a0(%rsp)
  40073d:       c5 fd 6f 84 24 c0 00 00 00      vmovdqa 0xc0(%rsp),%ymm0
  400746:       c5 fd 7f 84 24 c0 02 00 00      vmovdqa %ymm0,0x2c0(%rsp)
  40074f:       c5 fd 6f 84 24 e0 00 00 00      vmovdqa 0xe0(%rsp),%ymm0
  400758:       c5 fd 7f 84 24 e0 02 00 00      vmovdqa %ymm0,0x2e0(%rsp)
  400761:       0f 1f 80 00 00 00 00            nopl   0x0(%rax)
  400768:       80 3c 04 00                     cmpb   $0x0,(%rsp,%rax,1)
  40076c:       0f b6 8c 04 00 02 00 00         movzbl 0x200(%rsp,%rax,1),%ecx
  400774:       ba 01 00 00 00                  mov    $0x1,%edx
  400779:       75 08                           jne    400783 <_Z4Mainv+0x163>
  40077b:       0f b6 94 04 00 01 00 00         movzbl 0x100(%rsp,%rax,1),%edx
  400783:       38 d1                           cmp    %dl,%cl
  400785:       0f 85 b2 00 00 00               jne    40083d <_Z4Mainv+0x21d>
  40078b:       48 83 c0 01                     add    $0x1,%rax
  40078f:       48 3d 00 01 00 00               cmp    $0x100,%rax
  400795:       75 d1                           jne    400768 <_Z4Mainv+0x148>
  400797:       c5 fd 6f 8c 24 00 02 00 00      vmovdqa 0x200(%rsp),%ymm1
  4007a0:       31 c0                           xor    %eax,%eax
  4007a2:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  4007a7:       0f 94 c0                        sete   %al
  4007aa:       0f 85 88 00 00 00               jne    400838 <_Z4Mainv+0x218>
  4007b0:       c5 fd 6f 8c 24 20 02 00 00      vmovdqa 0x220(%rsp),%ymm1
  4007b9:       31 c0                           xor    %eax,%eax
  4007bb:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  4007c0:       0f 94 c0                        sete   %al
  4007c3:       75 73                           jne    400838 <_Z4Mainv+0x218>
  4007c5:       c5 fd 6f 8c 24 40 02 00 00      vmovdqa 0x240(%rsp),%ymm1
  4007ce:       31 c0                           xor    %eax,%eax
  4007d0:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  4007d5:       0f 94 c0                        sete   %al
  4007d8:       75 5e                           jne    400838 <_Z4Mainv+0x218>
  4007da:       c5 fd 6f 8c 24 60 02 00 00      vmovdqa 0x260(%rsp),%ymm1
  4007e3:       31 c0                           xor    %eax,%eax
  4007e5:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  4007ea:       0f 94 c0                        sete   %al
  4007ed:       75 49                           jne    400838 <_Z4Mainv+0x218>
  4007ef:       c5 fd 6f 8c 24 80 02 00 00      vmovdqa 0x280(%rsp),%ymm1
  4007f8:       31 c0                           xor    %eax,%eax
  4007fa:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  4007ff:       0f 94 c0                        sete   %al
  400802:       75 34                           jne    400838 <_Z4Mainv+0x218>
  400804:       c5 fd 6f 8c 24 a0 02 00 00      vmovdqa 0x2a0(%rsp),%ymm1
  40080d:       31 c0                           xor    %eax,%eax
  40080f:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  400814:       0f 94 c0                        sete   %al
  400817:       75 1f                           jne    400838 <_Z4Mainv+0x218>
  400819:       c5 fd 6f 8c 24 c0 02 00 00      vmovdqa 0x2c0(%rsp),%ymm1
  400822:       31 c0                           xor    %eax,%eax
  400824:       c4 e2 7d 17 c9                  vptest %ymm1,%ymm1
  400829:       0f 94 c0                        sete   %al
  40082c:       75 0a                           jne    400838 <_Z4Mainv+0x218>
  40082e:       31 c0                           xor    %eax,%eax
  400830:       c4 e2 7d 17 c0                  vptest %ymm0,%ymm0
  400835:       0f 94 c0                        sete   %al
  400838:       c5 f8 77                        vzeroupper 
  40083b:       c9                              leaveq 
  40083c:       c3                              retq   
  40083d:       b9 20 09 40 00                  mov    $0x400920,%ecx
  400842:       ba 26 00 00 00                  mov    $0x26,%edx
  400847:       be e9 08 40 00                  mov    $0x4008e9,%esi
  40084c:       bf f8 08 40 00                  mov    $0x4008f8,%edi
  400851:       c5 f8 77                        vzeroupper 
  400854:       e8 97 fc ff ff                  callq  4004f0 <__assert_fail@plt>
  400859:       0f 1f 80 00 00 00 00            nopl   0x0(%rax)

GCC 5:

0000000000400630 <_Z4Mainv>:
  400630:       4c 8d 54 24 08                  lea    0x8(%rsp),%r10
  400635:       48 83 e4 e0                     and    $0xffffffffffffffe0,%rsp
  400639:       b8 20 00 00 00                  mov    $0x20,%eax
  40063e:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  400642:       ba 25 08 40 00                  mov    $0x400825,%edx
  400647:       41 ff 72 f8                     pushq  -0x8(%r10)
  40064b:       55                              push   %rbp
  40064c:       48 89 e5                        mov    %rsp,%rbp
  40064f:       41 52                           push   %r10
  400651:       48 81 ec 08 03 00 00            sub    $0x308,%rsp
  400658:       c5 fd 7f 85 50 fd ff ff         vmovdqa %ymm0,-0x2b0(%rbp)
  400660:       c5 fd 7f 85 30 fd ff ff         vmovdqa %ymm0,-0x2d0(%rbp)
  400668:       c5 fd 7f 85 10 fd ff ff         vmovdqa %ymm0,-0x2f0(%rbp)
  400670:       c5 fd 7f 85 f0 fc ff ff         vmovdqa %ymm0,-0x310(%rbp)
  400678:       c5 fd 7f 85 d0 fd ff ff         vmovdqa %ymm0,-0x230(%rbp)
  400680:       c5 fd 7f 85 b0 fd ff ff         vmovdqa %ymm0,-0x250(%rbp)
  400688:       c5 fd 7f 85 90 fd ff ff         vmovdqa %ymm0,-0x270(%rbp)
  400690:       c5 fd 7f 85 70 fd ff ff         vmovdqa %ymm0,-0x290(%rbp)
  400698:       0f 1f 84 00 00 00 00 00         nopl   0x0(%rax,%rax,1)
  4006a0:       48 83 c2 01                     add    $0x1,%rdx
  4006a4:       c6 84 05 f0 fc ff ff 01         movb   $0x1,-0x310(%rbp,%rax,1)
  4006ac:       0f b6 42 ff                     movzbl -0x1(%rdx),%eax
  4006b0:       84 c0                           test   %al,%al
  4006b2:       75 ec                           jne    4006a0 <_Z4Mainv+0x70>
  4006b4:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  4006b8:       31 c0                           xor    %eax,%eax
  4006ba:       c5 fd 7f 85 50 fe ff ff         vmovdqa %ymm0,-0x1b0(%rbp)
  4006c2:       c5 fd 7f 85 30 fe ff ff         vmovdqa %ymm0,-0x1d0(%rbp)
  4006ca:       c5 fd 7f 85 10 fe ff ff         vmovdqa %ymm0,-0x1f0(%rbp)
  4006d2:       c5 fd 7f 85 f0 fd ff ff         vmovdqa %ymm0,-0x210(%rbp)
  4006da:       c5 fd 7f 85 d0 fe ff ff         vmovdqa %ymm0,-0x130(%rbp)
  4006e2:       c5 fd 7f 85 b0 fe ff ff         vmovdqa %ymm0,-0x150(%rbp)
  4006ea:       c5 fd 7f 85 90 fe ff ff         vmovdqa %ymm0,-0x170(%rbp)
  4006f2:       c5 fd 7f 85 70 fe ff ff         vmovdqa %ymm0,-0x190(%rbp)
  4006fa:       c5 fd 7f 85 f0 fe ff ff         vmovdqa %ymm0,-0x110(%rbp)
  400702:       c5 fd 7f 85 10 ff ff ff         vmovdqa %ymm0,-0xf0(%rbp)
  40070a:       c5 fd 7f 85 30 ff ff ff         vmovdqa %ymm0,-0xd0(%rbp)
  400712:       c5 fd 7f 85 50 ff ff ff         vmovdqa %ymm0,-0xb0(%rbp)
  40071a:       c5 fd 7f 85 70 ff ff ff         vmovdqa %ymm0,-0x90(%rbp)
  400722:       c5 fd 7f 45 90                  vmovdqa %ymm0,-0x70(%rbp)
  400727:       c5 fd 7f 45 b0                  vmovdqa %ymm0,-0x50(%rbp)
  40072c:       c5 fd 7f 45 d0                  vmovdqa %ymm0,-0x30(%rbp)
  400731:       0f 1f 80 00 00 00 00            nopl   0x0(%rax)
  400738:       0f b6 94 05 f0 fc ff ff         movzbl -0x310(%rbp,%rax,1),%edx
  400740:       0f b6 8c 05 f0 fe ff ff         movzbl -0x110(%rbp,%rax,1),%ecx
  400748:       84 d2                           test   %dl,%dl
  40074a:       75 08                           jne    400754 <_Z4Mainv+0x124>
  40074c:       0f b6 94 05 f0 fd ff ff         movzbl -0x210(%rbp,%rax,1),%edx
  400754:       38 d1                           cmp    %dl,%cl
  400756:       75 2c                           jne    400784 <_Z4Mainv+0x154>
  400758:       48 83 c0 01                     add    $0x1,%rax
  40075c:       48 3d 00 01 00 00               cmp    $0x100,%rax
  400762:       75 d4                           jne    400738 <_Z4Mainv+0x108>
  400764:       c5 f9 ef c0                     vpxor  %xmm0,%xmm0,%xmm0
  400768:       31 c0                           xor    %eax,%eax
  40076a:       c4 e2 7d 17 c0                  vptest %ymm0,%ymm0
  40076f:       0f 94 c0                        sete   %al
  400772:       c5 f8 77                        vzeroupper 
  400775:       48 81 c4 08 03 00 00            add    $0x308,%rsp
  40077c:       41 5a                           pop    %r10
  40077e:       5d                              pop    %rbp
  40077f:       49 8d 62 f8                     lea    -0x8(%r10),%rsp
  400783:       c3                              retq   
  400784:       b9 60 08 40 00                  mov    $0x400860,%ecx
  400789:       ba 26 00 00 00                  mov    $0x26,%edx
  40078e:       be 29 08 40 00                  mov    $0x400829,%esi
  400793:       bf 38 08 40 00                  mov    $0x400838,%edi
  400798:       c5 f8 77                        vzeroupper 
  40079b:       e8 50 fd ff ff                  callq  4004f0 <__assert_fail@plt>

【讨论】:

  • 出于好奇,是否有任何指向bool* 的指针别名?我尝试使用 (bool*)(char*)_bits 进行投射,但没有成功。
  • @personal_cloud void*char* 被允许为其他任何东西起别名,除了这两个和bool* 之外的任何东西都被允许别名为bool*。即使您在途中将bool* 转换为char*,也不会改变任何事情;别名规则根据您用于访问的指针类型而成立。
  • 这是一个很好的答案,但它缺少对编译器用来优化unsigned char 的别名规则的一些解释。您非常清楚地说明了它正在在做什么,但可以通过添加几句话来改善答案why(有点像您之前的评论)。
  • @IwillnotexistIdonotexist void * 没有实际意义,因为别名规则是根据执行访问的取消引用表达式定义的,您不能取消引用 void *。也可以使用任何字符类型,例如unsigned char,以及 const 变种等。
  • 我尝试将char* 别名为指向struct {bool b;} 的指针,但这似乎有同样的问题:直接分配给b 不可见为chars。也许编译器再次看到这样的代码只是另一个 bool*char* 演员...迷人。
猜你喜欢
  • 2020-09-13
  • 2022-11-08
  • 2014-08-18
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
  • 1970-01-01
  • 2021-04-12
  • 2018-04-04
相关资源
最近更新 更多