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...