简而言之,GCC选项-fipa-pta做什么?

时间:2012-10-25 10:32:08

标签: c++ gcc compiler-optimization

根据GCC手册,-fipa-pta优化确实:

  

-fipa-pta:执行过程间指针分析和过程间修改和参考分析。此选项可能导致过多   大型编译单元的内存和编译时用法。它不是   在任何优化级别默认启用。

我假设GCC试图根据过程中使用的指针和引用来区分可变数据和不可变数据。具有更深入GCC知识的人能解释-fipa-pta的作用吗?

2 个答案:

答案 0 :(得分:5)

我认为“interprocedural”这个词是关键所在。

我并不熟悉gcc的优化器,但之前我一直致力于优化编译器。以下是有点推测的;拿一小块盐,或与知道gcc内部的人确认。

优化编译器通常仅在每个单独的函数(或子例程或过程,取决于语言)内执行分析和优化。例如,给定代码就像这个人为的例子:

double *ptr = ...;

void foo(void) {
    ...
    *ptr = 123.456;
    some_other_function();
    printf("*ptr = %f\n", *ptr);
}

优化程序无法确定调用*ptr是否更改了some_other_function()的值。

如果启用了过程间分析,则优化程序可以分析some_other_function()的行为,并且可能能够证明它无法修改*ptr。鉴于此类分析,它可以确定表达式*ptr仍必须评估为123.456,原则上它甚至可以用printf替换puts("ptr = 123.456");调用。

(事实上,对于与上面的代码段类似的小程序,我使用-O3-O3 -fipa-pta获得了相同的生成代码,所以我可能会遗漏一些内容。)

由于典型程序包含大量函数,并且巨大可能的调用序列,因此这种分析可能非常昂贵。

答案 1 :(得分:0)

引用自 this article

“-fipa-pta”优化在分析时考虑了被调用函数的主体,因此编译

void __attribute__((noinline))
bar(int *x, int *y)
{
  *x = *y;
}

int foo(void)
{
  int a, b = 5;
  bar(&a, &b);
  return b + 10;
}

with -fipa-pta 让编译器看到 bar 没有修改 b,编译器通过将 b+10 改为 15 来优化 foo

int foo(void)
{
  int a, b = 5;
  bar(&a, &b);
  return 15;
}

一个更相关的例子是“Integer division is slow”博文中的“慢”代码

std::random_device entropySource;
std::mt19937 randGenerator(entropySource());
std::uniform_int_distribution<int> theIntDist(0, 99);

for (int i = 0; i < 1000000000; i++) {
  volatile auto r = theIntDist(randGenerator);
}

使用 -fipa-pta 编译它使编译器看到 theIntDist 在循环中没有被修改,因此内联代码可以像“快速”版本一样被常量折叠 - 结果它运行快四倍。