c/c++语言开发共享gcc中的“假设”条款

gcc(最新版本: __assume() )是否具有类似于icc所支持的__assume()内置的“assume”子句? 例如, __assume( n % 8 == 0 );

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

     N = N & 0xFFFFFFF8; 

    在你的代码中(如果N是32位整数)。 这不会改变N ,因为N是8的倍数,但是由于GCC 4.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; } 

    使用gcc -m64 -std=c99 -O3 ,gcc版本4.9, add_a编译为矢量化代码

     add_a: and edx, -8 jle .L6 sub edx, 4 xor ecx, ecx shr edx, 2 lea eax, [rdx+1] xor edx, edx .L3: movaps xmm0, XMMWORD PTR [rdi+rdx] add ecx, 1 addps xmm0, XMMWORD PTR [rsi+rdx] movaps XMMWORD PTR [rdi+rdx], xmm0 add rdx, 16 cmp ecx, eax jb .L3 .L6: xor eax, eax ret 

    使用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 

    见Godbolt链接 。

    从gcc 4.8.2开始,gcc中没有__assume()的等价物。 我不知道为什么 – 它会非常有用。 mafso建议:

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

    这是一个老技巧,至少可以追溯到2010年,可能更长。 编译器通常会优化’cond’的评估,因为无论如何,cond为false的任何评估都将是未定义的。 但是,如果它包含对不透明(非内联)函数的调用,它似乎不会优化掉’cond’。 编译器必须假设不透明调用可能具有副作用(例如,更改全局)并且无法优化掉调用,尽管它可以优化结果上的任何计算和分支。 因此,宏观方法充其量只是部分解决方案。

      以上就是c/c++开发分享gcc中的“假设”条款相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。

      本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

      ctvol管理联系方式QQ:251552304

      本文章地址:https://www.ctvol.com/c-cdevelopment/562203.html

      (0)
      上一篇 2021年2月4日
      下一篇 2021年2月4日

      精彩推荐