www.digitalmars.com         C & C++   DMDScript  

D - computing compile-time constants

reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
Sometimes you need to have compile time constants (an enum perhaps.)  The
situation I'm running into is D3D's definition of its HRESULT error codes.
It uses a macro MAKE_D3DHRESULT to do the computation.  Aside from expanding
it out manually I don't think there's any way in D to have a reusable
function-style package that generates compile time constants if given
compile time constants as inputs.

Surely the compiler could check when it expects a compile time constant and
instead encounters a function call, check if the function is inlineable and
the arguments are compile-time constants, and if so evaluates the function
at compile time?

Or is there some other way this can be automated?  I'd hate to duplicate
that much code using copy'n'paste.  Copy'n'paste coding is the opposite of
refactoring and is A Bad Thing.

Sean
Jun 08 2002
next sibling parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
Something like:

int f(int n) = n * 4 + 1;

Might work.  It's like shortcut function syntax that combines a computation
with a return of result and AFAIK so long as we don't allow it to call real
functions, can be evaluated at compile time.

the above would be roughly equivalent to:

int f(int n) { return n * 4 + 1; }

So mostly just syntax sugar I guess.  The real problem is turning all
possible arbitrary compile-time constant expressions into constants at
compile time, even in say debug builds.

It might also be interesting to have "non constant" constant expressions...
more like equivalence.  Such as:

double price_of_oil = 24.99;
double gasoline_scale_factor = 24.99;
let double price_of_gasoline = price_of_oil * gasoline_scale_factor;

This is also a form of syntax sugar for parameterless function calls.  But
this form would be used just like a variable except you can't store into it,
and reads evaluate the function.

Sean

"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:adu2u3$1gv1$1 digitaldaemon.com...
 Sometimes you need to have compile time constants (an enum perhaps.)  The
 situation I'm running into is D3D's definition of its HRESULT error codes.
 It uses a macro MAKE_D3DHRESULT to do the computation.  Aside from
expanding
 it out manually I don't think there's any way in D to have a reusable
 function-style package that generates compile time constants if given
 compile time constants as inputs.

 Surely the compiler could check when it expects a compile time constant
and
 instead encounters a function call, check if the function is inlineable
and
 the arguments are compile-time constants, and if so evaluates the function
 at compile time?

 Or is there some other way this can be automated?  I'd hate to duplicate
 that much code using copy'n'paste.  Copy'n'paste coding is the opposite of
 refactoring and is A Bad Thing.

 Sean
Jun 08 2002
next sibling parent "Carlos" <carlos8294 msn.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> escribió en el mensaje
news:adu6b9$1kh9$1 digitaldaemon.com...
 Something like:

 int f(int n) = n * 4 + 1;

 Might work.  It's like shortcut function syntax that combines a
computation
 with a return of result and AFAIK so long as we don't allow it to call
real
 functions, can be evaluated at compile time.

 the above would be roughly equivalent to:

 int f(int n) { return n * 4 + 1; }
I don't know if this could work much. And I say this from experience: in old releases of Basic (gwbasic, qb, etc.) there was something like this: def fnfoo(n)=n*4+1 and it was a function (since old Basics didn't have procedures, functions, subroutines, etc.). Eventually it was replaced (and eventually eliminated) by the (normal) syntax: function foo (n as integer) as integer ... end function now, many criticize Basic, but in all the mistakes that Basic has (in programming style I mean), they changed that syntax for good. They saw that other programming languages didn't work that way for a reason, so it wasn't a good idea to keep. So adding it to D, IMHO, would be like returning to the days when you had to put a line in every single line.
Jun 08 2002
prev sibling next sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:adu6b9$1kh9$1 digitaldaemon.com...

 Something like:

 int f(int n) = n * 4 + 1;

 Might work.  It's like shortcut function syntax that combines a
computation
 with a return of result and AFAIK so long as we don't allow it to call
real
 functions, can be evaluated at compile time.

 the above would be roughly equivalent to:

 int f(int n) { return n * 4 + 1; }
Maybe use the const attribute? I think it is a good idea, as long as such declaration would be _restricted_ to constant arguments. This would make it possible to do things like: const int f(int n) = n * 4 + 1; const int a = 3; const int b = f(a); Such a code cannot be written using inline functions...
Jun 10 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:ae354f$lqc$1 digitaldaemon.com...
 "Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
 news:adu6b9$1kh9$1 digitaldaemon.com...

 Something like:

 int f(int n) = n * 4 + 1;

 Might work.  It's like shortcut function syntax that combines a
computation
 with a return of result and AFAIK so long as we don't allow it to call
real
 functions, can be evaluated at compile time.

 the above would be roughly equivalent to:

 int f(int n) { return n * 4 + 1; }
Maybe use the const attribute? I think it is a good idea, as long as such declaration would be
_restricted_
 to constant arguments. This would make it possible to do things like:

     const int f(int n) = n * 4 + 1;
     const int a = 3;
     const int b = f(a);

 Such a code cannot be written using inline functions...
