Jump to page: 1 2
Thread overview
pragma(inline, true) errors?
Apr 01, 2021
tsbockman
Apr 02, 2021
Johan Engelen
Apr 02, 2021
jmh530
Apr 02, 2021
jmh530
Apr 03, 2021
Johan Engelen
Apr 03, 2021
Max Haughton
Apr 03, 2021
Johan Engelen
Apr 03, 2021
Max Haughton
April 01, 2021
Was diagnosing an issue on raylib-d with inlining. I have found some curious behavior.

Observe the following code:

```d
extern(C) pragma(inline, true) static float EaseBounceOut(float t, float b, float c, float d)
{
    if ((t/=d) < (1.0f/2.75f))
    {
        return (c*(7.5625f*t*t) + b);
    }
    else if (t < (2.0f/2.75f))
    {
        float postFix = t-=(1.5f/2.75f);
        return (c*(7.5625f*(postFix)*t + 0.75f) + b);
    }
    else if (t < (2.5/2.75))
    {
        float postFix = t-=(2.25f/2.75f);
        return (c*(7.5625f*(postFix)*t + 0.9375f) + b);
    }
    else
    {
        float postFix = t-=(2.625f/2.75f);
        return (c*(7.5625f*(postFix)*t + 0.984375f) + b);
    }
}

void main()
{
    auto f = EaseBounceOut(0.5, 1, 1, 1);
}
```

Here is a relevant run.dlang.io snippet: https://run.dlang.io/is/UEtyE8

Some interesting things about this:

1. With -w, I get no errors.
2. With -wi, I get a warning that the function can be inlined
3. Using ASM view, it appears the function is NOT inlined in either case.

I checked historical compilers, and I found that this behavior stems from 2.094. I looked at the changelog, and see this [1].

So I feel like this is a bug, but I'm not sure. I'm assuming the intended behavior is to inline at all costs, and error if it cannot. But I'm not sure of the intended uses of pragma(inline). I feel like if we "fix" this, it will break *a lot* of code.

In general, my thoughts on the pragma(inline) feature are that it is a complete failure. It either doesn't do what I want, or it is so fragile that I don't want to use it. My only use case is for a shim that should never really be emitted into the object file. But D tries to inline not just the shim, but every function it calls as well.

-Steve

[1] https://dlang.org/changelog/2.094.0.html#hasAlwaysInlines
April 01, 2021

On Thursday, 1 April 2021 at 18:38:45 UTC, Steven Schveighoffer wrote:

>

Here is a relevant run.dlang.io snippet: https://run.dlang.io/is/UEtyE8

Some interesting things about this:

  1. With -w, I get no errors.
  2. With -wi, I get a warning that the function can be inlined
  3. Using ASM view, it appears the function is NOT inlined in either case.

DMD's inliner often gets confused by multiple return statements. The solution is to either convert to single-return style, or use LDC/GDC which do not have this problem.

extern(C) pragma(inline, true) static float EaseBounceOut(float t, float b, float c, float d)
{
    float ret;
    if ((t/=d) < (1.0f/2.75f))
    {
        ret = (c*(7.5625f*t*t) + b);
    }
    else if (t < (2.0f/2.75f))
    {
        float postFix = t-=(1.5f/2.75f);
        ret = (c*(7.5625f*(postFix)*t + 0.75f) + b);
    }
    else if (t < (2.5/2.75))
    {
        float postFix = t-=(2.25f/2.75f);
        ret = (c*(7.5625f*(postFix)*t + 0.9375f) + b);
    }
    else
    {
        float postFix = t-=(2.625f/2.75f);
        ret = (c*(7.5625f*(postFix)*t + 0.984375f) + b);
    }
    return ret;
}

(I have no comment on the larger issues that you raised. Also, hurray for rich text formatting!)

