Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
97 views
in Technique[技术] by (71.8m points)

c++ - Is Visual Studio 2013 optimizing correctly in the presence of /OPT:ICF?

I expect the following program to return 0 all of the time. However with Visual Studio 2013 (Update 4), the program exits 1 in release builds. I'm not sure if this is a bug or if the compiler's optimizer is correct and is relying on some edge behavior. If the CONST macro is turned off, the release exe returns 0. If the optimizer is indeed correct, could I get the reason why it is allowed to emit the code it does?

#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;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

This does not seem like a valid optimization according to the draft C++11 standard section 14.8 [temp.fct.spec] says (emphasis mine going forward):

Each function template specialization instantiated from a template has its own copy of any static variable. [ Example:

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

Here f(int*) has a static variable s of type int and f<char*>(char**) has a static variable s of type char*. —end example ]

Since your taking the address of the variable folding them effects observable behavior which would violate the as-if rule.

T.C. points out that /opt:noicf prevents the non-conforming behavior.

Matt McNabb points out that the /OPT (Optimizations) documentation contains the following note:

Because /OPT:ICF can cause the same address to be assigned to different functions or read-only data members (const variables compiled by using /Gy), it can break a program that depends on unique addresses for functions or read-only data members. For more information, see /Gy (Enable Function-Level Linking).

Which suggests this could be intentional non-conforming behavior. Ben Voigt says in a comment now moved to chat that this indeed means the optimizations can be non-conforming but this points is debatable.

User usr linked to an MS blog post: Introducing ‘/Gw’ Compiler Switch and it says:

Please note, the ICF optimization will only be applied for identical COMDATs where their address is not taken, and they are read only. If a data is not address taken, then breaking address uniqueness by ICF won't lead to any observable difference, thus it is valid and conformant to the standard.

and a later comment says:

Even though it's on it's own completely standards complaint, when combined with /Gy potentially breaking behavior can result.

From what I can tell in order for /Gy to effect const variables __declspec(selectany) has to be used but it could be clearer in the documentation.

At minimum we can see that /Gw should not introduce non-conforming behavior but /Gy in combination with /Gw may.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...