In my spare time (not much), I am a compiler creator or maintainer,
and so I will try to answer some of your questions ... see below


Am 13.11.2021 um 17:10 schrieb Phil Smith III:
Unoptimised code typically has redundant instructions.
For example, a store instruction to finish an assignment
operation might be followed by a load from the same place
in a following statement.
That I could believe--the unoptimized code is dealing with the statements as
discrete code snippets. But this was code generated for a single, simple
statement.

Is this bad? You would not notice the time to execute
the redundant LR instruction.
If that statement were true, there would be no need for optimization. This
is code that will run billions of times, often millions in a single run;
yes, we will feel it. Again, my point (well, one of them) was that this is
really pretty grim code: I'd downmark a student who produced it.

If you want better code, specify optimisation.
Corollary: the compiler generates...deliberately poor code without
optimization? Again, why?

Note that I had the same ARCH() value on both versions. So why wouldn't the
original code use the same fancy new instruction?

I would have assumed that optimization meant considering how statements
interact, not generating lousy code for each on purpose.


Compilers often generate (unoptimized) code on the fly, when doing the parsing of the source (or an intermediate tree-representation of the code. The unoptimized code "drops out" of the parsing process, when the compiler pass parses through the source or the tree-representation.

If you take this code, this will be OPT-0 code. It will work, but it will probably have all sorts of obvious optimization possibilities, even in one statement, for example ST - L sequences
involving the same address etc.

Given this simple scheme, you have several possibilities where optimiziation can be done:

- before this code generation (when creating the tree-representation from the source code), for example: eliminating common sub-expression or moving something out of loops etc.

- after this code generation (elimination of ST - L sequences like above or doing other
optimization when looking at the generated code)

If you control these optimization steps via compiler switches, you can (if you want) allow the compiler user to specify "optimization levels" ... which have a tradeoff between
compilation time and quality of the generated code.

My compiler is New Stanford Pascal (http://bernd-oppolzer.de/job9.htm);
it generates P-Code directly when parsing the Pascal source (no tree representation); there is not much optimization in this step, other than that the P-Code is adjusted carefully to the needs of the Pascal language. The second step is the translation of the P-Code to 370 machine code, and there is some effort done to reduce the generation of machine instructions which are not needed (for example: leave certain information in registers as long as possible and do a reload only, when absolutely necessary).
Although the compiler is some 40 years old, it does (IMO) a very good job.

HTH, kind regards

Bernd

But I am not a compiler creator by any stretch of the imagination. Maybe I'm
missing some design principle here, which is why I asked in the first
place...

Reply via email to