April 01, 2021
On 4/1/21 3:13 PM, tsbockman wrote:
> On Thursday, 1 April 2021 at 18:38:45 UTC, Steven Schveighoffer wrote:
>> Here is a relevant run.dlang.io snippet: https://run.dlang.io/is/UEtyE8
>>
>> Some interesting things about this:
>>
>> 1. With -w, I get no errors.
>> 2. With -wi, I get a warning that the function can be inlined
>> 3. Using ASM view, it appears the function is NOT inlined in either case.
> 
> DMD's inliner often gets confused by multiple `return` statements. The solution is to either convert to single-`return` style, or use LDC/GDC which do not have this problem.
> 
> ```D
> extern(C) pragma(inline, true) static float EaseBounceOut(float t, float b, float c, float d)
> {
>     float ret;
>     if ((t/=d) < (1.0f/2.75f))
>     {
>         ret = (c*(7.5625f*t*t) + b);
>     }
>     else if (t < (2.0f/2.75f))
>     {
>         float postFix = t-=(1.5f/2.75f);
>         ret = (c*(7.5625f*(postFix)*t + 0.75f) + b);
>     }
>     else if (t < (2.5/2.75))
>     {
>         float postFix = t-=(2.25f/2.75f);
>         ret = (c*(7.5625f*(postFix)*t + 0.9375f) + b);
>     }
>     else
>     {
>         float postFix = t-=(2.625f/2.75f);
>         ret = (c*(7.5625f*(postFix)*t + 0.984375f) + b);
>     }
>     return ret;
> }
> ```

Yeah, I'm not too concerned with the fact that this can't be inlined, though I probably should just remove that from the lib (looks like that was a recent addition).

I'm more concerned with the larger issue that it's not doing what it says it should be doing.

> (I have no comment on the larger issues that you raised. Also, hurray for rich text formatting!)