Yes, that should work. We definitely need something like this. It's one of the few uses of macros D hasn't found a better replacement for yet. Sean
Jun 10 2002
parent "Matthew Wilson" <dm synesis-group.com> writes:
It gets my vote

"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ae41ms$1i0o$1 digitaldaemon.com...
 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:ae354f$lqc$1 digitaldaemon.com...
 "Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
 news:adu6b9$1kh9$1 digitaldaemon.com...

 Something like:

 int f(int n) = n * 4 + 1;

 Might work.  It's like shortcut function syntax that combines a
computation
 with a return of result and AFAIK so long as we don't allow it to call
real
 functions, can be evaluated at compile time.

 the above would be roughly equivalent to:

 int f(int n) { return n * 4 + 1; }
Maybe use the const attribute? I think it is a good idea, as long as such declaration would be
_restricted_
 to constant arguments. This would make it possible to do things like:

     const int f(int n) = n * 4 + 1;
     const int a = 3;
     const int b = f(a);

 Such a code cannot be written using inline functions...
Yes, that should work. We definitely need something like this. It's one
of
 the few uses of macros D hasn't found a better replacement for yet.

 Sean
Jun 10 2002
prev sibling parent reply "Sandor Hojtsy" <hojtsy index.hu> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:adu6b9$1kh9$1 digitaldaemon.com...
 Something like:

 int f(int n) = n * 4 + 1;

 Might work.  It's like shortcut function syntax that combines a
computation
 with a return of result and AFAIK so long as we don't allow it to call
real
 functions, can be evaluated at compile time.

 the above would be roughly equivalent to:

 int f(int n) { return n * 4 + 1; }

 So mostly just syntax sugar I guess.  The real problem is turning all
 possible arbitrary compile-time constant expressions into constants at
 compile time, even in say debug builds.

 It might also be interesting to have "non constant" constant
expressions...
 more like equivalence.  Such as:

 double price_of_oil = 24.99;
 double gasoline_scale_factor = 24.99;
 let double price_of_gasoline = price_of_oil * gasoline_scale_factor;

 This is also a form of syntax sugar for parameterless function calls.  But
 this form would be used just like a variable except you can't store into
it,
 and reads evaluate the function.
Hmm... Well, it seems to me this is actually syntax suggar for preprocessing! #define f(n) ((n)*4+1) #define price_of_gasoline ((price_of_oil) * (gasoline_scale_factor)) The syntax is different but the same effect. Or was it the syntax, that was problematic with the C preprocessor? I don't think so. Actually I love compile time computations, so I think we will need something to fill the gap left by the absence of the preprocessor. An other idea come up with that price_of_gasoline: GLOBAL PROPERTIES (tada!). So you can have: temperature = 10; int t = temperature; While temperature is actually a global property with a global gettor and/or settor function. THAT seems useful to me. Sandor
Jun 11 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Sandor Hojtsy" <hojtsy index.hu> wrote in message
news:ae50gr$2i9o$1 digitaldaemon.com...

 Hmm...
 Well, it seems to me this is actually syntax suggar for preprocessing!
 #define f(n) ((n)*4+1)
 #define price_of_gasoline ((price_of_oil) * (gasoline_scale_factor))
 The syntax is different but the same effect.
There _is_ a difference: // C++ #define f(n) n * n f(n++) == n++ * n++; // possibly D int f(int n) = n * n; f(n++) == (n++, n * n) n++ only gets computed once. Besides, this solution is typesafe: you should pass an int, and you cannot pass a string or even some keyword.
Jun 11 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
A nice side effect of this is that you get *forced* inlining?  Or would you?

Sean

"Pavel Minayev" <evilone omen.ru> wrote in message
news:ae57ei$2ptd$1 digitaldaemon.com...
 "Sandor Hojtsy" <hojtsy index.hu> wrote in message
 news:ae50gr$2i9o$1 digitaldaemon.com...

 Hmm...
 Well, it seems to me this is actually syntax suggar for preprocessing!
 #define f(n) ((n)*4+1)
 #define price_of_gasoline ((price_of_oil) * (gasoline_scale_factor))
 The syntax is different but the same effect.
There _is_ a difference: // C++ #define f(n) n * n f(n++) == n++ * n++; // possibly D int f(int n) = n * n; f(n++) == (n++, n * n) n++ only gets computed once. Besides, this solution is typesafe: you should pass an int, and you cannot pass a string or even some keyword.
Jun 11 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:ae5ghn$1ut$1 digitaldaemon.com...

 A nice side effect of this is that you get *forced* inlining?  Or would
