www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.announce - template functions, a special case of constant folding?

reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the 
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

the compiler shall do the computation at compile time and convert it to:
# x = 13;
is there a particular reason for not doing that?

What I'm trying to say is, why do we need templates to do compile-time 
computation of square roots? (as shown on 
http://www.digitalmars.com/d/templates-revisited.html)

Why not, instead of calling the templated sqrt
#    x = sqrt!(2);
you just call the regular sqrt
#    x = sqrt(2);
and the compiler, if smart enough, should do the computation at compile 
time?

If it's too hard to make the compiler smart enough, then maybe we can 
add a keyword to hint to the compiler that if all arguments to this 
function are constants then it can be "folded"!
After all, that's essentially what the "template" keyword is doing! 
(kinda, not really though, I know).

# fold int add( int x, int y ) { return x + y; }
vs.
# template add( int x, int y ) { const add = x + y; }

The "fold" version of the function can be reused for non-constant 
arguments. Where as the templated version can't. (although I'm not 
entirely sure about that).
Mar 23 2006
next sibling parent reply Derek Parnell <derek psych.ward> writes:
On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

 Given the following expression:
 #x = 10 * 5 + y;
 the compiler will compute 10 * 5 at compile-time and convert the 
 expression into
 #x = 50 + y;
 
 I think that's called constant-folding, am I right?
 
 Why can't this be extended such that for the following function:
 # int add( int x, int y ) { return x + y; }
 
 if it's called with constant arguments:
 # x = add( 10, 3 );
 

You can almost do this with mixins, except that mixins only allow one to mixin a complete statement and not just an expression. What would be useful is to allow mixins (or some other similar thing) to generate expressions at compile time and not just statements. Something like ... template add(b,c) { b + c; } int main() { int q; q = mixin add!(10,3); return q; } Which would generate int main() { int q; q = 10 + 3; return q; } Which the compiler would constant-fold as normal. But this is starting to look too much like text macros which Walter is very concerned not to have. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocracy!" 24/03/2006 10:51:16 AM
Mar 23 2006
next sibling parent James Dunne <james.jdunne gmail.com> writes:
Derek Parnell wrote:
 On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:
 
 
Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the 
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to mixin a complete statement and not just an expression. What would be useful is to allow mixins (or some other similar thing) to generate expressions at compile time and not just statements. Something like ... template add(b,c) { b + c; } int main() { int q; q = mixin add!(10,3); return q; } Which would generate int main() { int q; q = 10 + 3; return q; } Which the compiler would constant-fold as normal. But this is starting to look too much like text macros which Walter is very concerned not to have.

Why not reuse alias? Aliased expressions. -- Regards, James Dunne
Mar 23 2006
prev sibling parent reply Hasan Aljudy <hasan.aljudy gmail.com> writes:
Derek Parnell wrote:
 On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:
 
 
Given the following expression:
#x = 10 * 5 + y;
the compiler will compute 10 * 5 at compile-time and convert the 
expression into
#x = 50 + y;

I think that's called constant-folding, am I right?

Why can't this be extended such that for the following function:
# int add( int x, int y ) { return x + y; }

if it's called with constant arguments:
# x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to mixin a complete statement and not just an expression. What would be useful is to allow mixins (or some other similar thing) to generate expressions at compile time and not just statements. Something like ... template add(b,c) { b + c; } int main() { int q; q = mixin add!(10,3); return q; } Which would generate int main() { int q; q = 10 + 3; return q; } Which the compiler would constant-fold as normal. But this is starting to look too much like text macros which Walter is very concerned not to have.

but you're still using templates. which completely defies my point!
Mar 24 2006
parent reply =?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= <jmjmak utu.fi.invalid> writes:
Hasan Aljudy wrote:
 Derek Parnell wrote:
 On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:


 Given the following expression:
 #x = 10 * 5 + y;
 the compiler will compute 10 * 5 at compile-time and convert the
 expression into
 #x = 50 + y;

 I think that's called constant-folding, am I right?

 Why can't this be extended such that for the following function:
 # int add( int x, int y ) { return x + y; }

 if it's called with constant arguments:
 # x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to mixin a complete statement and not just an expression. What would be useful is to allow mixins (or some other similar thing) to generate expressions at compile time and not just statements. Something like ... template add(b,c) { b + c; } int main() { int q; q = mixin add!(10,3); return q; } Which would generate int main() { int q; q = 10 + 3; return q; } Which the compiler would constant-fold as normal. But this is starting to look too much like text macros which Walter is very concerned not to have.

but you're still using templates. which completely defies my point!