Grrrr... I want formatting too :(. Vladimir, we need an X-DFormat = markdown header or something I can use in Thunderbird.

-Steve
April 02, 2021
Nobody has comments on this? It was not an April fool's joke.

To recap:

pragma(inline, true)

means nothing in the current compiler. Well, it doesn't mean nothing, it only means that in the case of configuring the compiler to treat warnings as informational-only, you will get an informational warning. In the case that warnings are treated as an error, your code always compiles, and the function is only inlined based on implementation definitions.

Technically, this is according to spec, as it says what the compiler does if a pragma(inline, true) function cannot be inlined is implementation defined. But it does say "an error message is typical". Given that there is only one front end, the typical (and in fact universal) behavior now is, do nothing.

-Steve
April 02, 2021

On Friday, 2 April 2021 at 14:40:00 UTC, Steven Schveighoffer wrote:

>

pragma(inline, true)

means nothing in the current compiler. Well, it doesn't mean nothing, it only means that in the case of configuring the compiler to treat warnings as informational-only, you will get an informational warning. In the case that warnings are treated as an error, your code always compiles, and the function is only inlined based on implementation definitions.

Technically, this is according to spec, as it says what the compiler does if a pragma(inline, true) function cannot be inlined is implementation defined. But it does say "an error message is typical". Given that there is only one front end, the typical (and in fact universal) behavior now is, do nothing.

I'm pretty sure LDC will never give any warning or error on this pragma.
It will almost always inline the function into the caller (I don't know of cases where it can't).
I question the value of knowing whether a function was inlined or not.
Note that pragma(inline) is very different functionality from "not emitting a function to object file", which is useful functionality but there is no method to do that in D that I know of (and should not be called "inline").

cheers,
Johan

April 02, 2021
On 4/2/21 12:27 PM, Johan Engelen wrote:
> On Friday, 2 April 2021 at 14:40:00 UTC, Steven Schveighoffer wrote:
>>
>> pragma(inline, true)
>>
>> means nothing in the current compiler. Well, it doesn't mean nothing, it only means that in the case of configuring the compiler to treat warnings as informational-only, you will get an informational warning. In the case that warnings are treated as an error, your code always compiles, and the function is only inlined based on implementation definitions.
>>
>> Technically, this is according to spec, as it says what the compiler does if a pragma(inline, true) function cannot be inlined is implementation defined. But it does say "an error message is typical". Given that there is only one front end, the typical (and in fact universal) behavior now is, do nothing.
> 
> I'm pretty sure LDC will _never_ give any warning or error on this pragma.
> It will almost always inline the function into the caller (I don't know of cases where it can't).

So technically for LDC it will never encounter this case.

> I question the value of knowing whether a function was inlined or not.

I don't really care about inlining or not, but I'm forced to reckon with this, because I've taken over maintenance of a package that puts "pragma(inline, true):" at the top of a module, and therefore warnings are being spat out. So I want to ask the question, is this a bug? What is the expectation? Should we just change the description to "issue a informational warning in some cases when the function cannot be inlined"?

Does LDC make any inlining decisions based on this flag?

> Note that `pragma(inline)` is very different functionality from "not emitting a function to object file", which _is_ useful functionality but there is no method to do that in D that I know of (and should not be called "inline").

Yeah, I'm not necessarily invested in a debate about the feature, I just want to know what it really means, so I can make a decision whether to yank the attribute or not.

-Steve
April 02, 2021
On Friday, 2 April 2021 at 17:00:35 UTC, Steven Schveighoffer wrote:
> [snip]
>
> I don't really care about inlining or not, but I'm forced to reckon with this, because I've taken over maintenance of a package that puts "pragma(inline, true):" at the top of a module, and therefore warnings are being spat out. So I want to ask the question, is this a bug? What is the expectation? Should we just change the description to "issue a informational warning in some cases when the function cannot be inlined"?
> [snip]

It only does warnings when you use the -wi flag right? Otherwise it's an error. Is there a problem with the error not being generated when you don't have warnings turned on?
April 02, 2021
On Friday, 2 April 2021 at 17:25:43 UTC, jmh530 wrote:
> On Friday, 2 April 2021 at 17:00:35 UTC, Steven Schveighoffer wrote:
>> [snip]
>>
>> I don't really care about inlining or not, but I'm forced to reckon with this, because I've taken over maintenance of a package that puts "pragma(inline, true):" at the top of a module, and therefore warnings are being spat out. So I want to ask the question, is this a bug? What is the expectation? Should we just change the description to "issue a informational warning in some cases when the function cannot be inlined"?
>> [snip]
>
> It only does warnings when you use the -wi flag right? Otherwise it's an error. Is there a problem with the error not being generated when you don't have warnings turned on?

Yes that is exactly the case. With -w or no switch there is no error or warning. And no inlining.

-Steve

April 02, 2021
On Friday, 2 April 2021 at 18:21:59 UTC, Steven Schveighoffer wrote:
> [snip]
>
> Yes that is exactly the case. With -w or no switch there is no error or warning. And no inlining.
>
> -Steve

So the argument is that it is consistent with the spec, but not with the expected behavior after 2.094.0. For whatever reason, I assumed that the change in 2.094.0 was for the spec too, and not just DMD. A little hard to keep track...
April 03, 2021

On Friday, 2 April 2021 at 17:00:35 UTC, Steven Schveighoffer wrote:

>

On 4/2/21 12:27 PM, Johan Engelen wrote:

>

On Friday, 2 April 2021 at 14:40:00 UTC, Steven Schveighoffer wrote:

>

pragma(inline, true)

means nothing in the current compiler. Well, it doesn't mean nothing, it only means that in the case of configuring the compiler to treat warnings as informational-only, you will get an informational warning. In the case that warnings are treated as an error, your code always compiles, and the function is only inlined based on implementation definitions.

Technically, this is according to spec, as it says what the compiler does if a pragma(inline, true) function cannot be inlined is implementation defined. But it does say "an error message is typical". Given that there is only one front end, the typical (and in fact universal) behavior now is, do nothing.

I'm pretty sure LDC will never give any warning or error on this pragma.
It will almost always inline the function into the caller (I don't know of cases where it can't).

So technically for LDC it will never encounter this case.

Pretty much.
When the function is recursive, it may prevent inlining.

>

Does LDC make any inlining decisions based on this flag?

Yes: the flag sets the alwaysinline attribute on a function, meaning that it will be inlined whenever possible, also at -O0.
https://d.godbolt.org/z/GEe8zxrro

-Johan

« First   ‹ Prev
1 2