问题标签 [llvm-codegen]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
performance - 为什么在 Go 中交换 []float64 的元素比交换 Vec 的元素更快在锈?
我有两个(等效的?)程序,一个在 Go 中,另一个在 Rust 中。平均执行时间为:
- 去~169ms
- 生锈 ~201ms
去
锈
我编译了--release
在这种情况下,Rust 的性能是否不如 Go?Rust 程序能否以惯用的方式编写,以更快地执行?
c - 哪些优化技术应用于总结简单算术序列的 Rust 代码?
代码很天真:
输出是:
该计划几乎立即结束。我还使用 for 循环在 C 中编写了一个等效代码,但它运行了很长时间。我想知道是什么让 Rust 代码如此之快。
C代码:
Rust 代码是使用编译-O
的,C 代码是使用编译的-O3
。C 代码运行速度非常慢,以至于它还没有停止。
在修复了 visibleman 和 Sandeep 发现的错误后,两个程序几乎很快就打印了相同的数字。我试图减少NUM_LOOP
一个,考虑到溢出,结果似乎是合理的。此外,使用NUM_LOOP = 1000000000
,两个程序都不会溢出并立即产生正确的答案。这里使用了哪些优化?我知道我们可以使用简单的方程(0 + NUM_LOOP - 1) * NUM_LOOP / 2
来计算结果,但我不认为这种计算是由编译器完成的,有溢出情况......
c - 为什么clang用-O0(对于这个简单的浮点总和)产生效率低下的asm?
我在 llvm clang Apple LLVM 版本 8.0.0 (clang-800.0.42.1) 上反汇编此代码:
我编译时没有使用 -O 规范,但我也尝试使用 -O0 (给出相同的值)和 -O2 (实际上计算值并存储它预先计算)
得到的反汇编如下(我去掉了不相关的部分)
显然它正在执行以下操作:
- 将两个浮点数加载到寄存器 xmm0 和 xmm1
- 将它们放入堆栈
- 从堆栈加载一个值(不是 xmm0 之前的那个)到 xmm0
- 执行添加。
- 将结果存储回堆栈。
我发现它效率低下,因为:
- 一切都可以在注册表中完成。我以后不使用 a 和 b ,所以它可以跳过任何涉及堆栈的操作。
- 即使它想使用堆栈,如果它以不同的顺序执行操作,它也可以节省从堆栈重新加载 xmm0。
既然编译器永远是对的,为什么会选择这种策略呢?
c++ - C++ 标准是否允许未初始化的 bool 使程序崩溃?
我知道 C++ 中的“未定义行为”几乎可以让编译器做它想做的任何事情。然而,我有一个让我吃惊的崩溃,因为我认为代码足够安全。
在这种情况下,真正的问题只发生在使用特定编译器的特定平台上,并且只有在启用优化的情况下才会发生。
我尝试了几件事以重现问题并最大限度地简化它。这是一个名为 的函数的摘录Serialize
,它将采用 bool 参数,并将字符串复制true
或复制false
到现有的目标缓冲区。
如果 bool 参数是一个未初始化的值,这个函数是否会在代码审查中,没有办法告诉它实际上可能会崩溃?
如果使用 clang 5.0.0 + 优化执行此代码,它将/可能崩溃。
预期的三元运算符boolValue ? "true" : "false"
对我来说看起来足够安全,我假设,“无论是什么垃圾值都boolValue
无关紧要,因为它无论如何都会评估为真或假。”
我已经设置了一个Compiler Explorer 示例,它显示了反汇编中的问题,这里是完整的示例。注意:为了重现该问题,我发现有效的组合是使用带有 -O2 优化的 Clang 5.0.0。
问题是由于优化器而出现的:它很聪明地推断出字符串“true”和“false”的长度仅相差 1。因此,它不是真正计算长度,而是使用 bool 本身的值,这应该技术上是 0 或 1,如下所示:
虽然这很“聪明”,但可以这么说,我的问题是:C++ 标准是否允许编译器假设 bool 只能具有“0”或“1”的内部数字表示并以这种方式使用它?
或者这是实现定义的情况,在这种情况下,实现假设它的所有布尔值将只包含 0 或 1,并且任何其他值都是未定义的行为领域?
rust - 编译器(特别是 rustc)真的可以简化三角求和以避免循环吗?如何?
在Blandy 和 Orendorff的Programming Rust第 322 页上是这样的声明:
...Rust...认识到有一种更简单的方法可以将数字从 1
n
求和:总和始终等于n * (n+1) / 2
。
这当然是一个众所周知的等价,但是编译器是如何识别它的呢?我猜它是在 LLVM 优化过程中,但是 LLVM 是否以某种方式从第一原理推导出等价,或者它只是有一些可以简化为算术运算的“公共循环计算”?
rust - 假设两个可变引用不能别名,为什么 Rust 编译器不优化代码?
据我所知,引用/指针别名会阻碍编译器生成优化代码的能力,因为它们必须确保生成的二进制文件在两个引用/指针确实别名的情况下正确运行。例如,在下面的 C 代码中,
当clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final)
使用-O3
标志编译时,它会发出
在这里,代码存储回(%rdi)
两次以防万一int *a
和int *b
别名。
当我们明确告诉编译器这两个指针不能使用restrict
关键字别名时:
然后 Clang 将发出更优化的二进制代码版本:
由于 Rust 确保(在不安全的代码中除外)两个可变引用不能别名,我认为编译器应该能够发出更优化的代码版本。
rustc 1.35.0
当我使用下面的代码进行测试并使用with 进行编译时-C opt-level=3 --emit obj
,
它生成:
这没有利用保证a
并且b
不能别名。
这是因为当前的 Rust 编译器仍在开发中,还没有结合别名分析来进行优化吗?
这是因为即使在安全的 Rust 中,仍然有可能a
并且可以别名?b
rust - Rust 的 128 位整数 i128 如何在 64 位系统上工作?
Rust 有 128 位整数,它们用数据类型表示i128
(u128
对于无符号整数):
Rust 如何使这些i128
值在 64 位系统上工作;例如,它如何对这些进行算术运算?
因为,据我所知,该值无法放入 x86-64 CPU 的一个寄存器中,编译器是否以某种方式将两个寄存器用于一个i128
值?或者他们是否使用某种大整数结构来表示它们?
arrays - Why is there a large performance impact when looping over an array with 240 or more elements?
When running a sum loop over an array in Rust, I noticed a huge performance drop when CAPACITY
>= 240. CAPACITY
= 239 is about 80 times faster.
Is there special compilation optimization Rust is doing for "short" arrays?
Compiled with rustc -C opt-level=3
.
c++ - 获取 LLVM 类型/“取消引用”类型的大小
这个问题与这个问题非常相似,但我不确定如何在以下情况下获得大小:
我有一个指针类型,例如i32*
.
现在我想获得“指向”类型的大小,所以i32
(又名 4)。
现在我正在使用以下代码,这似乎有效,但我不确定它是否真的正确:
(注意:t
传递给函数的类型总是指针类型)
performance - 为什么这个 Rust 代码中没有分支预测失败惩罚?
我编写了这个非常简单的 Rust 函数:
我编写了一个基本基准,它使用有序数组和随机数组调用该方法:
令我惊讶的是,这两个基准测试具有几乎完全相同的运行时间,而 Java 中的类似基准测试显示两者之间存在明显差异,这可能是由于在 shuffled 情况下分支预测失败所致。
我见过提到条件移动指令,但如果我otool -tv
是可执行文件(我在 Mac 上运行),我在iterate
方法输出中看不到任何内容。
谁能阐明为什么 Rust 中的有序和无序案例之间没有明显的性能差异?