c++ - "Custom intrinsic"x64 函数而不是内联汇编可能吗?

标签 c++ assembly 64-bit inline-assembly intrinsics

我目前正在尝试为我的库创建高度优化、可重用的函数。例如,我按以下方式编写函数“是 2 的幂”:

template<class IntType>  
inline bool is_power_of_two( const IntType x )
{
    return (x != 0) && ((x & (x - 1)) == 0);
}

作为内联 C++ 模板,这是一个可移植、低维护的实现。这段代码被VC++ 2008编译为如下带有分支的代码:

is_power_of_two PROC
    test    rcx, rcx
    je  SHORT $LN3@is_power_o
    lea rax, QWORD PTR [rcx-1]
    test    rax, rcx
    jne SHORT $LN3@is_power_o
    mov al, 1
    ret 0
$LN3@is_power_o:
    xor al, al
    ret 0
is_power_of_two ENDP

我还从这里找到了实现:"The bit twiddler" ,它将在 x64 的程序集中编码如下:

is_power_of_two_fast PROC
    test rcx, rcx
    je  SHORT NotAPowerOfTwo
    lea rax, [rcx-1]
    and rax, rcx
    neg rax
    sbb rax, rax
    inc rax
    ret
NotAPowerOfTwo:
    xor rax, rax
    ret
is_power_of_two_fast ENDP

我在汇编模块(.asm 文件)中测试了两个与 C++ 分开编写的子例程,第二个子例程的运行速度提高了大约 20%!

然而,函数调用的开销相当大:如果我将第二个汇编实现“is_power_of_two_fast”与模板函数的内联版本进行比较,尽管有分支,后者速度更快!

不幸的是,x64 的新约定指定不允许内联汇编。人们应该改用“内在功能”。

现在的问题是:我可以将更快的版本“is_power_of_two_fast”实现为自定义内部函数或类似的东西,以便可以内联使用吗?或者,是否有可能以某种方式强制编译器生成函数的低分支版本?

最佳答案

不,您不能实现任何自定义内部函数,它们都内置在编译器中。不仅是内置的指令,编译器也知道内在的语义,并针对不同的周围代码调整代码。

为 x86-64 删除内联汇编的一个原因是将汇编插入函数的中间会干扰优化器,并且通常会导致围绕汇编代码优化得不太好的代码。那里很容易出现净亏损!

内在函数的唯一实际用途是用于编译器无法从 C 或 C++ 结构(如 BSF 或 BSR)生成的“有趣”特殊指令。大多数其他一切都会使用内联函数更好地工作,就像上面的模板。

如果您需要做一些编译器无法理解的特殊事情,唯一可行的选择是将整个函数编写为单独的汇编程序模块。如果该函数的调用开销太昂贵,那么优化可能一开始就不值得那么多。

相信您的编译器 (tm)!

关于c++ - "Custom intrinsic"x64 函数而不是内联汇编可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5536336/

相关文章:

caching - 软件预取是否分配行填充缓冲区(LFB)?

C++ 构建过程

c++ - 在 GCC 8 上工作的 Constexpr 计数器,并且不限于命名空间范围

c++ - emacs:类和结构的不同缩进

assembly - 使用 printf 在汇编 NASM 中打印数字

64-bit - 安装 python-igraph 0.7.1-4 会引发错误 "10038, ' 尝试对非套接字的内容进行操作'

windows - 我的程序应该如何决定安装在 "Program Files (x86)"下?

c++ - std::vector 上的嵌套循环

assembly - 实模式汇编获取键盘输入

algorithm - 如何在汇编中将两个十六进制 128 位数字相乘