__attribute __((pure))应用于void函数

时间:2019-07-07 15:52:50

标签: c gcc optimization attributes compiler-optimization

我有一个函数,它接收两个数组并将pure函数的结果写入第三个数组(c_i = a_i / b_i):

inline
void    array_division      (ptrdiff_t nmemb,
                             double dest[static nmemb],
                             const double src1[static nmemb],
                             const double src2[static nmemb])
        __attribute__((nonnull, pure));

inline
void    array_division      (ptrdiff_t nmemb,
                             double dest[static nmemb],
                             const double src1[static nmemb],
                             const double src2[static nmemb])
{

        for (ptrdiff_t i = 0; i < nmemb; i++)
                dest[i] = src1[i] / src2[i];
}

GCC引发错误,因为它不希望纯函数返回void

pure function是一个根据其参数以及这些参数所指向的值的函数;并且如果两个调用之间的参数或它们所指向的值均未更改,则它们应该是多余的,并且可以忽略该调用,并评估为上一个调用返回的相同值。

我的函数遵循所有这些规则:如果三个数组在两个函数调用之间均未更改,则可以完全删除该函数调用;并且它们求值的值相同(没有值,因为它是void)。

我认为GCC应该允许使用__attibute__((pure))吗?

我应该返回假的return 0;以避免GCC抱怨吗?

编辑:

GCC中的错误状态:__ attribute __((pure)) to function with non-const pointers

2 个答案:

答案 0 :(得分:3)

关于return 0;起作用的原因... 根据{{​​3}}:

  

由于纯函数不能具有任何可观察到的副作用,因此使此类函数返回void毫无意义。声明了这样的功能。

但也请注意,您无法返回void的原因是:没有道理。您将放弃返回值的能力,而返回值只是纯函数的唯一合法目的。

  

pure属性禁止函数修改程序的状态,该状态可以通过检查函数的返回值以外的其他方式来观察。

这意味着,例如,标记为pure的函数被禁止在您传入的数组中设置条目。令我有些惊讶的是,它完全允许使用非常量指针,而通过它进行的赋值要少得多他们。

至于一旦您欺骗了GCC允许对这种功能进行修改,会发生什么,我不确定。在这种情况下,取决于GCC指定的操作。

答案 1 :(得分:1)

您的函数不遵循纯函数的规则。链接到文本的内容很清楚,多次表示,不允许通过传递给函数的指针来更改程序的可观察状态。从纯函数中唯一可以观察到的是它的返回值。 通过非常量指针修改内存不会返回值,但是会产生副作用。

您的功能不纯,因为它有副作用。如果优化器认为纯函数的返回值未使用,则根本不需要调用,甚至第一次也不需要。

因此,void函数不能用作纯函数,因为它是必须可优化为void nop() { }的函数。这没有任何意义。

这里唯一的编译器和文档错误是,当您添加双重错误的返回值0时,编译器抑制了诊断。


您发现了另一组可能具有优化属性的函数-幂等。但是,问题是只能消除重复的调用-但是与在循环条件下使用strlen不同,几乎没有任何理由使用相同的参数重复调用幂等函数。