如何告诉编译器展开这个循环

时间:2013-04-15 18:35:04

标签: c gcc arm loop-unrolling

我在ARM处理器上运行以下循环。

// pin here is pointer to some part of an array
for (i = 0; i < v->numelements; i++)
{
    pe   = pptr[i];
    peParent = pe->parent;

    SPHERE  *ps = (SPHERE *)(pe->data);

    pin[0] = FLOAT2FIX(ps->rad2);
    pin[1] = *peParent->procs->pe_intersect == &SphPeIntersect;
    fixifyVector( &pin[2], ps->center ); // Is an inline function

    pin = pin + 5;
}

由于循环性能缓慢,我可以判断编译器无法展开此循环,因为当我手动执行展开时,它变得非常快。我认为编译器被pin指针搞糊涂了。我们可以使用restrict关键字来帮助编译器,还是只为函数参数保留restrict?一般来说,我们如何告诉编译器将其展开并且不用担心pin指针。

2 个答案:

答案 0 :(得分:3)

要告诉gcc展开所有循环,您可以使用优化标记-funroll-loops

要仅展开您可以使用的特定循环:

__attribute__((optimize("unroll-loops")))

有关详细信息,请参阅此answer

修改

如果编译器在输入时无法确定循环的迭代次数,则需要使用-funroll-all-loops。请注意,来自documentation"Unroll all loops, even if their number of iterations is uncertain when the loop is entered. This usually makes programs run more slowly."

答案 1 :(得分:0)

如果您将pptr大小扩展为1,则可以使用pld指令。

  __asm__ __volatile__("pld\t[%0]" :: "r" (pptr[i+1]));

或者您可能需要预先加载下一步 peParentSPHERE *ps。 ARM上的循环开销非常小。展开循环不太可能是一个重要的好处。没有循环变量常量。编译器的调度程序更有可能在取消循环时使用高级数据。

您尚未提供所有代码以查看数据依赖性。可能还有其他变量会受益于预加载。提供一个完整的例子可能会帮助每个人回答你的问题。