在 x86-64 asm 中:如果源操作数是两个立即值,是否有办法优化两个相邻的 32 位存储/写入内存?

2024-04-04

有没有一个好的方法来优化这段代码(x86-64)?

mov dword ptr[rsp], 0;
mov dword ptr[rsp+4], 0

其中立即值可以是任何值,不一定为零,但在这种情况下始终是立即常量。

原双店还慢吗?硬件中的写组合和 μop 的并行操作可能会让一切变得快得离谱?我想知道是否没有问题需要解决。

我正在考虑类似的事情(不知道以下说明是否存在)

mov  qword ptr[rsp], 0

or

mov  eax, 0;
mov  qword ptr[rsp], rax    ; assuming we can spare a register, a bad idea to corrupt one though

是的,编译时/asm源代码级写入合并通常是一个好主意,特别是如果两者或高半部分为零(或-1)这样你就可以用 1 条指令完成整个 qword;现代 x86 CPU 具有高效的未对齐存储,尤其是当它不跨越缓存行边界时。

您通常希望最小化总融合域微指令(以使代码尽可能高效地通过前端)、总代码大小(以字节为单位)以及总未融合域微指令(调度程序/RS 中的后端空间)。在类似的优先事项中。此外,Sandybridge 系列还需要考虑 uop 缓存; 64 位立即数或 32 位立即数 + disp8/disp32 可能需要从 uop 缓存行中的相邻条目借用额外空间。 (参见 Agner Fog 的 microarch pdfhttps://agner.org/optimize/ https://agner.org/optimize/,桑迪布里奇章节。这仍然适用于像 Skylake 这样的后来的 uarch)

此外,最大限度地减少周围代码大量使用的某些后端执行端口的压力也是有好处的。 Ice Lake 有 2 个存储数据端口和存储地址端口,因此可以并行运行两个存储,但在此之前,所有 x86 CPU 仅限每个时钟 1 个存储(只有一个存储数据端口用于将数据写入存储缓冲区) 。对 L1d 高速缓存的提交也仅限于每个时钟从存储缓冲区进行 1 次存储。乱序执行确实可以解决这个问题,因此 2 个连续存储并不是一个大问题,但 2x 4 字节立即存储需要大量指令大小。

不幸的是 x86 没有mov r/m32, sign_extended_imm8,仅imm32。 (https://www.felixcloutier.com/x86/mov https://www.felixcloutier.com/x86/mov)x86-64does have mov r/m64, sign_extended_imm32不过,您应该使用以下内容:

mov    qword [rsp], 0      ; 8 bytes, 1 fused-domain uop on modern Intel and AMD CPUs

与 7 个字节 + 8 个字节和 2 个微指令mov dword [rsp],0 / mov dword [rsp+4], 0。异或归零 EAX / 存储 RAX 会更小(代码大小),但成本为 2 uop,而不是 1。

假设我们可以腾出一个寄存器,但破坏寄存器是个坏主意

几乎不;您经常需要使用归零寄存器,并且异或归零实际上与 Sandybridge 系列上的 NOP 一样便宜 https://stackoverflow.com/questions/33666617/what-is-the-best-way-to-set-a-register-to-zero-in-x86-assembly-xor-mov-or-and。 (而且在 AMD 上也很便宜。)如果您可以在某个地方进行此存储,从而使归零寄存器变得有用,那么这是非常便宜的:

xor   eax, eax
mov  [rsp], rax         ; better if you have a use for RAX later

或者对于您想要的非零 64 位值mov r64, imm64,通常您有一个备用寄存器可以用作暂存目标。如果您必须在整个函数周围溢出寄存器或保存/恢复额外的寄存器,那么如果您无法执行单个符号扩展imm32,则最好只执行两个单独的双字立即存储。


对于非零常量,如果整个 qword 常量可以表示为符号扩展的 32 位立即数,则使用mov qword [rsp], imm32. (Or push imm32并优化掉早期的sub rsp, 8.)

如果您知道您的 qword 内存位置是 8 字节对齐的,那么即使对于不适合 32 位立即数的任意 8 字节常量,也值得组合:

mov  rax, 0x123456789abcdef0        ; 10 bytes, 1 uop
mov  [rsp], rax                     ; 4 bytes, 1 micro-fused uop, for port 4 + port 2,3, or 7

它只比执行 2 个单独的双字存储要好一些,并且在(可能?)跨越 64 字节缓存行边界的罕见情况下可能会更慢

mov  dword [rsp], 0x9abcdef0        ; 7 bytes, 1 micro-fused uop for port 4 + port 2,3, or 7
mov  dword [rsp+4], 0x12345678      ; 8 bytes, 1 micro-fused uop for port 4 + port 2,3, or 7

或者如果您的常量恰好适合 32 位值零扩展到 64 位,但不进行符号扩展,您可以mov eax, 0x87654321(5个字节,非常高效)/mov [rsp], rax.


如果您想稍后进行 qword 重新加载,请务必执行单个 qword 存储,以便存储转发可以有效地工作.


硬件中的写组合

这不是主要因素。更重要的是 OoO exec 和存储缓冲区将存储执行与周围代码解耦。

If you were实际上希望每个时钟执行时获得超过 1 个存储(任何宽度),在 Ice Lake 之前你在 uarches 上肯定不走运。在任何 uarch(甚至非 x86)上,硬件存储合并会在存储执行后发生。

如果您希望它能够合并并在存储缓冲区中获取更少的条目,以便它有更多的时间/空间来吸收两个缓存未命中存储,那么您也不走运。我们没有任何真正的证据表明任何 x86 这样做是为了节省存储缓冲区耗尽带宽,或者更快地释放存储缓冲区条目。看为什么退休后的 RFO 不会破坏内存排序? https://stackoverflow.com/questions/62376976/why-doesnt-rfo-after-retirement-break-memory-ordering以我目前对(缺乏)存储缓冲区合并的理解。有一些证据表明,英特尔至少可以将存储未命中提交给高速缓存未命中存储上的 LFB,以释放存储缓冲区中的空间,但仅限于程序顺序的限制,并且没有证据表明每个时钟提交多个。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 x86-64 asm 中:如果源操作数是两个立即值,是否有办法优化两个相邻的 32 位存储/写入内存? 的相关文章

  • 最大化数组中成对距离的总和

    想象一个清单 e1 e2 en 和一个函数f e1 e2 gt number返回常数时间内任意两个元素之间的距离 f e e 0 e1 e2 gt f e1 e2 gt 0 f e1 e2 lt f e1 e3 f e3 e2 目标是排列列
  • 如何在 x86 汇编中编写自修改代码

    我正在考虑为我最近开发的一个业余爱好虚拟机编写一个 JIT 编译器 我了解一些汇编语言 我主要是一名 C 程序员 我可以阅读大多数汇编语言并参考我不理解的操作码 并编写一些简单的程序 但是我很难理解这几个示例我在网上找到的自我修改代码 这是
  • Linux 内核中是否使用了扩展指令集(SSE、MMX)?

    好吧 它们带来 至少应该带来 性能的巨大提升 不是吗 所以 我还没有看到任何 Linux 内核源代码 但很想问 它们是否以某种方式被使用 在这种情况下 对于没有此类指令的系统 必须有一些特殊的 代码上限 SSE 和 MMX 指令集在音频 视
  • 编译器在函数名称前添加下划线前缀的原因是什么?

    当我看到 C 应用程序的汇编代码时 如下所示 emacs hello c clang S O hello c o hello s cat hello s 函数名称以下划线作为前缀 例如callq printf 为什么这样做以及它有什么优点
  • X86 汇编将小写字母转换为大写字母

    实现toUpper函数 将字符串中的小写字母转换 为大写 该函数采用一个参数 char string 字符串是一个 char类型指针 指向字符串的开头 因为C 样式字符串以零结尾 我们不需要取长度 字符串作为另一个参数 我需要帮助开始 我不
  • 快速平方根优化?

    如果你检查这个非常好的页面 http www codeproject com Articles 69941 Best Square Root Method Algorithm Function Precisi http www codepr
  • 两个 16 位数字相乘 - 为什么结果是 32 位长? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 如果我将两个 16 位数字相乘 结果将是 32 位长 但为什么会这样呢 对此有何明确解释 为了我的正确理解 其计算方法是 n 位数字乘以
  • 用于计算三角函数、对数或类似函数的算法。仅限加减法

    我正在修复 Ascota 170 古董机械可编程计算机 它已经开始工作了 现在我正在寻找一种算法来展示其功能 例如计算三角或对数表 或类似的东西 不幸的是 从数学运算来看 计算机只能进行整数的加减法 从 1E12到1E12的55个寄存器 甚
  • 二元炸弹 - 第 6 阶段

    这是拆解phase 6 08048dbf
  • SQL 中的最佳 LIKE 搜索

    我有一个零件数据库 我将不断查询该数据库以获取报价系统 零件数据库有超过 1 400 000 条记录 用户将开始输入零件号 他们希望系统能够在仅几个字符后找到这些零件号 因此我需要能够进行通配符搜索 例如 SELECT NeededFiel
  • 当我尝试在 Armv8 程序集中分配数组时,执行冻结

    所以我正在用汇编语言进行编程 这只是一个简单的代码 这样我就可以学习如何分配数组 以便稍后在 NEON 编程中使用它们 ASM FUNC FPE data balign 8 array skip 80 array1 word 10 20 3
  • 在LPC2148 ARM处理器上创建中断向量的汇编代码

    我最近刚刚开始使用 LPC2148 ARM 处理器 我试图理解一些有关创建中断向量的汇编代码 这是代码 Runtime Interrupt Vectors Vectors b start reset start ldr pc undf un
  • 如果没有按下任何键,则检查按键而不阻塞

    我正在创建一个应用程序来查看当前时间 并创建了一个循环来每秒更新时间 循环看起来像这样 UPDATE The code to be re executed JMP UPDATE 但我无法结束它 当我使用 MOV AH 00H INT 21H
  • javascript中的快捷方式融合优化

    我听说 lodash 和其他 javascript 库使用一种称为 快捷融合 的技术进行优化 但在任何地方都找不到该技术的详细解释 任何人都可以提供链接或举例解释 快捷方式融合 的含义吗 对于一个非常简短且不清楚的解释 https wiki
  • 简单内核无法在 GRUB 中启动

    我正在学习一些操作系统开发的知识OSDev org http osdev org 我有一个内核 我正在尝试使用 qemu 在 GRUB Legacy 0 97 中启动 但是 当我输入kernel 200 9 我收到消息 Multiboot
  • GCC 从 C++ 程序生成的汇编代码中的 .cfi 和 .LFE 是什么?

    我有以下 C 代码 int factorial int n if n 0 return 1 return n factorial n 1 int main void factorial 5 return 0 当我使用 g S Factori
  • 该程序如何知道该字符串存储的确切位置?

    我用 Radare2 反汇编了一个 C 程序 在这个程序中有很多调用scanf像下面这样 0x000011fe 488d4594 lea rax var 6ch 0x00001202 4889c6 mov rsi rax 0x0000120
  • 在 x86 汇编语言中获取文件大小的简单方法

    假设我已经在汇编中打开了一个文件 并且在寄存器 eax 中有该文件的文件句柄 我将如何获取文件的大小 以便为其分配足够的缓冲区空间 我在这里研究了另一个讨论 建议使用sys fstat 28 系统调用来获取文件统计信息但无法实现它 My a
  • 在汇编中,指令指定数据类型吗?

    我是汇编语言编程 x86 的初学者 以下说法是否正确 在汇编中 BYTE WORD DWORD 等数据类型分别表示 8 位 16 位和 32 位模式 而不仅仅是整数 它们本身没有意义 它们只是位模式 使用它们的指令赋予了它们意义 汇编 代码
  • 相当于 min() 的 rowMeans()

    我在 R 邮件列表上多次看到这个问题 但仍然找不到满意的答案 假设我有一个矩阵m m lt matrix rnorm 10000000 ncol 10 我可以通过以下方式获得每行的平均值 system time rowMeans m use

随机推荐

  • extjs 树面板上下文菜单不起作用

    var menu1 new Ext menu Menu items text Open in new tab var treePanel Ext create Ext tree Panel id tree panel region cent
  • ASP.NET MVC 3 使用身份验证

    如何使用 FormsAuthentication 保存某些内容 我不想通过 URL 存储用户 ID 例如 现在我有这样的代码 UserController class HttpPost public ActionResult LogOn L
  • 如何使用 PHP 打破外循环?

    我正在寻找打破 PHP 中的外部 for foreach 循环 这可以在 ActionScript 中完成 如下所示 top for each var i MovieClip in movieClipArray for each var j
  • 使用反应钩子 getSnapshotBeforeUpdate

    如何使用 React hooks 实现 getSnapshotBeforeUpdate 提供的相同逻辑 根据React Hook 常见问题解答 https reactjs org docs hooks faq html do hooks c
  • 为什么 python docker 镜像这么大(~750 MB)?

    My Dockerfile FROM python 3 onbuild CMD python test py test py print hello world 构建图像 docker build t my test app docker
  • 如何渲染模板和布局?

    在控制器方法中 如何渲染模板和布局 Like so def new render template gt devise invitations new layout gt application unauthorized2 t2 end r
  • VS2010中关闭双击取消停靠

    我总是不小心双击 VS2010 中的选项卡并取消停靠它们 是否可以关闭此行为 注意 我正在使用 Productivity Power Tools 中的 Document Well 2010 Plus 以防产生影响 在文档选项卡上找到它以及高
  • 重命名实体框架 T4 模板生成的类名称?

    我有一个包含大量表的数据库 不幸的是这些表的命名没有任何标准约定 表名 另一个表名 还有另一个表名 垃圾表 我使用实体框架和标准 T4 代码生成模板在 C 中创建 POCO 类 是否有我可以遵循的最佳实践 让我可以合并自己的约定 在 C 应
  • Excel - VLOOKUP 与 INDEX/MATCH - 哪个更好?

    我了解如何使用每种方法 VLOOKUP or HLOOKUP vs INDEX MATCH 我寻找它们之间的差异不是出于个人喜好 而是主要在以下方面 是否有一种方法可以做到而另一种方法不能做到的事情 一般来说 哪一种更有效 或者取决于具体情
  • 如何导入具有正确类型的 Vue 类组件?

    例如 如果我有一个单文件 Vue 类组件 MyComponent vue
  • 在 jQuery .serialize() 中包含空值字段

    我正在尝试通过 jQuery post 提交表单并通过序列化表单数据 form serialize 不幸的是未选中的字段单选按钮 or 复选框没有被序列化 因此已提交 有没有办法包含所有字段 无论它们是否包含值 我想这只会影响这样的字段
  • 使用seaborn和pandas绘图防止重叠条

    我正在尝试使用 pandas 绘图来创建带有 seaborn 导入的堆叠水平条形图 我想删除条之间的空间 但也不让条重叠 这是我尝试过的 import pandas as pd import numpy as pd import seabo
  • HDF5 - 并发、压缩和 I/O 性能 [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我对 HDF5 性能和并发性有以下疑问 HDF5 支持并发写访问吗 撇开并发因素不谈 HDF5 的性能如何 输入 输出性能 does 压缩率影响性能
  • 适用于 IOS/Android 应用程序的谷歌云存储下载

    有没有一种方法可以将单个大文件作为多线程下载 并在从谷歌云存储下载后合并所有文件 是的 从 Google Cloud 存储下载对象时 您可以指定要检索的字节范围 使用 XML API 这将通过 Range 标头进行处理 这对于恢复中断的下载
  • 正则表达式如何验证字母之间的下划线

    我如何允许任何单词字符和下划线之间应该有一个字母和一个数字 示例 ab2 sb s s 但它不应该允许 sdc 或 s2 这是我的代码 a zA Z0 9 6 255 我在 javascript 上使用正则表达式 您需要将字符长度检查与模式
  • MVC 的替代方案 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 模型视图控制器的替代 设计方法 有哪些 MVC 似乎很流行 SO 是用它构建的 我知道很多 但它是唯一使用的方法吗 关于几种不同的交互
  • 错误:mysqlnd 无法使用旧的不安全身份验证连接到 MySQL 4.1+

    我收到以下错误 数据库连接失败 mysqlnd 无法使用旧的不安全身份验证连接到 MySQL 4 1 请使用管理工具通过以下命令重置您的密码SET PASSWORD PASSWORD your existing password 这将存储一
  • C# 项目在 Visual Studio 中重建的原因

    我有一个包含约 320 个项目的大型解决方案 即使对单个 Web 表单进行很小的更改 也会导致测试 调试小更改所需的构建时间很长 我怀疑构建后文件复制任务会 触及 文件日期时间并导致多次重建 在没有任何强大的命名和版本控制影响的情况下 除了
  • 如何定义输出类型取决于输入类型的函数

    给定以下课程 case class AddRequest x Int y Int case class AddResponse sum Int case class ToUppercaseRequest str String case cl
  • 在 x86-64 asm 中:如果源操作数是两个立即值,是否有办法优化两个相邻的 32 位存储/写入内存?

    有没有一个好的方法来优化这段代码 x86 64 mov dword ptr rsp 0 mov dword ptr rsp 4 0 其中立即值可以是任何值 不一定为零 但在这种情况下始终是立即常量 原双店还慢吗 硬件中的写组合和 op 的并