you? Yes, absolutely. Since function can only consist of expression, it can always be inlined. In those cases where all arguments are const, the expression is simply calculated and the result is inserted into the code, also making it possible to be used in const expression. If arguments are variable, a code to calculate the expression would be generated: const word lo(dword d) = d & 0xFFFF; const word hi(dword d) = d >> 16; const int a = 12345678; const int b = hi(a); const int c = lo(a); int main() { dword x; scanf("%d", &x); printf("%d %d\n", hi(x), lo(x)); return 0; } What do you think of all this, Walter?
Jun 12 2002
prev sibling next sibling parent reply "Walter" <walter digitalmars.com> writes:
Inline functions are implemented. As such, the stuff will get folded if the
optimizer is running. Unfortunately, the earlier passes don't know it can be
folded, so for example case values will produce an error message about not
being constant.

Perhaps this can be improved so that functions that simply do a constant
calculation get folded in the semantic phase rather than the optimization
phase. This will avoid needing to change the language specification.

-Walter

"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:adu2u3$1gv1$1 digitaldaemon.com...
 Sometimes you need to have compile time constants (an enum perhaps.)  The
 situation I'm running into is D3D's definition of its HRESULT error codes.
 It uses a macro MAKE_D3DHRESULT to do the computation.  Aside from
expanding
 it out manually I don't think there's any way in D to have a reusable
 function-style package that generates compile time constants if given
 compile time constants as inputs.

 Surely the compiler could check when it expects a compile time constant
and
 instead encounters a function call, check if the function is inlineable
and
 the arguments are compile-time constants, and if so evaluates the function
 at compile time?

 Or is there some other way this can be automated?  I'd hate to duplicate
 that much code using copy'n'paste.  Copy'n'paste coding is the opposite of
 refactoring and is A Bad Thing.

 Sean
Jun 12 2002
next sibling parent reply "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:ae8et9$1b1b$1 digitaldaemon.com...

 Inline functions are implemented. As such, the stuff will get folded if
the
 optimizer is running. Unfortunately, the earlier passes don't know it can
be
 folded, so for example case values will produce an error message about not
 being constant.

 Perhaps this can be improved so that functions that simply do a constant
 calculation get folded in the semantic phase rather than the optimization
 phase. This will avoid needing to change the language specification.
I've pushed for some thing like this before: allowing the programmer to specify that an inline function MUST be inlined instead of letting the optimizer choose. For constant expressions, that would be a really nice thing, too. Salutaciones, JCAB
Jun 12 2002
next sibling parent "Matthew Wilson" <dm synesis-group.com> writes:
I would also like to have that same "power", although it would be even nicer
if the compiler could warn when such an assertion would likely produce
code-bloat / performance problems (though I recognise that's going to be
complex)

"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:ae8g2c$1c7h$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:ae8et9$1b1b$1 digitaldaemon.com...

 Inline functions are implemented. As such, the stuff will get folded if
the
 optimizer is running. Unfortunately, the earlier passes don't know it
can
 be
 folded, so for example case values will produce an error message about
not
 being constant.

 Perhaps this can be improved so that functions that simply do a constant
 calculation get folded in the semantic phase rather than the
optimization
 phase. This will avoid needing to change the language specification.
I've pushed for some thing like this before: allowing the programmer to specify that an inline function MUST be inlined instead of letting the optimizer choose. For constant expressions, that would be a really nice thing, too. Salutaciones, JCAB
Jun 12 2002
prev sibling parent reply "Walter" <walter digitalmars.com> writes:
"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:ae8g2c$1c7h$1 digitaldaemon.com...
    I've pushed for some thing like this before: allowing the programmer to
 specify that an inline function MUST be inlined instead of letting the
 optimizer choose. For constant expressions, that would be a really nice
 thing, too.
Time for a philosophical question - why do you need to control whether a function is actually inlined or not? Isn't that like using the 'register' keyword in C, and just as obsolete? As long as the semantics are maintained, inlining should be at the compiler's discretion, and how well it is done should be a quality-of-implementation issue. I see the inlining issue as an overall speed/space tradeoff, something that you'd specify with a global switch on the compiler. (For debug compiles, it's nice to not inline anything, so that breakpoints on function calls work.)
Jun 13 2002
next sibling parent reply "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:aeb9eg$1c72$2 digitaldaemon.com...

 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:ae8g2c$1c7h$1 digitaldaemon.com...

    I've pushed for some thing like this before: allowing the programmer
to
 specify that an inline function MUST be inlined instead of letting the
 optimizer choose. For constant expressions, that would be a really nice
 thing, too.
Time for a philosophical question - why do you need to control whether a function is actually inlined or not?
Ok... I guess I asked for it :)
 Isn't that like using the 'register' keyword in C, and just as obsolete?
