[LLVMdev] Inclusion of iostream affects devirtualization in release_35

martin krastev blu.dark at gmail.com
Thu Jan 8 05:06:22 PST 2015


> On 7 January 2015 at 08:38, Reid Kleckner <rnk at google.com> wrote:
>>
>> This isn't really devirtualization so much as global opt plus basic constant propagation. My theory is that iostream injects static initializers for std::cout / std::cerr into your TU. LLVM's global opt pass will fail when those are present.

I just verified your theory - it's correct. The same effect is
exhibited by the following version of the original code:


#include <stdio.h>

struct Base {
    virtual int foo() const = 0;
};

struct A : Base {
    int a;

    A(const int a)
    : a(a) {
    }

    int foo() const {
        return a;
    }
};

struct B : Base {
    const Base* b;

    B(const Base* const base)
    : b(base) {
    }

    int foo() const {
        return b->foo();
    }
};

struct C {
    C() {
#if BREAKAGE_ENSUES
       printf("");

#endif
    }
};

const A a(42);
const B b(&a);
const C c;

int main(int, char**) {
    return b.foo();
}


To get the (un)desired effect, it suffices to have a static
initializer with an (implied) side effect (e.g. a call external to the
TU). In the case of iostream - their introduce a static (__ioinit)
with a ctor external to our TU.


On Wed, Jan 7, 2015 at 10:02 PM, Nick Lewycky <nlewycky at google.com> wrote:
> Yikes, that's a limitation right there isn't it. Should we have a PR or is there nothing for the optimizer can do?


IMHO, it's an issue that might warrant at least some feedback to the
developer upon detection. Some warning along the lines of 'Global opt
pass is disabled due to such-and-such static initializer with side
effects.' After all it is easy for a TU to unintentionally 'catch' a
wrong include.


Best regards,
Martin



More information about the llvm-dev mailing list