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

时间:2015-03-15 03:22:21

标签: c++ c++11 visual-studio-2013 optimization

我希望以下程序一直返回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;
}

2 个答案:

答案 0 :(得分:15)

这似乎不是根据草案C ++ 11标准部分14.8 [temp.fct.spec] 所说的有效优化(强调我的前进< / em>的):

  

从模板实例化的每个功能模板专业化   它自己的任何静态变量的副本。 [例如:

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**)
}
     

这里f(int *)有一个类型为int和的静态变量s   f(char **)有一个char *类型的静态变量。 - 例子]

由于您使用变量的地址折叠它们会影响可观察的行为,这会违反as-if rule

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

Matt McNabb指出/OPT (Optimizations) documentation包含以下注释:

  

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

这表明这可能是故意的不合规行为。 Ben Voigt says in a comment now moved to chat这确实意味着优化可以不符合,但这一点值得商榷。

将用户linked发送至MS blog post: Introducing ‘/Gw’ Compiler Switch并说明:

  

请注意, ICF优化仅适用于相同的情况   没有接收地址的COMDAT ,它们是只读的。如果一个   数据不是地址,然后由ICF打破地址唯一性   不会导致任何可观察到的差异,因此它是有效的   符合标准。

以后的评论说:

  

即使它完全是标准投诉,但是   结合/ Gy可能导致破坏行为。

从我所知道的为/Gy影响 const 变量 __ declspec(selectany)必须使用但在文档中可能更清楚

至少我们可以看到/Gw不应该引入不合规行为,/Gy可能与/Gw结合使用。

答案 1 :(得分:7)

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

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