I'll admit it is a control-freak's pacifier. With the perfect compiler, it wouldn't be needed. Under ideal conditions, I would let the compiler do it. Problem is, I've never seen a compiler get it consistently right. Maybe it's just me, after all, I don't have that much experience with most compilers (including yours, which I can't use for lack of enough C++ support). Visual C++ is particularly bad, and it is the one I know best at this point. The thing is, when coding, I often have things that I _know_ should be best inlined, so I'd like to be able to tell the compiler to do it. Tell, not ask. Automatic processing of data is a good thing that saves work from the human, but in my experience it usually gets 80% short of the results of the human. Wether it is program optimization, or 3D mesh tri-stripping, or voice recognition. It's not reasonable to force a human to do all the processing, but still it is a good thing to let the human provide additional information. A question: does the compiler do the inlining on the initial translation phase, ot during final optimization?
 As long as the semantics are maintained,
 inlining should be at the compiler's discretion, and how well it is done
 should be a quality-of-implementation issue.

 I see the inlining issue as an overall speed/space tradeoff, something
that
 you'd specify with a global switch on the compiler.
I guess I do agree on this. Would you say your compiler would be able to satisfy me in this regard?
 (For debug compiles, it's nice to not inline anything, so that breakpoints
 on function calls work.)
I totally disagree with you on this. I would really want some inlining on debug builds, too. The problem of propagating a breakpoint on the function to all the points where it got inlined, sounds no worse to me than, for example, the problem of propagating it to all instances of a template. I guess that my main point of conflict in philosophy with you, Walter, is that I prefer to put the burden of implementation in the program instead of in the human who is using the program. Consider: things like ambiguities hurt both, so they are bad to have in a language, but things like automatic resource management help the human but make the program harder, so you seem contrary to using them while I'm not. Maybe that's too much of a generalization, but I do see this kind of pattern somewhere in there. In this case, I would want the compiler/debugger to be smart enough to do the right thing while still allow inlining. It's harder, but it makes the experience of debugging potentially better for the user. And while we're talking about philosophy, the other point of philosophy that I embrace and you seem to avoid is leaving the (optional) power in the user's (programmer's in this case) hands. If the programmer _knows_ he wants a function to be inlined, I don't see why the language should get in the way. I'm aware that you can't possibly foresee all possible things that the programmer might want to express, but at least you shouldn't try to shy away from those things programmers have already wanted to express in other languages. This is something in which C++, with all its deficiencies, really shines: even if a programmer cannot quite express something, maybe she can make a library that lets her express it. The Spirit library (on SourceForge), for one, is a clear example of this. Mind over language, so to speak. All this is easy for me to say, of course. After all, it's not me the one designng a new language implementing its compiler suite. :) Well, actually it is, but I'm just doing it in my limited free time, starting with C++, from scratch and without experience, so it's going super-extra-slow. I would love to get into a discussion of language philosopy, design and implementation, but that would be kind of off-topic here. Salutaciones, JCAB
Jun 13 2002
next sibling parent "Matthew Wilson" <matthew thedjournal.com> writes:
JCAB

I think we have another opinion-piece for "The D Journal". Would you be
prepared to write this note up as such, and submit it? I think it would
provide some interesting reading ...

Matthew

"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:aebmod$1o80$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:aeb9eg$1c72$2 digitaldaemon.com...

 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:ae8g2c$1c7h$1 digitaldaemon.com...

    I've pushed for some thing like this before: allowing the
programmer
 to
 specify that an inline function MUST be inlined instead of letting the
 optimizer choose. For constant expressions, that would be a really
nice
 thing, too.
Time for a philosophical question - why do you need to control whether a function is actually inlined or not?
Ok... I guess I asked for it :)
 Isn't that like using the 'register' keyword in C, and just as obsolete?
I'll admit it is a control-freak's pacifier. With the perfect compiler, it wouldn't be needed. Under ideal conditions, I would let the compiler do it. Problem is,
I've
 never seen a compiler get it consistently right. Maybe it's just me, after
 all, I don't have that much experience with most compilers (including
yours,
 which I can't use for lack of enough C++ support). Visual C++ is
 particularly bad, and it is the one I know best at this point. The thing
is,
 when coding, I often have things that I _know_ should be best inlined, so
 I'd like to be able to tell the compiler to do it. Tell, not ask.
Automatic
 processing of data is a good thing that saves work from the human, but in
my
 experience it usually gets 80% short of the results of the human. Wether
it
 is program optimization, or 3D mesh tri-stripping, or voice recognition.
 It's not reasonable to force a human to do all the processing, but still
it
 is a good thing to let the human provide additional information.

    A question: does the compiler do the inlining on the initial
translation
 phase, ot during final optimization?

 As long as the semantics are maintained,
 inlining should be at the compiler's discretion, and how well it is done
 should be a quality-of-implementation issue.

 I see the inlining issue as an overall speed/space tradeoff, something
that
 you'd specify with a global switch on the compiler.
I guess I do agree on this. Would you say your compiler would be able
to
 satisfy me in this regard?

 (For debug compiles, it's nice to not inline anything, so that
breakpoints
 on function calls work.)
I totally disagree with you on this. I would really want some inlining
on
 debug builds, too. The problem of propagating a breakpoint on the function
 to all the points where it got inlined, sounds no worse to me than, for
 example, the problem of propagating it to all instances of a template.

    I guess that my main point of conflict in philosophy with you, Walter,
