Tag: 循环展开

GCC 5.1循环展开

给出以下代码 #include int main(int argc, char **argv) { int k = 0; for( k = 0; k < 20; ++k ) { printf( "%d\n", k ) ; } } 使用GCC 5.1或更高版本 -xc -std=c99 -O3 -funroll-all-loops –param max-completely-peeled-insns=1000 –param max-completely-peel-times=10000 部分循环展开,它将循环展开十次然后进行条件跳转。 .LC0: .string “%d\n” main: pushq %rbx xorl %ebx, %ebx .L2: movl %ebx, %esi movl $.LC0, […]

强制/说服/欺骗GCC展开_Longer_循环?

我如何说服GCC展开一个已知迭代次数但又很大的循环? 我正在使用-O3编译。 当然,有问题的真实代码更复杂,但这是一个具有相同行为的简化示例: int const constants[] = { 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144 }; int get_sum_1() { int total = 0; for (int i = 0; i < CONSTANT_COUNT; ++i) { total += constants[i]; } return total; } …如果CONSTANT_COUNT被定义为8(或更少),那么GCC将展开循环,传播常量,并将整个函数减少为简单的return ; 。 另一方面,如果CONSTANT_COUNT为9(或更大),则循环不会展开,GCC会生成一个二进制循环,读取常量,并在运行时添加它们 – 即使理论上该函数可以仍然被优化到只返回一个常数。 (是的,我看过反编译的二进制文件。) 如果我手动展开循环,如下所示: int get_sum_2() […]

如何让GCC完全展开这个循环(即剥离这个循环)?

有没有办法指示GCC(版本我使用4.8.4)完全展开底部函数中的while循环,即剥离此循环? 循环的迭代次数在编译时是已知的:58。 我先解释一下我的尝试。 通过检查GAS输出: gcc -fpic -O2 -S GEPDOT.c 使用12个寄存器XMM0 – XMM11。 如果我将标志-funroll-loops传递给gcc: gcc -fpic -O2 -funroll-loops -S GEPDOT.c 循环只展开两次。 我检查了GCC优化选项。 GCC表示-funroll-loops也会打开-frename-registers ,所以当GCC展开一个循环时,它先前选择的寄存器分配是使用“遗留”寄存器。 但是XMM12只剩下4个 – XMM15,所以GCC最多只能展开2次。 如果有48个而不是16个XMM寄存器可用,GCC将毫无困难地展开while循环4次。 然而我做了另一个实验。 我首先手动两次展开while循环,获得一个函数GEPDOT_2。 然后两者之间没有任何区别 gcc -fpic -O2 -S GEPDOT_2.c 和 gcc -fpic -O2 -funroll-loops -S GEPDOT_2.c 由于GEPDOT_2已用完所有寄存器,因此不执行展开。 GCC确实注册了重命名,以避免引入潜在的错误依赖。 但我确信在我的GEPDOT中没有这样的潜力; 即使有,也不重要。 我尝试自己展开循环,展开4次比展开2次更快,比没有展开更快。 当然我可以手动展开更多次,但这很乏味。 GCC可以帮我吗? 谢谢。 // C file “GEPDOT.c” #include […]

展开循环并使用矢量化进行独立求和

对于以下循环,如果我告诉它使用关联数学,例如使用-Ofast GCC将仅对循环进行矢量化。 float sumf(float *x) { x = (float*)__builtin_assume_aligned(x, 64); float sum = 0; for(int i=0; i<2048; i++) sum += x[i]; return sum; } 这是带-Ofast -mavx的程序集 sumf(float*): vxorps %xmm0, %xmm0, %xmm0 leaq 8192(%rdi), %rax .L2: vaddps (%rdi), %ymm0, %ymm0 addq $32, %rdi cmpq %rdi, %rax jne .L2 vhaddps %ymm0, %ymm0, %ymm0 vhaddps %ymm0, %ymm0, %ymm1 […]

C / C ++中的自展开宏循环

我目前正在开展一个项目,每个周期都很重要。 在分析我的应用程序时,我发现一些内部循环的开销非常高,因为它们只包含一些机器指令。 此外,这些循环中的迭代次数在编译时是已知的。 所以我认为不是手动展开带有复制和粘贴的循环,而是可以使用宏在编译时展开循环,以便以后可以轻松修改它。 我的形象是这样的: #define LOOP_N_TIMES(N, CODE) 这样我就可以替换for (int i = 0; i < N, ++i) { do_stuff(); } 用: #define INNER_LOOP_COUNT 4 LOOP_N_TIMES(INNER_LOOP_COUNT, do_stuff();) 它将自己展开: do_stuff(); do_stuff(); do_stuff(); do_stuff(); 由于C预处理器在大多数时间对我来说仍然是一个谜,我不知道如何实现这一点,但我知道它必须是可能的,因为Boost似乎有一个BOOST_PP_REPEAT宏。 不幸的是我不能在这个项目中使用Boost。