Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
GCC编译器中的条件移动(cmov)_C_Gcc_Assembly_Compiler Optimization - Fatal编程技术网

GCC编译器中的条件移动(cmov)

GCC编译器中的条件移动(cmov),c,gcc,assembly,compiler-optimization,C,Gcc,Assembly,Compiler Optimization,我发现GCC编译器在将代码转换为ASM时有时可能不喜欢使用条件mov 在哪些情况下,它可能会选择执行条件mov以外的操作?编译器通常喜欢在分支两侧都很短的情况下,将其转换为cmov,特别是对于三元变量,因此您总是分配一个C变量。e、 g.ifx y=巴;有时不优化到CMOV,但y=x?酒吧:y;确实更经常使用CMOV。特别是当y是一个数组条目,否则就不会被触及时:引入它的非原子RMW可能会创建一个源中不存在的数据竞争。编译器无法发明对可能共享对象的写入 当if/else双方都有大量工作时,if转

我发现GCC编译器在将代码转换为ASM时有时可能不喜欢使用条件mov


在哪些情况下,它可能会选择执行条件mov以外的操作?

编译器通常喜欢在分支两侧都很短的情况下,将其转换为cmov,特别是对于三元变量,因此您总是分配一个C变量。e、 g.ifx y=巴;有时不优化到CMOV,但y=x?酒吧:y;确实更经常使用CMOV。特别是当y是一个数组条目,否则就不会被触及时:引入它的非原子RMW可能会创建一个源中不存在的数据竞争。编译器无法发明对可能共享对象的写入

当if/else双方都有大量工作时,if转换是合法的,但显然不盈利的一个明显例子。e、 g.一些乘法和除法、整个循环和/或表查找。即使gcc能够证明运行双方并最终选择一个结果是安全的,它也会发现做更多的工作不值得避免分支

如果仅在有限的情况下才可能转换为数据依赖性无分支cmov。e、 g.展示了一个可以/不能完成的案例。其他情况包括执行C抽象机不执行的内存访问,编译器无法证明这不会出错。或者可能有副作用的非内联函数调用

另请参见这些关于让gcc使用CMOV的问题

另请参见-gcc-fno if-conversion-fno-if-conversion2将禁用cmov的使用

对于cmov会影响性能的情况,请参见-GCC-O3需要配置文件引导的优化,以使其正确,并使用一个分支来表示高度可预测的if。GCC-O2一开始并没有进行if转换,即使没有PGO分析数据

另一个例子是:

显示了三元在两半中都有副作用的情况:三元和CMOV不同:只有一个副作用被评估


显示了一个Fortran示例,其中GCC需要源代码更改的帮助才能使用无分支SIMD。标量CMOV的等价物。这是一个不发明写的例子:它不能将源代码不会编写的元素的读/分支转换为读/可能修改/写。自动矢量化通常需要If转换。

当分支两边都很短时,编译器通常喜欢If转换为cmov,特别是对于三元变量,因此您总是分配一个C变量。e、 g.ifx y=巴;有时不优化到CMOV,但y=x?酒吧:y;确实更经常使用CMOV。特别是当y是一个数组条目,否则就不会被触及时:引入它的非原子RMW可能会创建一个源中不存在的数据竞争。编译器无法发明对可能共享对象的写入

当if/else双方都有大量工作时,if转换是合法的,但显然不盈利的一个明显例子。e、 g.一些乘法和除法、整个循环和/或表查找。即使gcc能够证明运行双方并最终选择一个结果是安全的,它也会发现做更多的工作不值得避免分支

如果仅在有限的情况下才可能转换为数据依赖性无分支cmov。e、 g.展示了一个可以/不能完成的案例。其他情况包括执行C抽象机不执行的内存访问,编译器无法证明这不会出错。或者可能有副作用的非内联函数调用

另请参见这些关于让gcc使用CMOV的问题

另请参见-gcc-fno if-conversion-fno-if-conversion2将禁用cmov的使用

对于cmov会影响性能的情况,请参见-GCC-O3需要配置文件引导的优化,以使其正确,并使用一个分支来表示高度可预测的if。GCC-O2一开始并没有进行if转换,即使没有PGO分析数据

另一个例子是:

