在/ OPT:ICF存在的情况下,Visual Studio 2013是否正确优化?

Tho*_*ing 24 c++ optimization c++11 visual-studio-2013

我希望以下程序一直返回0.但是,对于Visual Studio 2013(Update 4),程序在发布版本中退出1.我不确定这是一个错误,还是编译器的优化器是正确的,并且依赖于某些边缘行为.如果关闭CONST宏,则release exe返回0.如果优化器确实正确,我是否可以获得允许它发出代码的原因?

#if 1
#   define CONST const
#else
#   define CONST
#endif


class TypeId {
public:
    bool operator== (TypeId const & other) const
    {
        return id == other.id;
    }

private:
    TypeId (void const * id)
        : id(id)
    {}

public:
    template <typename T>
    static TypeId Get ()
    {
        static char CONST uniqueMemLoc = 0;
        return TypeId(&uniqueMemLoc);
    }

private:
    void const * id;
};


int main(int, char **)
{
    typedef int A;
    typedef unsigned int B;

    if (TypeId::Get<A>() == TypeId::Get<B>()) {
        return 1;
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Sha*_*our 15

根据草案C++ 11标准部分14.8 [temp.fct.spec]所说,这似乎不是一个有效的优化(强调我的未来):

从模板实例化的每个函数模板特化都有自己的任何静态变量的副本.[例如:

template<class T> void f(T* p) {
static T s;
};
void g(int a, char* b) {
    f(&a); // calls f<int>(int*)
    f(&b); // calls f<char*>(char**)
}
Run Code Online (Sandbox Code Playgroud)

这里f(int*)有一个int类型的静态变量s,f(char**)有一个char*类型的静态变量s. - 末端的例子]

由于您获取变量的地址折叠它们会影响可观察的行为,这会违反as-if规则.

TC指出可以/opt:noicf防止不合规行为.

Matt McNabb指出/ OPT(优化)文档包含以下注释:

因为/ OPT:ICF可以将相同的地址分配给不同的函数或只读数据成员(使用/ Gy编译的const变量),它可以破坏依赖于函数或只读数据成员的唯一地址的程序.有关更多信息,请参阅/ Gy(启用功能级链接).

这表明这可能是故意的不符合行为.Ben Voigt 在一篇评论中表示现在转向聊天,这确实意味着优化可能不符合要求,但这一点值得商榷.

用户usr 链接MS博客文章:介绍'/ Gw'编译器开关,它说:

请注意,ICF优化仅适用于未采用其地址的相同COMDAT,并且它们是只读的.如果数据没有被采用,那么ICF破坏地址唯一性将不会导致任何可观察到的差异,因此它是有效的并且符合标准.

以后的评论说:

即使它是完全标准的投诉,当与/ Gy结合时,可能会导致破坏行为.

从我所知道的为了/Gy影响const变量,必须使用__declspec(selectany),但在文档中可以更清楚.

至少我们可以看到不/Gw应该引入不符合要求的行为,而是/Gy/Gwmay 结合使用.


Pot*_*ter 7

不,这种优化不符合C++标准.声明为uniqueMemLoc模板的每个实例定义一个唯一对象,每个对象都有自己的地址.

(如果您使用了字符串文字,那将是一个不同的故事.在这种情况下,优化将是有效的.)