Oracle® Solaris Studio 12.4:Fortran 用户指南

退出打印视图

更新时间: 2014 年 12 月
 
 

3.4.133 –xipo[={0|1|2}]

执行过程间优化。

通过调用一次过程间分析传递来执行整个程序的优化。-xipo 可以在链接步骤中的所有对象文件间执行优化,而不是仅限于在编译命令中的源文件。

在编译和链接大型多文件应用程序时,-xipo 特别有用。用该标志编译的对象文件具有在这些文件内编译的分析信息,这些信息实现了在源码和预编译的程序文件中的过程间分析。不过,分析和优化仅限于用 -xipo 编译的对象文件,而不扩展到库的对象文件。

-xipo=0 可禁用过程间分析,-xipo=1 可启用过程间分析。-xipo=2 可添加过程间别名分析以及内存分配和布局优化,以便改善高速缓存性能。缺省值为 -xipo=0,如果指定了不带值的 -xipo,则使用 -xipo=1

如果使用 -xipo=2 进行编译,未使用 -xipo=2 编译的函数或子例程(例如,库)不能调用使用 -xipo=2 编译的函数或子例程。

例如,如果您干预 malloc() 函数并使用 -xipo=2 编译您自己的 malloc(),则引用与您的代码链接的任何库中的 malloc() 的所有函数也必须使用 -xipo=2 进行编译。由于这对于系统库不大可能,因此您自己的 malloc 不应该使用 -xipo=2 进行编译。

在不同的步骤中进行编译和链接时,必须在这两个步骤中都指定 -xipo 才有效。

在一个编译/链接步骤中使用 -xipo 的示例:

demo% f95 -xipo -xO4 -o prog  part1.f part2.f part3.f

优化器在三个源文件之间执行交叉文件内联。该操作是在最终的链接步骤中完成的,因此源文件的编译工作不必全在一个编译过程中完成,可以跨多个不同的编译过程,但每个编译过程都需要指定 -xipo

在不同的编译/链接步骤中使用 -xipo 的示例:

demo% f95 -xipo -xO4 -c part1.f part2.f
demo% f95 -xipo -xO4 -c part3.f
demo% f95 -xipo -xO4 -o prog  part1.o part2.o part3.o

在编译步骤中创建的对象文件具有在文件内部编译的附加分析信息,这样就可以在链接步骤中执行跨文件优化。

即使使用 -xipo 进行编译,也存在库不参与跨文件过程间分析的限制,如下例所示:

demo% f95 -xipo -xO4 one.f two.f three.f
demo% ar -r mylib.a one.o two.o three.o
...
demo% f95 -xipo -xO4 -o myprog main.f four.f mylib.a

在此例中,过程间优化将在 one.ftwo.fthree.f 之间以及 main.ffour.f 之间执行,但不在 main.ffour.fmylib.a 上的例程之间执行。(第一个编译可能生成有关未定义符号的警告,但仍可执行过程间优化,因为过程间优化是编译和链接的一个步骤。)

关于 -xipo 的其他重要信息:

  • 至少需要优化级别 -xO4

  • 如果在内部版本中使用的对象文件对于并行运行的链接步骤通用,则使用并行 make 工具生成采用 -xipo 编译的可执行文件会产生问题。每个链接步骤都应有自己的对象文件副本,并且该副本应在链接前进行优化。

  • 未使用 -xipo 编译的对象可以与使用 -xipo 编译的对象自由链接。

  • 由于执行跨文件优化时需要附加信息,因此 -xipo 选项会生成更大的对象文件。不过,该附加信息不会成为最终的二进制可执行文件的一部分。可执行程序大小的增加是由于执行额外的优化导致的。

  • 在此发行版中,跨文件子程序内联是由 -xipo 执行的唯一过程间优化。

  • .s 汇编语言文件不参与过程间分析。

  • 如果使用 -S 进行编译,则忽略 -xipo 标志。

何时不使用 -xipo 进行编译:

在链接步骤中使用对象文件集合时,编译器试图执行整个程序的分析和优化。对于该对象文件集合中定义的任何函数或子例程 foo(),编译器作出以下两个假定:

  1. 运行时,在该对象文件集合外部定义的其他例程将不显式调用 foo()

  2. 从该对象文件集合中的任何例程调用 foo() 时,将不会受到在该对象文件集合外部定义的不同版本的 foo() 的干预。

如果假定 (1) 对给定应用程序不成立,请勿使用 -xipo=2 进行编译。如果假定 (2) 不成立,请勿使用 -xipo=1-xipo=2 进行编译。

例如,考虑使用您自己的源版本干预 malloc() 函数并使用 -xipo=2 进行编译。然后,任何库中引用与您的代码链接的 malloc() 的所有函数也必须使用 -xipo=2 进行编译,并且它们的对象文件将不需要参与链接步骤。由于这对于系统库不大可能,因此您自己的 malloc() 不应该使用 -xipo=2 进行编译。

另举一例,假定您使用以下两个外部调用来生成共享库:两个不同的源文件中的 foo()bar(),并且 bar() 调用其主体内的 foo()。如果有可能在运行时干预函数调用 foo(),则不要使用 -xipo=1-xipo=2 编译 foo()bar() 的任何一个源文件。否则,foo() 可以内联到 bar(),这会导致在使用 -xipo 编译时出现不正确的结果。