- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想检查在我的代码中应用 boost::variant
的汇编输出,以查看哪些中间调用被优化掉了。
当我编译以下示例时(使用 GCC 5.3 使用 g++ -O3 -std=c++14 -S
),似乎编译器优化了所有内容并直接返回 100:
(...)
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
(...)
#include <boost/variant.hpp>
struct Foo
{
int get() { return 100; }
};
struct Bar
{
int get() { return 999; }
};
using Variant = boost::variant<Foo, Bar>;
int run(Variant v)
{
return boost::apply_visitor([](auto& x){return x.get();}, v);
}
int main()
{
Foo f;
return run(f);
}
.file "main1.cpp"
.section .rodata.str1.8,"aMS",@progbits,1
.align 8
.LC0:
.string "/opt/boost/include/boost/variant/detail/forced_return.hpp"
.section .rodata.str1.1,"aMS",@progbits,1
.LC1:
.string "false"
.section .text.unlikely._ZN5boost6detail7variant13forced_returnIvEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIvEET_v,comdat
.LCOLDB2:
.section .text._ZN5boost6detail7variant13forced_returnIvEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIvEET_v,comdat
.LHOTB2:
.p2align 4,,15
.weak _ZN5boost6detail7variant13forced_returnIvEET_v
.type _ZN5boost6detail7variant13forced_returnIvEET_v, @function
_ZN5boost6detail7variant13forced_returnIvEET_v:
.LFB1197:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZZN5boost6detail7variant13forced_returnIvEET_vE19__PRETTY_FUNCTION__, %ecx
movl $49, %edx
movl $.LC0, %esi
movl $.LC1, %edi
call __assert_fail
.cfi_endproc
.LFE1197:
.size _ZN5boost6detail7variant13forced_returnIvEET_v, .-_ZN5boost6detail7variant13forced_returnIvEET_v
.section .text.unlikely._ZN5boost6detail7variant13forced_returnIvEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIvEET_v,comdat
.LCOLDE2:
.section .text._ZN5boost6detail7variant13forced_returnIvEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIvEET_v,comdat
.LHOTE2:
.section .text.unlikely._ZN5boost6detail7variant13forced_returnIiEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIiEET_v,comdat
.LCOLDB3:
.section .text._ZN5boost6detail7variant13forced_returnIiEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIiEET_v,comdat
.LHOTB3:
.p2align 4,,15
.weak _ZN5boost6detail7variant13forced_returnIiEET_v
.type _ZN5boost6detail7variant13forced_returnIiEET_v, @function
_ZN5boost6detail7variant13forced_returnIiEET_v:
.LFB9757:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl $_ZZN5boost6detail7variant13forced_returnIiEET_vE19__PRETTY_FUNCTION__, %ecx
movl $39, %edx
movl $.LC0, %esi
movl $.LC1, %edi
call __assert_fail
.cfi_endproc
.LFE9757:
.size _ZN5boost6detail7variant13forced_returnIiEET_v, .-_ZN5boost6detail7variant13forced_returnIiEET_v
.section .text.unlikely._ZN5boost6detail7variant13forced_returnIiEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIiEET_v,comdat
.LCOLDE3:
.section .text._ZN5boost6detail7variant13forced_returnIiEET_v,"axG",@progbits,_ZN5boost6detail7variant13forced_returnIiEET_v,comdat
.LHOTE3:
.section .text.unlikely,"ax",@progbits
.LCOLDB4:
.text
.LHOTB4:
.p2align 4,,15
.globl _Z3runN5boost7variantI3FooJ3BarEEE
.type _Z3runN5boost7variantI3FooJ3BarEEE, @function
_Z3runN5boost7variantI3FooJ3BarEEE:
.LFB9310:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl (%rdi), %eax
cltd
xorl %edx, %eax
cmpl $19, %eax
ja .L7
jmp *.L9(,%rax,8)
.section .rodata
.align 8
.align 4
.L9:
.quad .L30
.quad .L10
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.quad .L7
.text
.p2align 4,,10
.p2align 3
.L7:
call _ZN5boost6detail7variant13forced_returnIiEET_v
.p2align 4,,10
.p2align 3
.L30:
movl $100, %eax
.L8:
addq $8, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 8
ret
.p2align 4,,10
.p2align 3
.L10:
.cfi_restore_state
movl $999, %eax
jmp .L8
.cfi_endproc
.LFE9310:
.size _Z3runN5boost7variantI3FooJ3BarEEE, .-_Z3runN5boost7variantI3FooJ3BarEEE
.section .text.unlikely
.LCOLDE4:
.text
.LHOTE4:
.globl _Z3runN5boost7variantI3FooI3BarEEE
.set _Z3runN5boost7variantI3FooI3BarEEE,_Z3runN5boost7variantI3FooJ3BarEEE
.section .text.unlikely
.LCOLDB5:
.section .text.startup,"ax",@progbits
.LHOTB5:
.p2align 4,,15
.globl main
.type main, @function
main:
.LFB9320:
.cfi_startproc
movl $100, %eax
ret
.cfi_endproc
.LFE9320:
.size main, .-main
.section .text.unlikely
.LCOLDE5:
.section .text.startup
.LHOTE5:
.section .rodata
.align 32
.type _ZZN5boost6detail7variant13forced_returnIvEET_vE19__PRETTY_FUNCTION__, @object
.size _ZZN5boost6detail7variant13forced_returnIvEET_vE19__PRETTY_FUNCTION__, 58
_ZZN5boost6detail7variant13forced_returnIvEET_vE19__PRETTY_FUNCTION__:
.string "T boost::detail::variant::forced_return() [with T = void]"
.align 32
.type _ZZN5boost6detail7variant13forced_returnIiEET_vE19__PRETTY_FUNCTION__, @object
.size _ZZN5boost6detail7variant13forced_returnIiEET_vE19__PRETTY_FUNCTION__, 57
_ZZN5boost6detail7variant13forced_returnIiEET_vE19__PRETTY_FUNCTION__:
.string "T boost::detail::variant::forced_return() [with T = int]"
.ident "GCC: (Ubuntu 5.3.0-3ubuntu1~14.04) 5.3.0 20151204"
.section .note.GNU-stack,"",@progbits
最佳答案
去除 .cfi
指令、未使用的标签和注释行是一个已解决的问题:Matt Godbolt's compiler explorer 背后的脚本在 its github project 上是开源的。它甚至可以进行颜色突出显示以将源代码行与汇编行匹配(使用调试信息)。
您可以在本地设置它,以便您可以使用所有 #include
路径等(使用 -I/...
)提供属于您项目的文件。因此,您可以在不想通过 Internet 发送的私有(private)源代码上使用它。
马特Godbolt的CppCon2017谈话“What Has My Compiler Done for Me Lately? Unbolting the Compiler's Lid”展示了如何使用它(这是相当不言自明,但有,如果你阅读GitHub上的文档一些整洁的功能),并且还如何阅读的x86 ASM ,用轻柔介绍的x86汇编本身对于初学者,并查看编译器输出。他继续展示了一些简洁的编译器优化(例如除以常数),以及什么样的函数提供有用的 asm 输出来查看优化的编译器输出(函数 args,而不是 int a = 123;
)。
使用普通的 gcc/clang(不是 g++),-fno-asynchronous-unwind-tables
避免了 .cfi
指令。可能也有用: -fno-exceptions -fno-rtti
-masm=intel
。确保省略 -g
。
复制/粘贴此供本地使用 :
g++ -fno-asynchronous-unwind-tables -fno-exceptions -fno-rtti -fverbose-asm \
-Wall -Wextra foo.cpp -O3 -masm=intel -S -o- | less
int
比寄存器宽或不是 32 位的机器上会发生什么可能会很有趣。或者在 RISC 与 x86 上)。
-xc -std=gnu11
之类的;编译器资源管理器站点仅提供 g++/clang++,不提供 gcc/clang。 (或者,您可以在语言下拉列表中使用 C 模式,但它有不同的编译器选择,而且大多受到更多限制。它会重置您的源代码 Pane ,因此在 C 和 C++ 之间切换更像是一种折磨。)
void ext(int*p)
是阻止某些东西优化掉 0x251819211 的好方法。您只需要一个原型(prototype),没有定义,因此编译器无法内联它或对其功能做出任何假设。-O3 -Wall -Wextra -fverbose-asm -march=haswell
) 查看代码。 ( -fverbose-asm
只会让源代码看起来很嘈杂,但是,当您得到的只是临时编号作为操作数的名称时。)当您摆弄源代码以查看它如何更改 asm 时,您肯定希望启用编译器警告。当解释是你做了一些值得在源代码中警告的事情时,你不想浪费时间为 asm 挠头。__attribute__((noinline,noclone)) foo_t foo(bar_t x) { ... }
,或使用 gcc -O3 -fno-inline-functions -fno-inline-functions-called-once -fno-inline-small-functions
进行编译以禁用内联。 (但这些命令行选项不会禁用克隆用于常量传播的函数。)示例参见 From compiler perspective, how is reference for array dealt with, and, why passing by value(not decay) is not allowed?。-ffast-math
将获得许多要内联的 libm 函数,其中一些是单个指令(特别是 SSE4 可用于 roundsd
)。有些将仅与 -fno-math-errno
或 -ffast-math
的其他“更安全”部分内联,而没有允许编译器以不同方式舍入的部分。如果你有 FP 代码,一定要看看它有/没有 -ffast-math
。如果您无法在常规构建中安全地启用 -ffast-math
中的任何一个,也许您会想到可以在源代码中进行安全更改以允许在没有 -ffast-math
的情况下进行相同的优化。-O3 -fno-tree-vectorize
将在不自动矢量化的情况下进行优化 ,因此如果您想与 12518 上的自动矢量化进行比较,则无需自动矢量化 0x2518192142 即可获得完整的优化(但在 123243 上启用自动矢量化 123243 上的 1232333513 上的 cc-O2
在复杂函数 中很有用。您可以了解“编译器做了什么”,而无需费力地浏览展开的循环。 (gcc 启用 -fno-unroll-loops
和 -funroll-loops
,但不启用 -fprofile-use
)。 (这是对人类可读代码的建议,而不是对运行速度更快的代码的建议。)-O3
做了什么 。它的“可预测的调试行为”要求使编译器在每个 C 语句之间存储/重新加载所有内容,因此您可以使用调试器修改 C 变量,甚至可以“跳转”到同一函数中的不同源代码行,并继续执行,就像您一样在 C 源代码中做到了这一点。 -O0
输出在存储/重新加载时如此嘈杂(而且如此缓慢)不仅是由于缺乏优化,而且是 forced de-optimization to support debugging 。 (也是 related )。-O0
将额外选项传递给 gcc -Wa,-adhln -c -g foo.c | less
。 (在 a blog post 和 another blog 中对此进行了更多讨论。)。请注意,此输出不是有效的汇编器输入,因为 C 源代码直接存在,而不是作为汇编器注释。所以不要称它为 as
。如果您想将其保存到文件中,则 .s
可能有意义。.lst
和编译时常量 。您希望看到处理寄存器中函数 arg 的代码,而不是常量传播将其转换为 main()
后的代码,或者至少优化掉一些东西。return 42
和/或 static
将为它们生成一个独立的定义,以及对任何调用者的定义,因此您可以查看它。inline
的函数中。 gcc 知道 main()
是特殊的,并假设它只会被调用一次,因此它将其标记为“冷”并对其进行了较少的优化。main
,则可以运行它并使用调试器。 main()
( stepi
) 按指令执行。有关说明,请参阅 x86 tag wiki 底部。但请记住,使用编译时常量参数内联到 main 后,代码可能会优化掉。si
可能对您不想内联的函数有所帮助。 gcc 还将制作函数的常量传播克隆,即一个特殊版本,其中一个 args 作为常量,用于知道它们正在传递常量的调用站点。符号名称将是 __attribute__((noinline))
或 asm 输出中的某些内容。您也可以使用 .clone.foo.constprop_1234
来禁用它。)。__attribute__((noclone))
)。// the wrong way, which people often write when they're used to creating a runnable test-case with a main() and a printf
// or worse, people will actually look at the asm for such a main()
int constants() { int a = 10, b = 20; return a * b; }
mov eax, 200 #,
ret # compiles the same as return 200; not interesting
// the right way: compiler doesn't know anything about the inputs
// so we get asm like what would happen when this inlines into a bigger function.
int variables(int a, int b) { return a * b; }
mov eax, edi # D.2345, a
imul eax, esi # D.2345, b
ret
(这种 asm 和 C 的组合是通过将 Godbolt 的 asm 输出复制粘贴到正确位置来手工制作的。我发现这是一个很好的方式来展示一个简短的函数如何在 SO 答案/编译器错误报告/电子邮件中编译。)
关于c++ - 如何从 GCC/clang 程序集输出中删除 "noise"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38552116/
我知道如何通过iPhone开发创建sqlite数据库、向其中插入数据、删除行等,但我试图以编程方式删除整个数据库本身,但没有得到任何帮助。请有人指导我如何通过代码从设备中删除/删除整个 sqlite
请帮助指导如何在 Teradata 中删除数据库。 当我运行命令DROP DATABASE database_name时,我收到错误消息: *** Failure 3552 Cannot DROP d
Azure 警报规则的删除命令似乎不起作用,尝试了下面的方法,它返回状态为无内容,并且警报未被删除 使用的命令Remove-AzAlertRule -ResourceGroup "RGName"-Na
我在 flex 搜索中为大约50000个视频建立了索引,但是当它达到52000左右时,所有数据都被删除。嗯,这对我来说真的很奇怪,我没有为ES设置任何Heap大小或最小或最大大小的内存大小,因此它们没
我正在处理的问题是表单错误“输入由字母、数字、下划线或连字符组成的有效‘slug’。” 以下是我的表单字段验证: def clean_slug(self): slug = self.c
阅读文档,我希望 $("#wrap2").remove(".error") 从 中删除所有 .error 元素#wrap2。然而看看这个 JSFiddle: http://jsfiddle.net/h
嗨,我第一次尝试发现 laravel 我从 laravel 4.2 开始,我刚刚创建了一个新项目,但我误以为我写了这样的命令行 composer create-project laravel/lara
我已经在网上搜索了很长一段时间,但我找不到如何完全删除 apache 2.4 。 使用: Windows 7 c:\apache24\ 我已经尝试了所有命令,但没有任何效果。 httpd -k shu
可能是一个简单的答案,所以提前道歉(最少的编码经验)。 我正在尝试从任何列中删除具有特定字符串(经济 7)的任何行,并且一直在尝试离开此线程: How to drop rows from pandas
有几种方法可以删除/移除 vector 中的项目。 我有一个指针 vector ,我需要在类的析构函数中删除所有指针。 什么是最有效/最快甚至最安全的方式? // 1º std::for_each(v
我安装了一个 VNC 服务器并在某处阅读了我必须安装 xinetd 的信息。稍后我决定删除 VNC 服务器,所以我也删除了 xinetd。似乎 xinetd 删除了一些与 plesk 相关的文件,如果
我制作了一个从我们的服务器下载视频的应用。问题是: 当我取消下载时,我打电话: myAsyncTask.cancel(true) 我注意到,myAsyncTask 并没有在调用取消时停止...我的 P
是否可以在使用DELETE_MODEL删除模型之前检查模型是否存在我试图避免在尝试删除尚未创建的模型时收到错误消息。基本上我正在寻找对应的: DROP TABLE IF EXISTS 但对于模型。 最
我已经有了这个代码: 但它仍然会生成一个表行条目。 我想做的是,当输入的数量为0时,表行将被删除。请耐心等待,因为我是 php 和 mySQL 编码新手。 最佳答案 您忘记执行查询。应该是 $que
在 SharePoint 中,如果您删除/修改重复日历条目的单次出现,则不会真正删除/修改任何内容 - 相反,会创建一个新条目,告诉 SP 对于特定日期,该事件不存在或具有新参数. 因此,这可以通过删
在 routes.php 中我有以下路由: Route::post('dropzone', ['as' => 'dropzone.upload', 'uses' => 'AdminPhotoContr
在我的应用程序中,我正在尝试删除产品。当我第一次删除产品时,它会成功并且 URL 更改为/remove_category/15。我正在渲染到同一页面。现在,当我尝试删除另一个产品时,网址更改为/rem
这个问题被问了很多次,但给出的答案都是 GNU sed 特定的。 sed -i '' "/${FIND}/,+2d""$FILE" 给出“预期的上下文地址”错误。 有人可以给我一个例子,说明如何使用
在使用 V3 API 时,我找不到任何方法来删除和清理 Google map 。 我已经在 AJAX 站点中运行它,所以我想完全关闭它而无需重新加载页面。 我希望有一个 .unload() 或 .de
是否可以创建一个 Azure SQL 数据库用户来执行以下操作: 针对所有表和 View 进行 SELECT 创建/更改/删除 View 但用户不应该不拥有以下权限: 针对任何表或 View 插入/更
我是一名优秀的程序员,十分优秀!