is
 that I prefer to put the burden of implementation in the program instead
of
 in the human who is using the program. Consider: things like ambiguities
 hurt both, so they are bad to have in a language, but things like
automatic
 resource management help the human but make the program harder, so you
seem
 contrary to using them while I'm not. Maybe that's too much of a
 generalization, but I do see this kind of pattern somewhere in there.

    In this case, I would want the compiler/debugger to be smart enough to
do
 the right thing while still allow inlining. It's harder, but it makes the
 experience of debugging potentially better for the user.

    And while we're talking about philosophy, the other point of philosophy
 that I embrace and you seem to avoid is leaving the (optional) power in
the
 user's (programmer's in this case) hands. If the programmer _knows_ he
wants
 a function to be inlined, I don't see why the language should get in the
 way. I'm aware that you can't possibly foresee all possible things that
the
 programmer might want to express, but at least you shouldn't try to shy
away
 from those things programmers have already wanted to express in other
 languages. This is something in which C++, with all its deficiencies,
really
 shines: even if a programmer cannot quite express something, maybe she can
 make a library that lets her express it. The Spirit library (on
 SourceForge), for one, is a clear example of this. Mind over language, so
to
 speak.

    All this is easy for me to say, of course. After all, it's not me the
one
 designng a new language implementing its compiler suite. :) Well, actually
 it is, but I'm just doing it in my limited free time, starting with C++,
 from scratch and without experience, so it's going super-extra-slow. I
would
 love to get into a discussion of language philosopy, design and
 implementation, but that would be kind of off-topic here.

 Salutaciones,
                          JCAB
Jun 13 2002
prev sibling parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
news:aebmod$1o80$1 digitaldaemon.com...

    A question: does the compiler do the inlining on the initial
translation
 phase, ot during final optimization?
I would rather it be done on initial translation, probably; I guess right during semantic analysis at point of call. Provided there were no bugs in the inlining algorithm (or that the vendor provides a way to turn off inlining in case there is a bug). Of course the vendor will make sure there's no bugs in the inlining process, right? ;) Sean
Jun 14 2002
next sibling parent "Juan Carlos Arevalo Baeza" <jcab roningames.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:aec4nf$279h$1 digitaldaemon.com...

 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:aebmod$1o80$1 digitaldaemon.com...

    A question: does the compiler do the inlining on the initial
translation
 phase, ot during final optimization?
I would rather it be done on initial translation, probably; I guess right during semantic analysis at point of call. Provided there were no bugs in the inlining algorithm (or that the vendor provides a way to turn off inlining in case there is a bug). Of course the vendor will make sure there's no bugs in the inlining process, right? ;)
:-) I totally agree. Still, my guts tell me that it's usually done during optimization or code generation. I just wanted Walter's take on it. Salutaciones, JCAB
Jun 14 2002
prev sibling parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:aec4nf$279h$1 digitaldaemon.com...
 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:aebmod$1o80$1 digitaldaemon.com...

    A question: does the compiler do the inlining on the initial
translation
 phase, ot during final optimization?
I would rather it be done on initial translation, probably; I guess right during semantic analysis at point of call.
The inlining is done in a pass after semantic analysis but before optimization.
Jun 14 2002
prev sibling next sibling parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
"Walter" <walter digitalmars.com> wrote in message
news:aeb9eg$1c72$2 digitaldaemon.com...
 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:ae8g2c$1c7h$1 digitaldaemon.com...
    I've pushed for some thing like this before: allowing the programmer
to
 specify that an inline function MUST be inlined instead of letting the
 optimizer choose. For constant expressions, that would be a really nice
 thing, too.
Time for a philosophical question - why do you need to control whether a function is actually inlined or not? Isn't that like using the 'register' keyword in C, and just as obsolete? As long as the semantics are
maintained,
 inlining should be at the compiler's discretion, and how well it is done
 should be a quality-of-implementation issue.
I kind of disagree with this. See below.
 I see the inlining issue as an overall speed/space tradeoff, something
that
 you'd specify with a global switch on the compiler.
