Thoughts about "Compile-time types" talk

H. S. Teoh hsteoh at quickfur.ath.cx
Wed May 15 19:28:21 UTC 2019


On Wed, May 15, 2019 at 06:57:02PM +0000, Alex via Digitalmars-d wrote:
[...]
> D already does all this but the language clearly was not designed with
> the intention to unify them.
> 
> For example,
> 
> int x = 3;
> if (x == 3) fart;
> 
> Hear the compiler should be able to reason that x = 3 and to optimize
> it all to
> 
> fart;
> 
> 
> This requires flow analysis but if everything is 100% analyzed
> correctly the compiler could in theory determine if any statement is
> reducible and cascade everything if necessary until all that's left
> are things that are not reducible.
> 
> It's pretty simple in theory but probably very difficult to modify a
> pre-existing compiler that was designed without it to use it.

Good news: this is not just theory, and you don't have to modify any
compiler to achieve this.  Just compile the above code with LDC (ldc2
-O3) and look at the disassembly.  :-)

In fact, the LDC optimizer is capable of far more than you might think.
I've seen it optimize an entire benchmark, complete with functions,
user-defined types, etc., into a single return instruction because it
determined that the program's output does not depend on any of it.

Writing the output into a file (cause a visible effect to prevent the
optimizer from eliding the entire program) doesn't always help either,
because the optimizer would then run the entire program at compile-time
then emit the equivalent of:

	enum answer = 123;
	outputfile.writeln(answer);

The only way to get an accurate benchmark is to make it do non-trivial
work -- non-trivial meaning every operation the program does contributes
to its output, and said operations cannot be (easily) simplified into a
precomputed result.  The easiest way to do this is for the program to
read some input that can only be known at runtime, then perform the
calculation on this input.  (Of course, there's a certain complexity
limit to LDC's aggressive optimizer; I don't think it'd optimize away an
NP-complete problem with fixed input at compile-time, for example.  But
it's much easier to read an integer at runtime than to implement a SAT
solver just so LDC won't optimize it all away at compile-time. :-D  Well
actually, I'm sure the LDC optimizer will give up long before you give
it an NP-complete problem, but in theory it *could* just run the entire
program at compile-time if all inputs are already known.)

The DMD optimizer, by comparison, is a sore loser in this game. That's
why these days I don't even bother considering it where performance is
concerned.


But the other point to all this, is that while LDC *can* do all of this
at compile-time, meaning the LLVM backend can do all of this, for other
languages like C and C++ too, what it *cannot* do without language
support is to use the result of such a computation to influence program
structure.  That's where D's CTFE + AST manipulation becomes such a
powerful tool.  And that's where further unification of RT/CT concepts
in the language will give us an even more powerfully-expressive
language.


T

-- 
Computers aren't intelligent; they only think they are.


More information about the Digitalmars-d mailing list