[llvm-dev] Inline constant std::function parameter

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

[llvm-dev] Inline constant std::function parameter

韩玉 via llvm-dev
Hey LLVM-dev,

I'm trying to inline the following C++ code:

    __attribute__((always_inline)) static void inline compose(const char* s, std::function<void(const char *)> f) {
        std::cout << s << std::endl;
        f(s);
    }
   
    // --------------- Main ---------------
    int main() {
        // Nest three things
        compose("hello world", [](const char *s) {
            compose("hello again", [](const char *s) {
                compose("hello third time", [](const char *s) {
                    return;
                });
            });
        });
   
        return 0;
    }

Here my continuations are of type `std::function<void(const char*)>` and what I wanted from LLVM with the `always_inline` option was to transform it to a single call-site that looks like this:


    // --------------- Main ---------------
    int main() {
        // Nest three things
        std::cout << "hello world" << std::endl;
        std::cout << "hello again" << std::endl;
        std::cout << "hello third time" << std::endl;
        return 0;
    }

However that doesn't seem to be the case, does the inliner not get triggered if the functions are passed as objects (std::function) or am I using the wrong `opt` invokation?

    OPT=opt-6.0
    OPTFLAGS?=-O3 -always-inline -dot-callgraph

Thanks!


_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

smime.p7s (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] Inline constant std::function parameter

韩玉 via llvm-dev
On 5/29/2018 10:52 AM, Eleftherios Ioannidis via llvm-dev wrote:
> However that doesn't seem to be the case, does the inliner not get triggered if the functions are passed as objects (std::function) or am I using the wrong `opt` invokation?

In general, the inliner can only inline direct function calls (not
virtual calls, or calls through a function pointer or std::function);
otherwise, it doesn't know what to inline.

In some cases, optimizations can prove that an indirect call actually
calls some specific function, but your testcase isn't one of those
cases.  In particular, the implementation of std::function is kind of
hard for the optimizer to deal with. This could probably be improved.

-Eli

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] Inline constant std::function parameter

韩玉 via llvm-dev
I was afraid that was the case, since std::function is not a first-class object of LLVM.
Every implementation that I can think of that inlines std::function intrinsically seems a bit awkward, in the way that it will be along the lines:

“Treat this class (std::function) in a special way”

A better way would be to generalize for all callables, and say something along the lines of

“If a class has the () operator, see if you can inline that method”

But that too is too specific to C++ and I’m afraid high-level operator semantics will be lost by the time it turns to byte code. Seems to me, the sane solution would be for clang++ to treat std::function as an LLVM function type (https://llvm.org/docs/LangRef.html#function-type) instead of a class object and then the road to these optimizations will open. But I have not looked at the gritty details of the clang implementation, so I could be way off. Anybody willing to step in and fill the blanks would be appreciated.

Regards,
Lef



On May 29, 2018, at 2:53 PM, Friedman, Eli <[hidden email]> wrote:

On 5/29/2018 10:52 AM, Eleftherios Ioannidis via llvm-dev wrote:
However that doesn't seem to be the case, does the inliner not get triggered if the functions are passed as objects (std::function) or am I using the wrong `opt` invokation?

In general, the inliner can only inline direct function calls (not virtual calls, or calls through a function pointer or std::function); otherwise, it doesn't know what to inline.

In some cases, optimizations can prove that an indirect call actually calls some specific function, but your testcase isn't one of those cases.  In particular, the implementation of std::function is kind of hard for the optimizer to deal with. This could probably be improved.

-Eli

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project



_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

smime.p7s (2K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: [llvm-dev] Inline constant std::function parameter

韩玉 via llvm-dev
Yeah, it's unfortunately a fair bit more complicated than that.

It's unlikely that LLVM or Clang would ever special-case the IR for std::function specifically. Generally the goal would be to find what parts of LLVM aren't able to see through the abstractions in std::function to optimize it generally.

On Tue, May 29, 2018 at 12:44 PM Eleftherios Ioannidis via llvm-dev <[hidden email]> wrote:
I was afraid that was the case, since std::function is not a first-class object of LLVM.
Every implementation that I can think of that inlines std::function intrinsically seems a bit awkward, in the way that it will be along the lines:

“Treat this class (std::function) in a special way”

A better way would be to generalize for all callables, and say something along the lines of

“If a class has the () operator, see if you can inline that method”

But that too is too specific to C++ and I’m afraid high-level operator semantics will be lost by the time it turns to byte code. Seems to me, the sane solution would be for clang++ to treat std::function as an LLVM function type (https://llvm.org/docs/LangRef.html#function-type) instead of a class object and then the road to these optimizations will open. But I have not looked at the gritty details of the clang implementation, so I could be way off. Anybody willing to step in and fill the blanks would be appreciated.

Regards,
Lef



On May 29, 2018, at 2:53 PM, Friedman, Eli <[hidden email]> wrote:

On 5/29/2018 10:52 AM, Eleftherios Ioannidis via llvm-dev wrote:
However that doesn't seem to be the case, does the inliner not get triggered if the functions are passed as objects (std::function) or am I using the wrong `opt` invokation?

In general, the inliner can only inline direct function calls (not virtual calls, or calls through a function pointer or std::function); otherwise, it doesn't know what to inline.

In some cases, optimizations can prove that an indirect call actually calls some specific function, but your testcase isn't one of those cases.  In particular, the implementation of std::function is kind of hard for the optimizer to deal with. This could probably be improved.

-Eli

--
Employee of Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project


_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev

_______________________________________________
LLVM Developers mailing list
[hidden email]
http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev