C++ &引用;假设;通用条款中的条款

C++ &引用;假设;通用条款中的条款,c++,c,gcc,built-in,gcc4.9,C++,C,Gcc,Built In,Gcc4.9,gcc(最新版本:4.8、4.9)是否有类似于icc支持的内置的\uuuu ascape()的“假设”条款? 例如,假设(n%8==0)从gcc 4.8.2开始,gcc中没有与_u-ascape()等效的代码。我不知道为什么——这会非常有用。马夫索建议: #define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0) 这是一个老把戏,至少早在2010年就知道了,而且可能更久。编译器通常会优化“cond”

gcc(最新版本:4.8、4.9)是否有类似于icc支持的内置的
\uuuu ascape()
的“假设”条款?
例如,假设(n%8==0)

从gcc 4.8.2开始,gcc中没有与_u-ascape()等效的代码。我不知道为什么——这会非常有用。马夫索建议:

#define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0)

这是一个老把戏,至少早在2010年就知道了,而且可能更久。编译器通常会优化“cond”的计算,因为cond为false的任何计算都是未定义的。但是,如果“cond”包含对不透明(非内联)函数的调用,则它似乎不会优化掉它。编译器必须假设不透明调用可能有副作用(例如,更改全局),并且不能优化调用,尽管它可以优化结果上的任何计算和分支。因此,宏方法充其量只是部分解决方案。

在您的示例中,您希望告知编译器
N
是8的倍数。 只需插入行即可完成此操作

N = N & 0xFFFFFFF8;
在代码中(如果
N
是32位整数)。这不会改变,因为
N
是8的倍数, 但是自从GCC4.9编译器 似乎知道
N
是这行后面8的倍数

下一个示例显示了这一点,其中添加了两个浮点向量:

int add_a(float * restrict a, float * restrict b, int N)
{
    a = (float*)__builtin_assume_aligned(a, 32);
    b = (float*)__builtin_assume_aligned(b, 32);
    N = N & 0xFFFFFFF8; 
    for (int i = 0; i < N; i++){
        a[i] = a[i] + b[i];
    }
    return 0;
}


int add_b(float * restrict a, float * restrict b, int N)
{
    a = (float*)__builtin_assume_aligned(a, 32);
    b = (float*)__builtin_assume_aligned(b, 32);
    for (int i = 0; i < N; i++){
        a[i] = a[i] + b[i];
    }
    return 0;
}
使用函数
add_b
,需要20多条额外指令来处理以下情况:
N
不是8的倍数:

add_b:
  test edx, edx
  jle .L17
  lea ecx, [rdx-4]
  lea r8d, [rdx-1]
  shr ecx, 2
  add ecx, 1
  cmp r8d, 2
  lea eax, [0+rcx*4]
  jbe .L16
  xor r8d, r8d
  xor r9d, r9d
.L11:
  movaps xmm0, XMMWORD PTR [rdi+r8]
  add r9d, 1
  addps xmm0, XMMWORD PTR [rsi+r8]
  movaps XMMWORD PTR [rdi+r8], xmm0
  add r8, 16
  cmp ecx, r9d
  ja .L11
  cmp eax, edx
  je .L17
.L10:
  movsx r8, eax
  lea rcx, [rdi+r8*4]
  movss xmm0, DWORD PTR [rcx]
  addss xmm0, DWORD PTR [rsi+r8*4]
  movss DWORD PTR [rcx], xmm0
  lea ecx, [rax+1]
  cmp edx, ecx
  jle .L17
  movsx rcx, ecx
  add eax, 2
  lea r8, [rdi+rcx*4]
  cmp edx, eax
  movss xmm0, DWORD PTR [r8]
  addss xmm0, DWORD PTR [rsi+rcx*4]
  movss DWORD PTR [r8], xmm0
  jle .L17
  cdqe
  lea rdx, [rdi+rax*4]
  movss xmm0, DWORD PTR [rdx]
  addss xmm0, DWORD PTR [rsi+rax*4]
  movss DWORD PTR [rdx], xmm0
.L17:
  xor eax, eax
  ret
.L16:
  xor eax, eax
  jmp .L10

请参阅。

请参阅:
\u内置\u expect
?看起来它是用于分支预测的,我需要提示向量器循环计数是一个好的数字。我没有访问icc的权限,它与Visual C__Ascape()相同吗?()From:
#define uuu-aspect(cond)do{if(!(cond))uu-builtin u-unreachable()}而(0)
。不过,我还没有测试Gcc是否将其用于优化。在Gcc 5.2和6.1中也遇到了这个问题。当基础表达式不透明时,cond不会被优化掉。即使cond被包装在纯函数中,您也会认为编译器可以自由地进行优化。此外,我还没有找到一种方法来检测编译器是否优化了cond。这意味着使用此宏时,编译器可能会无声地添加不必要的代码,从而影响性能。对于透明表达式,宏运行得非常好。@user377178“即使cond被包装在纯函数中”-这将是一个严重的性能问题,请仍然复制。这也会导致编译器插入代码来执行按位和。
add_b:
  test edx, edx
  jle .L17
  lea ecx, [rdx-4]
  lea r8d, [rdx-1]
  shr ecx, 2
  add ecx, 1
  cmp r8d, 2
  lea eax, [0+rcx*4]
  jbe .L16
  xor r8d, r8d
  xor r9d, r9d
.L11:
  movaps xmm0, XMMWORD PTR [rdi+r8]
  add r9d, 1
  addps xmm0, XMMWORD PTR [rsi+r8]
  movaps XMMWORD PTR [rdi+r8], xmm0
  add r8, 16
  cmp ecx, r9d
  ja .L11
  cmp eax, edx
  je .L17
.L10:
  movsx r8, eax
  lea rcx, [rdi+r8*4]
  movss xmm0, DWORD PTR [rcx]
  addss xmm0, DWORD PTR [rsi+r8*4]
  movss DWORD PTR [rcx], xmm0
  lea ecx, [rax+1]
  cmp edx, ecx
  jle .L17
  movsx rcx, ecx
  add eax, 2
  lea r8, [rdi+rcx*4]
  cmp edx, eax
  movss xmm0, DWORD PTR [r8]
  addss xmm0, DWORD PTR [rsi+rcx*4]
  movss DWORD PTR [r8], xmm0
  jle .L17
  cdqe
  lea rdx, [rdi+rax*4]
  movss xmm0, DWORD PTR [rdx]
  addss xmm0, DWORD PTR [rsi+rax*4]
  movss DWORD PTR [rdx], xmm0
.L17:
  xor eax, eax
  ret
.L16:
  xor eax, eax
  jmp .L10