Bug 15110 – pragma(inline) rarely works how I want it to

Status
NEW
Severity
enhancement
Priority
P4
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2015-09-24T15:01:20Z
Last change time
2024-12-13T18:44:56Z
Assigned to
No Owner
Creator
Manu
Moved to GitHub: dmd#19049 →

Comments

Comment #0 by turkeyman — 2015-09-24T15:01:20Z
pragma(inline, true) R normalisedSubtract(T, U, R = ResultType!(T, U))(T a, U b) { R x = cast(R)a;//convertNormInt!R(a); R y = cast(R)b;//convertNormInt!R(b); static if(isUnsigned!R) { if(x <= y) return 0; return cast(R)(x - y); } else { auto r = x - y; if(r < R.min) r = R.min; else static if(isSigned!R) { if(r > R.max) r = R.max; } return cast(R)r; } } src\std\experimental\color\internal\normint.d(90): Error: function std.experimental.color.internal.normint.normalisedSubtract!(ubyte, ubyte, ubyte).normalisedSubtract cannot inline function This function is literally nothing more than a single integer subtract. I have no idea why this won't inline. I experience this general problem quite a bit. Strangely, the addition compliment to this function doesn't complain.
Comment #1 by code — 2015-09-24T15:49:11Z
Didn't Walter just fix an issue like this in master? The problem is probably that DMD can't/couldn't inline "if (a) return b; return c;"-type constructs.
Comment #2 by turkeyman — 2015-09-24T23:39:08Z
Okay. I've encountered this sort of problem a lot, it might all be the same problem though, this isn't exactly an uncommon pattern.
Comment #3 by yebblies — 2015-09-29T13:56:28Z
> pragma(inline) rarely works how I want it to How exactly are you expecting pragma(inline) to work?
Comment #4 by turkeyman — 2015-09-29T22:21:34Z
Well, firstly, it should inline. Secondly, it should never be an error if it's impossible to inline (it should be a warning). Ie, exactly like __forceinline in C++. Also, it would be nice if it were an attribute (like GDC/LDC) so it can be aliased.
Comment #5 by ibuclaw — 2015-09-30T07:08:41Z
(In reply to Manu from comment #4) > Well, firstly, it should inline. > Secondly, it should never be an error if it's impossible to inline (it > should be a warning). > I disagree on point 2 here (it rightly should be an error). But then again we are talking about a behaviour that can't be regulated with our current choice of compiler technologies. So you'll have to accept that each will do it's own independent thing here. > Ie, exactly like __forceinline in C++. > There is no __forceinline in C++. :-)
Comment #6 by turkeyman — 2015-10-03T23:55:25Z
There are cases where it should be valid to fail inlining, but shouldn't be an error. For instance, if I take the address of the function, that kinda implies it needs to emit an instance of the function... I shouldn't need to duplicate the function just because I take a function pointer in some situation. Another problem is that it's difficult to make all compilers inline with exactly the same behaviour, and what might work fine in one doesn't work in the other. I don't believe it's reasonable for this to emit a compile error when behaviour is different between compilers. You can't reliably build code anymore. It should just be a warning. The user needs to know when it doesn't inline, and they can then take appropriate action, but it shouldn't stop the program from compiling. That's highly annoying, it may create mutual-exclusions with other configurations where it works fine. It may very well be a niche configuration where it doesn't work (probably, since inhibitors would be addressed in the main configuration). There's no value in making it an error, it's only annoying, and results in code that's almost certainly brittle, since you have no idea whether your code will compile without errors unless you test every possible configuration. __forceinline/__attribute__((always_inline)). The behaviour is the same; it's a warning when inlining fails, and it would be extremely inconvenient (to the point of the feature being virtually useless) if it didn't behave this way.
Comment #7 by slavo5150 — 2019-06-05T02:39:25Z
The problem is that DMD currently ignores `pragma(inline, true)` unless the compiler is invoked with `-inline`. I think the correct behavior is that `pragma(inline, true)` should work regardless of the presence of the `-inline` compiler flag.
Comment #8 by turkeyman — 2019-06-05T02:55:14Z
Right. I think `pragma(inline, true)` should express an AST inline in the front-end, and fail whenever such inlining can't occur.
Comment #9 by turkeyman — 2019-06-05T02:56:02Z
** error even
Comment #10 by bugzilla — 2020-06-06T06:22:58Z
Manu, I thought you had argued strongly to me that if the inlining fails an error should be generated.
Comment #11 by turkeyman — 2020-06-08T02:34:40Z
(In reply to Walter Bright from comment #10) > Manu, I thought you had argued strongly to me that if the inlining fails an > error should be generated. True, but I also think I understand a little more nuance now than I did 8 years ago. I'll make these points from today's perspective: 1. All arguments I made at that time were based on a presumption that inline worked *AT LEAST* as I expected as a native C/C++ ABI developer. It may have been inexperience to assume that, but I absolutely did assume that the binary linkage facets of inline would be 'predictable' as I considered that a baseline for the concept, and what I was arguing were the details where our definition may be distinct from those expectations. I was essentially arguing the high-level semantic; we wanted to be confident inline 'worked' (did inline), but I did leave out the other ABI related considerations that are useful and predictable things about binary generation and linkage from the conversation. 2. I still feel it's valuable to have an error when inlining fails, but I change my mind on the absolute-ness of this from time to time... I think both are valuable in different cases. Today I would argue for `inline` to behave as people expect when interacting with typical native code ecosystems, and `forceinline` to produce an error, in addition to those linkage details. What I think the most useful union of concepts would look like, is that `(inline, true)` do what I've been saying; emit the symbol only when called, and mark it with the internal linkage flag. I think this is what most people want almost all of the time, and it's generally compatible with widely standard binary/linkage environments. I don't think it's right that people should experience weird surprises when trying to integration into their existing ecosystems. We have no reason not to work in a 'standard' way here. `(inline, force)` could emit an error when inlining is impossible (like taking the address), but while it's left to the optimiser, GCC/LLVM will always have ultimate agency over inlining. The only way I can imagine that we can assure a reliable error when inlining fails is if it's performed in the front-end. I think what's underlying all of this, is that `inline` in C/C++ is frequently (almost exclusively?) used as a mechanism to control your binary output. Accepting the attribute as a hint that inlining is desirable is nice, but what really matters is that it is used to control the formation of the binary, and how it interacts with the linker environment. There are 2 particularly useful tools in C/C++, `inline` (ie, on-demand + internal linkage) and `weak` (nix + windows express this differently). We have neither of those in D... I see no reason why 'inline' should not be used to inform the first thing; the rule of least surprise makes it the obvious thing to do, but it may also be possible to have an alternative way to express that extremely useful concept.
Comment #12 by robert.schadek — 2024-12-13T18:44:56Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19049 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB