llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.76k stars 11.89k forks source link

Missed optimizazion opportunity with anonymous structures #97162

Open fekir opened 4 months ago

fekir commented 4 months ago

Consider following code snippet

struct {
    int i = 42;
} const a;

auto bar(){
    return a;
}

clang optimizes the code to

        mov     eax, 42
        ret

but the MSVC compiler does better, even without optimizations enabled. It seems that it does not generate any code for the function bar at all!

It would be nice if clang can consistently avoid generating code for functions that are not used at all.

I've collected some examples here: https://godbolt.org/z/xEj51j8E7

Note that in case of auto foo0(){return a;} the code is generated, but for decltype(a) foo2( ){return a;} not (GCC has similar issue https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115670).

The scenarios that clang does not seem to handle optimally are

struct {
    int i = 42;
} const a;
namespace {
    struct s{};
}
auto foo0(){
    return a;
}
s foo4(){
    return {};
}

auto foo5(){
    struct {} t;
    return t;
}

struct s2{
    s i; //s is in anonymous namespace
};

s2 foo6(){
    return {};
}

Also the diagnostic -Wunused-function can be improved, as it currently does not warn for those cases.

MitalAshok commented 4 months ago

namespace {
    struct s{};
}
s foo4(){
    return {};
}

Clang already eliminates this function and warns -Wunused-function for it: https://godbolt.org/z/7b4W13Wf4

struct s2{
    s i; //s is in anonymous namespace
};

s2 foo6(){
    return {};
}

Removing this one is dangerous. Even though struct s2 can only be defined in that translation unit, it can still be declared in another translation unit:

struct s2;
extern s2 foo6();
s2(*p)() = foo6;

Where removing the function would cause a linker error. It could also escape back in to the first translation unit, requiring the full definition.


Also it seems a non-inline non-templated function definition with a placeholder return type can be eliminated:

auto unused() { return 1; }

Since other translation units can only contain the declaration auto unused();, where the auto type can never be deduced (so you can't take it's address or call it)

fekir commented 4 months ago

Clang already eliminates this function and warns -Wunused-function for it: https://godbolt.org/z/7b4W13Wf4

Yes, sorry, it was also eliminated in my example

Even though struct s2 can only be defined in that translation unit, it can still be declared in another translation unit:

Oh, did not think about it.

But the function itself still cannot be used in other translation units. Thus if in the current translation unit there are no pointers of the given type... I agree that this use case is not as simple as I've thought.

Also it seems a non-inline non-templated function definition with a placeholder return type can be eliminated:

Nice, it seems that this one is also not detected by gcc and msvc.