ein*_*ica 16 c++ gcc compiler-optimization constexpr ubsan
考虑以下代码:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
auto x = f();
return x.substr(1, 3);
}
int foo() { return g().length(); }
Run Code Online (Sandbox Code Playgroud)
如果我用 GCC 10.2 和 flags 编译它--std=c++17 -O1
,我会得到:
foo():
mov eax, 3
ret
Run Code Online (Sandbox Code Playgroud)
此外,据我所知,这段代码没有任何未定义的行为问题。
但是 - 如果我添加 flag -fsanitize=undefined
,编译结果是:
.LC0:
.string "hello"
foo():
sub rsp, 104
mov QWORD PTR [rsp+80], 5
mov QWORD PTR [rsp+16], 5
mov QWORD PTR [rsp+24], OFFSET FLAT:.LC0
mov QWORD PTR [rsp+8], 3
mov QWORD PTR [rsp+72], 4
mov eax, OFFSET FLAT:.LC0
cmp rax, -1
jnb .L4
.L2:
mov eax, 3
add rsp, 104
ret
.L4:
mov edx, OFFSET FLAT:.LC0+1
mov rsi, rax
mov edi, OFFSET FLAT:.Lubsan_data154
call __ubsan_handle_pointer_overflow
jmp .L2
.LC1:
.string "/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/string_view"
.Lubsan_data154:
.quad .LC1
.long 287
.long 49
Run Code Online (Sandbox Code Playgroud)
看到这个Compiler Explorer。
我的问题:为什么消毒会干扰优化?特别是因为代码似乎没有任何 UB 危害......
笔记:
-O3
。x
为constexpr
变量,则清理不会阻止优化。-O3
)。Dan*_* M. 10
消毒剂添加了必要的工具来检测运行时的违规行为。该检测可能会通过引入一些不透明的调用/副作用来阻止函数在编译时作为优化计算,否则这些调用/副作用不会在那里出现。
您看到的不一致行为是因为g().length();
调用不是在constexpr
上下文中完成的,因此不需要在编译时计算(好吧,“不期望”会更准确)。GCC 可能有一些启发式方法来计算常规上下文中constexpr
带constexpr
参数的函数,一旦消毒剂通过破坏constexpr
函数-ness(由于添加的检测)或所涉及的启发式方法之一,这些函数。
添加constexpr
到x
使f()
调用成为一个常量表达式(即使g()
不是),因此它在编译时编译,因此不需要检测,这足以触发其他优化。
人们可以将其视为 QoI 问题,但总的来说,这是有道理的
constexpr
函数评估可能需要任意长的时间,因此除非被要求,否则在编译时评估所有内容并不总是可取的 归档时间: |
|
查看次数: |
603 次 |
最近记录: |