为什么 clang 的 `-O3` 分配比 g++ 快 2 倍?基于简单的 alloca 基准

发布于 2024-11-04 01:58:47 字数 251 浏览 6 评论 0原文

关于 alloca 的使用和滥用

在底部得到了一些基准之前的一个问题。 clang 显然在 -O3 优化器配置文件中有更好的实现。什么给? clang 是否有偷工减料?另外,由于 clang 是一个现代编译器,它的 alloca 实现中是否有任何安全性或其他有趣的属性?

On the use and abuse of alloca

Got some benchmarks at the bottom of a previous question. clang clearly has a better implementation in the -O3 optimizer profile. What gives? Is clang cutting any corners? Also, since clang is a modern compiler, are there any safeties or other interesting properties in its alloca implementation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

对不⑦ 2024-11-11 01:58:47

德尔南的猜测是正确的。但他没有考虑到测试非常糟糕,clang 可以从 alloca_test 优化实际的 alloca 操作。

alloca_test 只有 llvm ir 操作 alloca,但没有 alloca() 函数调用:

%11 = call i32 @_Z18random_string_sizev()
%12 = alloca i8, i32 %11

malloc_test 比较:

%11 = call i32 @_Z18random_string_sizev()
%12 = call i8* @malloc(i32 %11)

即使使用 -O1 在 alloca_test 中不再有分配:

define void @_Z11alloca_testv() nounwind {
; <label>:0
  %1 = tail call i32 @_Z18random_vector_sizev()
  %2 = icmp sgt i32 %1, 0
  br i1 %2, label %.lr.ph, label %._crit_edge

.lr.ph:                                           ; preds = %.lr.ph, %0
  %i.01 = phi i32 [ %4, %.lr.ph ], [ 0, %0 ]
  %3 = tail call i32 @_Z18random_string_sizev()
  %4 = add nsw i32 %i.01, 1
  %exitcond = icmp eq i32 %4, %1
  br i1 %exitcond, label %._crit_edge, label %.lr.ph

._crit_edge:                                      ; preds = %.lr.ph, %0
  ret void
}

对于 malloc_test,malloc 调用仍然在这里:

%6 = tail call i32 @_Z18random_string_sizev()
%7 = tail call i8* @malloc(i32 %6)

我还应该说 g++ -O3 (测试过的 4.1 和 4.5.2)不会优化堆栈大小的变化(分配主效应)。

Guess by delnan is true. But he didn't account that test is very bad, and clang can to optimize out actual alloca operation from alloca_test.

alloca_test have only llvm ir operation alloca, but no alloca() function call:

%11 = call i32 @_Z18random_string_sizev()
%12 = alloca i8, i32 %11

Compare with malloc_test:

%11 = call i32 @_Z18random_string_sizev()
%12 = call i8* @malloc(i32 %11)

Even with -O1 there is no more alloca in alloca_test:

define void @_Z11alloca_testv() nounwind {
; <label>:0
  %1 = tail call i32 @_Z18random_vector_sizev()
  %2 = icmp sgt i32 %1, 0
  br i1 %2, label %.lr.ph, label %._crit_edge

.lr.ph:                                           ; preds = %.lr.ph, %0
  %i.01 = phi i32 [ %4, %.lr.ph ], [ 0, %0 ]
  %3 = tail call i32 @_Z18random_string_sizev()
  %4 = add nsw i32 %i.01, 1
  %exitcond = icmp eq i32 %4, %1
  br i1 %exitcond, label %._crit_edge, label %.lr.ph

._crit_edge:                                      ; preds = %.lr.ph, %0
  ret void
}

And for malloc_test, malloc call is still here:

%6 = tail call i32 @_Z18random_string_sizev()
%7 = tail call i8* @malloc(i32 %6)

I should also say that g++ -O3 (tested 4.1 and 4.5.2) doesn't optimize out changing size of stack (alloca main effect).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文