在探讨 C++ 优化器并专门回顾循环展开之后,在本视频中,Amir Kirsh 将深入探究循环展开场景、代码中未定义行为的含义以及优化标志对编译代码的影响。我们一起来观看视频吧。
转录文本:C++ 优化器和循环展开
大家好!
我是 Amir Kirsh,是 Incredibuild 的一名开发推广工程师。
今天,我想继续我之前的讨论,并介绍一些更为简单的 C++ 编译器、优化器和循环展开。
Compiler Explorer
那么,我们就来看看 Compiler Explorer 吧。这是一款在线工具,用来查看被汇编的 C++ 代码。希望大家能够看到我的屏幕,我将写一个非常简单的函数。我们将它称为 foo 吧。Foo 得到一个整数并返回一个整数。在 foo 内部,我想要一个简单的循环。我想要在 I 上循环,当 i 达到 10 且增量为 i 时循环停止,最后,我想要返回 i。所以,当我们看这个函数时,嗯,这儿会有两个可能的结果,要么得到小于 10 的 i,在这种情况下,返回值为 10,要么得到大于或等于 10 的 i。然后我们只返回 i,所以要么 foo 将返回 i,要么 foo 将返回 10,但问题是循环是否会出现在实际汇编中,答案是,这取决于优化级别。
如果我们的优化级别为 -O2,那么确实不需要循环,也不会有循环。如果这儿我将其更改为 -O0,那么你会看到一个内部循环,之所以我们在这儿可以看到,是因为我们要求编译器不要做任何优化。实际上这里有一个循环,有人把这个值和 9 进行了比较。然后决定是回到循环还是结束循环。
让我们回到 -O2。这个函数变成了一个简单的 if 条件函数,一个简单的比较,我们取 10 并把它放在整数的返回值寄存器中。然后,我们将返回值寄存器中的值与我们得到的位于 EDI 寄存器中的参数值进行比较。然后我们会有一个条件转移。如果之前的比较结果为大于或等于,那么我们将 EDI 寄存器复制到返回值。否则,我们就不进行复制。我们继续使内部保持为 10。所以最终它会返回 10 或 i,这取决于 i 是否大于 10,这就是一个简单的 if 条件。在这里我们可以看到,编译器可以接受一个循环,并将其转换成不需要循环的情况。这就叫做循环展开。这是一个非常简单的例子,比我们在前一个视频中看到的要简单得多,尽管前一个更逼真,但这是一个虚构的例子。
现在我们在示例中添加一个 main,并在 main 中调用 foo。我们可以再次看到,main 中有一些与 foo 中相同的函数,如果要返回值,那么我们就返回 foo 的返回值。所以我们返回 foo ,我们可以看到实际上没有必要调用 foo。这由编译器或优化器决定,好吧,我们将返回 120,因为在某种程度上,foo 是内联的。结果是 120。如果我们把它变为 5,那么我们可以看到结果给出的是 10。实际上没有必要调用 foo,因为在某种程度上 foo 被内联至 main。优化器可以在编译时执行 if,并根据它们发送给 foo 的初始值决定是从 main 10 返回还是从其他值返回。
循环展开
我们在 main 中还可以做一些其他事情,比如,执行循环。我们将 int i 放入 main 中。然后看看并决定返回 i,所以我们有一些类似于在 foo 中所执行的操作,但是这里的 i 并不是我们作为参数而得到的变量,我们只是定义 i,我们有一个变量 i,它是一个局部变量。我们运行这个循环,然后返回 i。如果我们看一下汇编代码,我们会发现 main 仅返回 10,那 main 为什么会返回 10 呢?这是否意味着局部变量被初始化为零?不,并不是那样,而是意味着优化器假设了一些东西,我们这里有未定义的行为,而这个未定义的行为就是我们使用未初始化的变量。一旦你使用了未初始化的变量,优化器就能假设任何东西。这里优化器决定假设 i 小于 10 或小于等于 10,因为如果 i 大于 10,那么结果应该是 i,而事实并非如此。我们只是返回 10。所以优化器在这假设了一些东西。这没关系。这是合理的,因为一旦我们有了一个未定义的行为,比如,我们对一些未初始化的东西设置了条件,优化器就可以假设它需要或想要假设的任何东西来优化代码。在这个例子中,实际上并不需要检查 i,因为 i 并未初始化,我们假设它小于或等于 10。
结语
我们能在 main 中看到实际的循环吗?好吧,如果我们返回到 -O0,那么我们可能会找到循环,即使是在 main 中,因为我们要求优化器或编译器不要优化我们的代码。我并不是告诉大家使用未定义的行为。不,一定要初始化你的变量,但是你必须要知道是的是,一旦你不初始化一个变量或一旦你的代码依赖于未定义的行为,这就意味着优化器和编译器可以假设一些东西。当你将代码移动至另一编译器或使用其它一些优化标志时,你的代码可能会有不同的行为,而这正是未定义行为的结果。
今天我们讨论了循环展开、C++ 优化器,以及关于未定义行为的一些内容。我们下一个视频见。谢谢观看。再见!