Yes. And for the most part that's what you want. However I know from a fact that sometimes the &$* % compiler vendors decide, in their infinite wisdom, to cause the compiler to not inline something for some reason that is based on flawed reasoning; any reasoning that is not based on hard empirical evidence of execution flow and profiling is likely to be wrong, and can cost precious milliseconds in a game innerloop. The programmer is infinitely better at deciding what absolutely must be inlined than the compiler is, so it is *very* handy to be able to force the stupid compiler to inline something that you know needs to be inlined than for the programmer to have no tool at their disposal to do anything about the speed problem. It's not like we have macros to resort to, either; At least in C++ we had those. In D we'd have no choice but to copy and paste "manually inlined" chunks of code around to make sure they get optimized properly. And that is *very* bad for maintenance reasons. It's the opposite of refactoring, which is a very good thing. Please give the programmer some way to control this. At very least let it be a "strong hint" to the optimizer that this function should be inlined *if at all possible*. Perhaps even in a debug build. And same for "register" keyword in C; many times that keyword was misused (along with "const" as a way to tell the compiler that there *will* be *no* aliasing on that value (register variables cannot have their address taken)). I do not know of a compiler that can 100% verify whether a value is aliased and thus whether its value will change across a function call. With "register" keyword we can assure the compiler it shouldn't worry about it and thus it's safe to optimize the value (leave it in a register, for instance). I really think in the Real World (TM) programmers end up *needing* this level of control over the code the compiler produces. Bitching at the compiler walter to get us an upgrade pronto that inlines better is usually not a viable option when deadlines are looming. So please give us some kind of "optimize" or "inline" keywords or attributes to help the compiler do a better job of generating optimal code. Not everyone can write a badass optimizing backend like you can. ;) But we still need to run on those platforms.
 (For debug compiles, it's nice to not inline anything, so that breakpoints
 on function calls work.)
Constant folding can still take place just not through inline function calls. Some minor optimizations are possible in debug builds (ones that do not alter execution order at all). In fact many times this is desirable (try debugging a debug build of the game that is running at 2 FPS, it is very hard to steer your guy around and reproduce game behavior. But still easier than debugging the same problem in a fully optimized build)
Jun 14 2002
parent reply "Walter" <walter digitalmars.com> writes:
Generally, a function is inlined if it is below a certain threshold of
complexity. The idea is short, simple functions get inlined, and large
complex ones do not. In what circumstances would this not be what is desired
anyway?
Jun 14 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
Because what *YOU* the compiler vendor think is an "acceptable" threshold
for how simple it should be, may be too low, or too high.  In my experience
it's too low; what I think is simple (say, an empty constructor or one that
initializes a 4x4 matrix with identity) may be "too much" for the poor
compiler to allow to be inlined.  A few critical sections of code may need
inlining even though they exceed that arbitrary limit.  Sometimes,
especially with later optimization and constant folding, sometimes the
entire function just optimizes away, but the compiler wouldn't know that
until it tried.  I would err on the side of inlining too much, since RAM is
cheap and code caches are too small anyway.

Maybe if there is an inlining switch it could have a range setting, from low
to high and in between.  However even "high" may not be enough in some
situations.  So some quanta may be necessary.

Sean


"Walter" <walter digitalmars.com> wrote in message
news:aee4ke$16it$2 digitaldaemon.com...
 Generally, a function is inlined if it is below a certain threshold of
 complexity. The idea is short, simple functions get inlined, and large
 complex ones do not. In what circumstances would this not be what is
desired
 anyway?
Jun 15 2002
parent "Walter" <walter digitalmars.com> writes:
"Sean L. Palmer" <seanpalmer earthlink.net> wrote in message
news:aef16u$2ee1$1 digitaldaemon.com...
 Because what *YOU* the compiler vendor think is an "acceptable" threshold
 for how simple it should be, may be too low, or too high.  In my
experience
 it's too low; what I think is simple (say, an empty constructor or one
that
 initializes a 4x4 matrix with identity) may be "too much" for the poor
 compiler to allow to be inlined.  A few critical sections of code may need
 inlining even though they exceed that arbitrary limit.  Sometimes,
 especially with later optimization and constant folding, sometimes the
 entire function just optimizes away, but the compiler wouldn't know that
 until it tried.  I would err on the side of inlining too much, since RAM
is
 cheap and code caches are too small anyway.

 Maybe if there is an inlining switch it could have a range setting, from
low
 to high and in between.  However even "high" may not be enough in some
 situations.  So some quanta may be necessary.

 Sean
I was envisioning a "speed" or "space" optimization setting. The "speed" one would inline larger functions, the "space" would only inline if the result was expected to reduce eventual code size. I understand that this 2 position switch isn't optimal.
Jun 15 2002
prev sibling parent reply "Richard Krehbiel" <rich kastle.com> writes:
"Walter" <walter digitalmars.com> wrote in message
news:aeb9eg$1c72$2 digitaldaemon.com...
 "Juan Carlos Arevalo Baeza" <jcab roningames.com> wrote in message
 news:ae8g2c$1c7h$1 digitaldaemon.com...
    I've pushed for some thing like this before: allowing the programmer
to
 specify that an inline function MUST be inlined instead of letting the
 optimizer choose. For constant expressions, that would be a really nice
 thing, too.
Time for a philosophical question - why do you need to control whether a function is actually inlined or not? Isn't that like using the 'register' keyword in C, and just as obsolete? As long as the semantics are
maintained,
 inlining should be at the compiler's discretion, and how well it is done
 should be a quality-of-implementation issue.

 I see the inlining issue as an overall speed/space tradeoff, something
that
 you'd specify with a global switch on the compiler.

 (For debug compiles, it's nice to not inline anything, so that breakpoints
 on function calls work.)
