Oracle Solaris Studio 12.2:C++ 用户指南

A.2.175 -xrestrict[= f]

赋值为指针的函数参数视为受限指针。f 必须是下列值之一:

表 A–46 -xrestrict

值  

含义  

%all

整个文件中的所有指针参数均被视为限定的。 

%none

文件中没有指针参数被视为限定的。 

%source

只有在主源文件中定义的函数是限定的。在包含文件中定义的函数不是限定的。 

fn[,fn...]

用逗号隔开的一个或多个函数名称的列表。如果指定一个函数列表,编译器会将指定函数中的指针参数视为限定指针;有关更多信息,请参阅下一节A.2.175.1 限定指针

此命令行选项可以单独使用,但最好将其用于优化。例如,命令:


%CC -xO3 -xrestrict=%all prog.cc

将文件 prog.c 中的所有指针参数都视为限定指针。命令:


%CC -xO3 -xrestrict=agc prog.cc

将文件 prog.c 中函数 agc 中的所有指针参数都视为限定指针。

请注意,C 编程语言的 C99 标准引入了 restrict 关键字,但该关键字不是当前 C++ 标准的一部分。有些编译器的 C99 restrict 关键字具有 C++ 语言扩展,有时拼写为 __restrict__restrict__,但是 Solaris Studio C++ 编译器当前没有此扩展。-xrestrict 选项是源代码中 restrict 关键字的部分替代。(使用该关键字后,并非函数的所有指针参数都需要声明为 restrict。)关键字主要影响优化机会,还会限制可以传递给函数的参数。从源代码中删除 restict__restrict 的所有实例不会影响程序的可观测行为。

缺省值为 %none;指定 -xrestrict 与指定 -xrestrict=%source 等效。

A.2.175.1 限定指针

为使编译器高效并行执行循环,需要确定某些左值是否指定不同的存储区域。别名是其存储区域相同的左值。由于需要分析整个程序,因此确定对象的两个指针是否为别名是一个困难而费时的过程。例如下面的函数 vsq()


示例 A–3 带两个指针的循环


extern "C"
void vsq(int n, double *a, double *b) {
    int i;
    for (i=0; i<n; i++) {
            b[i] = a[i] * a[i];
    }
}

如果编译器知道指针 ab 访问不同的对象,可以并行化循环的不同迭代的执行。如果通过指针 ab 访问的对象存在重叠,编译器以并行方式执行循环将会不安全。

在编译时,编译器并不能通过简单地分析函数 vsq() 来获悉 ab 访问的对象是否重叠;编辑器需要分析整个程序才能获取此信息。可以使用以下命令行选项指定将返回赋值指针函数参数视为限定指针:-xrestrict[=func1,...,funcn]。如果指定了函数列表,则指定函数中的指针参数被视为是限定的,否则,整个源文件中的所有指针参数都被视为是限定的(不推荐)。例如,-xrestrict=vsq 限定 vsq() 函数示例中给定的指针 ab

将指针参数声明为限定的表示指针指定不同的对象。编译器可以假定 ab 指向不同的存储区域。有了此别名信息,编译器就能够并行化循环。

正确使用 -xrestrict 至关重要。如果指针被限定为指向并非不同的对象的限定指针,编译器可能会错误地并行化循环,从而导致不确定的行为。例如,假定函数 vsq() 的指针 ab 指向的对象重叠,如 b[i]a[i+1] 是同一对象。如果 ab 未声明为限定指针,循环将以串行方式执行。如果 ab 被错误地限定为限定指针,编译器可能会并行化循环的执行,这是不安全的,因为 b[i+1] 仅应在计算 b[i] 之后进行计算。