显示了三元在两半中都有副作用的情况:三元和CMOV不同:只有一个副作用被评估


显示了一个Fortran示例,其中GCC需要源代码更改的帮助才能使用无分支SIMD。标量CMOV的等价物。这是一个不发明写的例子:它不能将源代码不会编写的元素的读/分支转换为读/可能修改/写。如果自动矢量化通常需要转换。

我不知道GCC的具体细节。但要了解一般信息,请参阅Agner Fog中的用条件移动替换条件跳转。我不知道GCC的具体内容。但有关一般信息,请参阅Agner Fog中的“用条件移动替换条件跳转”。编译器不能发明对可能共享对象的写入—编译器不认为只有对std::原子变量的写入才是对共享变量的写入吗?A w
非原子变量的rite只有在该变量未被共享时才是无数据竞争的,不是吗?@MaximeGroushkin:如果该线程在C抽象机中从未接触过arr[5],那么只有arr[4]和arr[6],那么引入arr[5]的非原子RMW是不允许的。当循环运行时,其他线程可能正在编写它,我们可以继续编写。发明写入可以创建源中不存在的共享和数据竞争,因此是不允许的。通常也不允许将一个read转换为RMW,即使我们正在阅读,那么另一个线程已经在写了。如果没有硬件数据竞争检测,理论上可能还可以?@PeterCordes-另一个不涉及并发性的参数是,如果内存映射为只读,会发生什么?编译器在实践中会这样做,例如字符串常量,如果您试图写入它们,即使使用相同的值,也会爆炸,因此这是一种简单的方法,可以证明这是不允许的,除非调用并发性,并发性是一种更为冗长的证明。@BeeOnRope:True,但是如果编译器可以证明数组的任何部分都已写入,那么整个事情就不能在只读存储器中了。或者至少是一个结构。或者UB保护数组的一部分,使其部分为常量,而其余部分为常量,这是否合法?可能对于像GCC这样的真正编译器来说,有相当严格的不发明写操作的行为,这很好。对于现实世界的编译器来说,发明写操作可能是不可取的,因为这可能会不必要地破坏COW共享。所以我认为问题更多的是编译器想要支持什么。我想他们会支持不在一个元素一个元素的基础上发明写操作,也就是说,他们会支持mprotect场景。请注意,icc确实发明了写入!我可以通过将一个const char*定义的字符串传递给icc矢量化的方法,并使用虚构的写操作,从而可靠地使其崩溃。编译器不能虚构对可能共享对象的写操作—难道编译器不认为只有对std::atomic变量的写操作才是对共享变量的写操作吗?对非原子变量的写入只有在该变量未被共享时才是无数据竞争的,不是吗?@MaximeGroushkin:如果该线程在C抽象机中从未接触过arr[5],则只允许arr[4]和arr[6],那么不允许引入arr[5]的非原子RMW。当循环运行时,其他线程可能正在编写它,我们可以继续编写。发明写入可以创建源中不存在的共享和数据竞争,因此是不允许的。通常也不允许将一个read转换为RMW,即使我们正在阅读,那么另一个线程已经在写了。如果没有硬件数据竞争检测,理论上可能还可以?@PeterCordes-另一个不涉及并发性的参数是,如果内存映射为只读,会发生什么?编译器在实践中会这样做,例如字符串常量,如果您试图写入它们,即使使用相同的值,也会爆炸,因此这是一种简单的方法,可以证明这是不允许的,除非调用并发性,并发性是一种更为冗长的证明。@BeeOnRope:True,但是如果编译器可以证明数组的任何部分都已写入,那么整个事情就不能在只读存储器中了。或者至少是一个结构。或者UB保护数组的一部分,使其部分为常量,而其余部分为常量,这是否合法?可能对于像GCC这样的真正编译器来说,有相当严格的不发明写操作的行为,这很好。对于现实世界的编译器来说,发明写操作可能是不可取的,因为这可能会不必要地破坏COW共享。所以我认为问题更多的是编译器想要支持什么。我想他们会支持不在一个元素一个元素的基础上发明写操作,也就是说,他们会支持mprotect场景。请注意,icc确实发明了写入!我可以通过将一个const char*定义的字符串传递给一个由icc使用虚拟写入向量化的方法来可靠地使它崩溃。