If you *really* believe this, then your compiler should not impose any constraints on structures which require constant expressions, like case labels and static initializers. These things should allow arbitrary expressions, involving variables and function calls, so long as they are computable at compile time. -- Richard Krehbiel, Arlington, VA, USA rich kastle.com (work) or krehbiel3 comcast.net (personal)
Jun 14 2002
parent "Walter" <walter digitalmars.com> writes:
 If you *really* believe this, then your compiler should not impose any
 constraints on structures which require constant expressions, like case
 labels and static initializers.  These things should allow arbitrary
 expressions, involving variables and function calls, so long as they are
 computable at compile time.
Yes, you are right.
Jun 14 2002
prev sibling next sibling parent "Martin M. Pedersen" <mmp www.moeller-pedersen.dk> writes:
 Perhaps this can be improved so that functions that simply do a constant
 calculation get folded in the semantic phase rather than the optimization
 phase.
Perhaps it could be done, but it should be noted that it could have implications for a cross-platform compiler, because it cannot rely on its native types.
Jun 12 2002
prev sibling parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:ae8et9$1b1b$1 digitaldaemon.com...

 Inline functions are implemented. As such, the stuff will get folded if
the
 optimizer is running. Unfortunately, the earlier passes don't know it can
be
 folded, so for example case values will produce an error message about not
 being constant.

 Perhaps this can be improved so that functions that simply do a constant
 calculation get folded in the semantic phase rather than the optimization
 phase. This will avoid needing to change the language specification.
Another problem is, it heavily depends on the compiler capable of determining which functions perform constant calculations and which are not. So, you risk of writing the code which will compiles with DMD, but fails with GCC D (note: this was just an example! =)). In this thread, there was a suggestion of some form of macros support: a function with a body consisting of a single expression, defined using special syntax (so it's easy for any compiler writer to handle this case). It could serve both as a macro, and as a forced-inline function (since these should always be possible to inline)...
Jun 14 2002
parent reply "Walter" <walter digitalmars.com> writes:
"Pavel Minayev" <evilone omen.ru> wrote in message
news:aec67k$28u1$1 digitaldaemon.com...
 Another problem is, it heavily depends on the compiler capable of
 determining which functions perform constant calculations and
 which are not. So, you risk of writing the code which will compiles
 with DMD, but fails with GCC D (note: this was just an example! =)).
This can be consistent given a subset of the only thing a function references are its parameters and constants.
 In this thread, there was a suggestion of some form of macros support:
 a function with a body consisting of a single expression, defined using
 special syntax (so it's easy for any compiler writer to handle this
 case). It could serve both as a macro, and as a forced-inline function
 (since these should always be possible to inline)...
I think it's a crutch to do a special syntax where the regular function syntax will serve with a little more effort at the compiler implementation.
Jun 14 2002
parent reply "Pavel Minayev" <evilone omen.ru> writes:
"Walter" <walter digitalmars.com> wrote in message
news:aee57a$1757$1 digitaldaemon.com...

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:aec67k$28u1$1 digitaldaemon.com...
 Another problem is, it heavily depends on the compiler capable of
 determining which functions perform constant calculations and
 which are not. So, you risk of writing the code which will compiles
 with DMD, but fails with GCC D (note: this was just an example! =)).
This can be consistent given a subset of the only thing a function references are its parameters and constants.
...and other such functions. Yes, you are absolutely right. But in 90% cases, it's just what we need. There are plenty of macros in API headers, like MAKEINTRESOURCE, which, on one hand, must be function (or at least look like a function), but, on other hand, is used in constant expressions.
 In this thread, there was a suggestion of some form of macros support:
 a function with a body consisting of a single expression, defined using
 special syntax (so it's easy for any compiler writer to handle this
 case). It could serve both as a macro, and as a forced-inline function
 (since these should always be possible to inline)...
I think it's a crutch to do a special syntax where the regular function syntax will serve with a little more effort at the compiler
implementation. The problem is, it is not predictable, unless you define the rules which strictly describe whether the function is "const" or not, and require _all_ implementations to support inlining to this degree...
Jun 14 2002
parent reply "Sean L. Palmer" <seanpalmer earthlink.net> writes:
I don't mind using special syntax to indicate to the compiler that something
is very simple and should be treated as a "optimal" special case.  Such as a
function that's completely compile-time deterministic (doesn't reference any
external variables except constant ones nor any non-deterministic function).
If you want to keep existing function syntax, then what we'd want instead is
some kind of function attribute, am I right?

Sean

"Pavel Minayev" <evilone omen.ru> wrote in message
news:aeeln6$1men$1 digitaldaemon.com...
 "Walter" <walter digitalmars.com> wrote in message
 news:aee57a$1757$1 digitaldaemon.com...

 "Pavel Minayev" <evilone omen.ru> wrote in message
 news:aec67k$28u1$1 digitaldaemon.com...
 Another problem is, it heavily depends on the compiler capable of
 determining which functions perform constant calculations and
 which are not. So, you risk of writing the code which will compiles
 with DMD, but fails with GCC D (note: this was just an example! =)).