Doing this kind of compiler optimization is very expensive (adds compiling time & optimizer complexity and thus more bugs). If you already know that the function should be folded / inlined when you're writing the code, it's a natural way to explicitly say this with templates. I think the compiler already does some tricks when -inline is used. I think new M$ compilers convert stuff like this: int a = 5, b = 2; for (int i=0; i<3; i++) a *= b; int get(int c) { return c+2; } a = b = get(a); into: int a = 42, b = 42; but IMHO it's a sign of a bad coder not to optimize code on the higher levels. It's extremely simple to "hint" to compiler by using templates and lift the burden of implementation to the metaprogramming engine. -- Jari-Matti
Mar 24 2006
parent Kevin Bealer <Kevin_member pathlink.com> writes:
In article <e00jv5$19h2$1 digitaldaemon.com>,
=?ISO-8859-1?Q?Jari-Matti_M=E4kel=E4?= says...
Hasan Aljudy wrote:
 Derek Parnell wrote:
 On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:


 Given the following expression:
 #x = 10 * 5 + y;
 the compiler will compute 10 * 5 at compile-time and convert the
 expression into
 #x = 50 + y;

 I think that's called constant-folding, am I right?

 Why can't this be extended such that for the following function:
 # int add( int x, int y ) { return x + y; }

 if it's called with constant arguments:
 # x = add( 10, 3 );

You can almost do this with mixins, except that mixins only allow one to mixin a complete statement and not just an expression. What would be useful is to allow mixins (or some other similar thing) to generate expressions at compile time and not just statements. Something like ... template add(b,c) { b + c; } int main() { int q; q = mixin add!(10,3); return q; } Which would generate int main() { int q; q = 10 + 3; return q; } Which the compiler would constant-fold as normal. But this is starting to look too much like text macros which Walter is very concerned not to have.

but you're still using templates. which completely defies my point!

Doing this kind of compiler optimization is very expensive (adds compiling time & optimizer complexity and thus more bugs). If you already know that the function should be folded / inlined when you're writing the code, it's a natural way to explicitly say this with templates. I think the compiler already does some tricks when -inline is used. I think new M$ compilers convert stuff like this: int a = 5, b = 2; for (int i=0; i<3; i++) a *= b; int get(int c) { return c+2; } a = b = get(a); into: int a = 42, b = 42; but IMHO it's a sign of a bad coder not to optimize code on the higher levels. It's extremely simple to "hint" to compiler by using templates and lift the burden of implementation to the metaprogramming engine. -- Jari-Matti

An idiom that I find helpful is static variables. : int[] BuildLookupTable(...) : { : // computes some complex table or : // other data set. : } : : int do_lookup(int i) : { : static int[] s = BuildLookupTable(...); : return s[i]; : } The static int[] gets computed once and stored the first time the code runs, after this the compiler just checks that it is assigned. I use this in C++. I'm not sure if this works in D, if not you can still do this: : static int[] s; : if (s.length == 0) { : s = BuildLookupTable(); : } Sometimes a data structure computation is complex and has a lot of data, but the code to compute it is compact. This lets you build that code on demand at the point of use, and only if the program needs it. Kevin
Mar 24 2006
prev sibling parent =?iso-8859-1?q?Knud_S=F8rensen?= <12tkvvb02 sneakemail.com> writes:
What if the compiler automatic inlines functions with 
constant arguments.

Then the optimiser could do some real work on it !

Just a trough.

Knud

On Thu, 23 Mar 2006 16:34:07 -0700, Hasan Aljudy wrote:

 Given the following expression:
 #x = 10 * 5 + y;
 the compiler will compute 10 * 5 at compile-time and convert the 
 expression into
 #x = 50 + y;
 
 I think that's called constant-folding, am I right?
 
 Why can't this be extended such that for the following function:
 # int add( int x, int y ) { return x + y; }
 
 if it's called with constant arguments:
 # x = add( 10, 3 );
 
 the compiler shall do the computation at compile time and convert it to:
 # x = 13;
 is there a particular reason for not doing that?
 
 What I'm trying to say is, why do we need templates to do compile-time 
 computation of square roots? (as shown on 
 http://www.digitalmars.com/d/templates-revisited.html)
 
 Why not, instead of calling the templated sqrt
 #    x = sqrt!(2);
 you just call the regular sqrt
 #    x = sqrt(2);
 and the compiler, if smart enough, should do the computation at compile 
 time?
 
 If it's too hard to make the compiler smart enough, then maybe we can 
 add a keyword to hint to the compiler that if all arguments to this 
 function are constants then it can be "folded"!
 After all, that's essentially what the "template" keyword is doing! 
 (kinda, not really though, I know).
 
 # fold int add( int x, int y ) { return x + y; }
 vs.
 # template add( int x, int y ) { const add = x + y; }
 
 The "fold" version of the function can be reused for non-constant 
 arguments. Where as the templated version can't. (although I'm not 
 entirely sure about that).

Mar 24 2006