Compile-time optimization
JS
js.mdnq at gmail.com
Tue Jul 23 16:35:23 PDT 2013
On Tuesday, 23 July 2013 at 22:38:35 UTC, Yota wrote:
> On Tuesday, 23 July 2013 at 20:11:21 UTC, JS wrote:
>> Your code doesn't exactly do what I wanted but probably
>> because I wasn't clear... I think it is modifiable and solves
>> the problem I was having(again, assuming your code is correct).
>>
>> Note though that something like
>>
>> string x = "asd"
>> join(x,...); // x is compile time known and should be joined
>> at compile time. Not sure if D is smart enough to get this one?
>>
>> When I get some time later I'll check your code out, what I
>> want to do is get something like
>>
>> string x = join(a, b, "a", "b"); to produce the same code as
>> string x = a~b~"ab";
>>
>> (no looping using for each except for string arrays)
>>
>> Thanks!
>
>
> Don't forget that tuples can store more than just types! See
> this for instance.
>
> import std.stdio;
>
> typeof(Xs[0]) sum(Xs...)()
> {
> pragma(msg, Xs); // tuple(1, 2, 3)
> typeof(Xs[0]) y;
> foreach(x; Xs) y ~= x;
> return y;
> }
>
> int main() {
> auto n = sum!(1, 2, 3);
> enum m = sum!(1, 2, 3);
>
> pragma(msg, typeof(n)); // int
> writeln(n); // 6
> writeln(m); // 6
>
> return 0;
> }
>
> Works great. When I comment out the 'sum!("1", "2", "3")' and
> replace it with a literal '6', the compiled EXE is byte for
> byte exactly the same. You can exchange the '+=' for '~=' and
> it will concatenate strings instead. Of course, now all
> arguments MUST be known at compile time, but that's no surprise.
>
> PS: OK, just noticed that you were hoping to mix run time and
> compile time arguments. Oops....
> Oh well, posting anyway because I think it's neat. lol
>
> As for a~"B"~"C" compiling into a~"BC", I think we just need to
> work on constant folding in the compiler. (If it doesn't
> already do this anyway.)
Well, it's not that simple. Constant folding is easy when it is
obvious to the compiler... but something buried in foreach loop
that uses runtime and compile time objects is not obvious.
My three points out of the post is:
1. D needs some way to make doing this stuff easier.
2. It needs to be done! ;)
3. Goto 1.
I didn't realize D could even potentially do it, and still not
sure if it can(have to check out T's post again and work with the
code).
I think there is a lot of potential power behind such techniques
with regard to optimization.
Suppose you are writing a matrix library. Wouldn't it be nice to
have certain matrix computations that can be done at compile time
actually done? (I suppose what I'm trying to do is extend the
compiler's "constant folding" to be able to deal with much more
complex cases).
Another way to potentially do it, I think, is for the compiler to
automatically expand ctfe functions and replace runtime entities
with "placeholder" code which is then expanded at runtime.
e.g., for a simple join
join(T...)(T t)
{
string s;
foreach(tt; t)
s ~= tt;
return s;
}
the compiler can unroll the loop to get
s ~= t[0]~t[1]~t[2]~...;
replace the compile time entities, e.g., suppose t[1] and t[3]
are known at compile time at the invocation, then
s ~= t[0]~"abcd"~t[2]~"asdf";
then this code could be used inline for the join call instead of
the actual code. The key here is there is no dependence on the
for loop. If all arguments are compile-time evaluable, then s
could be just a reference lookup to a static string. If it can't
be done, then no big deal, it is optimized as far as it can go.
Only if all arguments passed are runtime entities will the exact
code be used.
This seems like it would take a pretty smart compiler and
possibly it would have issues in some many cases. I personally
don't mind writing the code itself but it seems pretty complex,
and having no way to debug the code generation easily(AFAIK)
makes it difficult to do.
Possibly using version(ctfe) can help... I'll work on it when I
get a chance...
More information about the Digitalmars-d
mailing list