This can be consistent given a subset of the only thing a function references are its parameters and constants.
...and other such functions. Yes, you are absolutely right. But in 90% cases, it's just what we need. There are plenty of macros in API headers, like MAKEINTRESOURCE, which, on one hand, must be function (or at least look like a function), but, on other hand, is used in constant
expressions.
 In this thread, there was a suggestion of some form of macros support:
 a function with a body consisting of a single expression, defined
using
 special syntax (so it's easy for any compiler writer to handle this
 case). It could serve both as a macro, and as a forced-inline function
 (since these should always be possible to inline)...
I think it's a crutch to do a special syntax where the regular function syntax will serve with a little more effort at the compiler
implementation. The problem is, it is not predictable, unless you define the rules which strictly describe whether the function is "const" or not, and require
_all_
 implementations to support inlining to this degree...
Jun 15 2002
parent Pavel Minayev <evilone omen.ru> writes:
 I don't mind using special syntax to indicate to the compiler that something
 is very simple and should be treated as a "optimal" special case.  Such as a
 function that's completely compile-time deterministic (doesn't reference any
 external variables except constant ones nor any non-deterministic function).
 If you want to keep existing function syntax, then what we'd want instead is
 some kind of function attribute, am I right?
Yes, right - the const attribute (since it cannot be applied to types anyhow). I just like that new syntax, makes it quite clear to the user that he's looking at a macro rather than some sort of function...
Jun 15 2002
prev sibling parent reply "Alix Pexton" <Alix seven-point-star.co.uk> writes:
Reading the rest of this thread has given me an absurd idea...

Could the D compiler have a switch which turned on performance analysis
code within a build, say -analyze.
Then when the program is run, call to each function, (or at least those
marked inline or whatever) is logged.
Then The D compiler can be run with a second switch (-inline perhaps) that
reads the performance log and uses it to decide which functions are used
enough that inlining them might give a performance enhancement...

Two switches are better that one, because then you could performance
monitor an inlined function and refine the inlining model...

Did that make sense???

Probably not, and it sounds like hard work to me...

Alix Pexton...
Jun 15 2002
parent reply "Walter" <walter digitalmars.com> writes:
At least the first part is done by the Digital Mars trace dynamic profiler!

"Alix Pexton" <Alix seven-point-star.co.uk> wrote in message
news:01c21477$aff61900$77087ad5 jpswm...
 Reading the rest of this thread has given me an absurd idea...

 Could the D compiler have a switch which turned on performance analysis
 code within a build, say -analyze.
 Then when the program is run, call to each function, (or at least those
 marked inline or whatever) is logged.
 Then The D compiler can be run with a second switch (-inline perhaps) that
 reads the performance log and uses it to decide which functions are used
 enough that inlining them might give a performance enhancement...

 Two switches are better that one, because then you could performance
 monitor an inlined function and refine the inlining model...

 Did that make sense???

 Probably not, and it sounds like hard work to me...

 Alix Pexton...
Jun 15 2002
parent reply "Alix Pexton" <Alix seven-point-star.co.uk> writes:
I notice that your not ruling out, implementing the second part <g>...

Walter <walter digitalmars.com> wrote in article
<aeg2in$df2$2 digitaldaemon.com>...
 At least the first part is done by the Digital Mars trace dynamic
profiler!
 
 Could the D compiler have a switch which turned on performance analysis
 code within a build, say -analyze.
 Then when the program is run, call to each function, (or at least those
 marked inline or whatever) is logged.
 Then The D compiler can be run with a second switch (-inline perhaps)
that
 reads the performance log and uses it to decide which functions are
used
 enough that inlining them might give a performance enhancement...

 Two switches are better that one, because then you could performance
 monitor an inlined function and refine the inlining model...
Jun 17 2002
parent "Walter" <walter digitalmars.com> writes:
Never say never!

"Alix Pexton" <Alix seven-point-star.co.uk> wrote in message
news:01c215eb$42a4f540$f2517ad5 jpswm...
 I notice that your not ruling out, implementing the second part <g>...

 Walter <walter digitalmars.com> wrote in article
 <aeg2in$df2$2 digitaldaemon.com>...
 At least the first part is done by the Digital Mars trace dynamic
profiler!
 Could the D compiler have a switch which turned on performance
analysis
 code within a build, say -analyze.
 Then when the program is run, call to each function, (or at least
those
 marked inline or whatever) is logged.
 Then The D compiler can be run with a second switch (-inline perhaps)
that
 reads the performance log and uses it to decide which functions are
used
 enough that inlining them might give a performance enhancement...

 Two switches are better that one, because then you could performance
 monitor an inlined function and refine the inlining model...
Jun 18 2002