Proposals

Lynn H. Maxson lmaxson@pacbell.net
Wed, 12 Jul 2000 21:05:26 -0700 (PDT)


Billy wrote:
" The problem is that if you pay attention only to 
the <operand><operand><operator> you're
working on now, you'll miss the fact that a 
previous <operand><operand><operator> used a 
subsequence that you could borrow economically if 
you rearranged the program a bit."

No, no, no.  What I tell you three times is 
true.<g>  We have already conceded that multiple 
levels of optimization occur including handling of 
this example.  That's what occurs today.  That's 
what will occur tomorrow.  I am not changing a 
thing.

Look IBM's VisualAge compilers regardless of source 
language (C, C++, JAVA, COBOL, PL/I) translate the 
source into a "common" intermediary symbolic 
(machine-independent) language which is then feed 
into an optimizing code generator for a target 
system.  The same language (source), multiple 
target systems.

In the system I propose you have a hierarchy of 
specifications.  Within that hierarchy the two 
lowest levels contain machine-dependent 
specifications (the machine architectures for RISC 
and CISC systems).  At the level immediately above 
these two, the third level, begins the remaining 
hierarchical levels of machine-independent 
specifications.  

This third level contains the raw material of all 
higher level assemblies.  This raw material 
consists of control structures (sequence, decision, 
iteration) and all the primitive operators.  Just 
as in any manufacturing system all the higher level 
assemblies must eventually decompose into a 
collecton of raw material.

There is no need to use the principal of logical 
equivalence with any of the machine-independent 
specifications (the third level on up) because any 
lower level is explicitly invoked by a higher, i.e. 
the organization of a set of machine-independent 
specifications is pre-determined, pre-set, and 
pre-known.  No search or discovery process is 
necessary.  None is invoked.

The only time it gets invoked, the only time 
logical equivalence comes into play, is making the 
transition from the third level, which is 
machine-independent, to an equivalent form in 
either of the machine architectures of the two 
lower (machine-dependent) levels.  This is code 
generation.

For any given machine architecture we can have a 
set of specifications governing the translation of 
the input stream of third level specifications.  We 
can do optimization iteratively as it is done 
routinely now.  All this is specifiable.

Take a look at LISP, at FORTH, and what you see is 
a decomposition of an expression using either 
prefix, infix, or postfix operator notation.  LISP 
uses prefix operator notation 
(<operator><operand><operand>) which can include 
sub-expressions (lists) in any of the three.  FORTH 
does the same thing only using postfix operator 
notation.

Whenever I have applied a set of global 
optimizations I still end up with a stream 
generically represented by this operator/operand 
triad.  This represents the "basic" executable 
expressions.  Given that I have complete knowledge 
of the attributes of each triad member and a set of 
rules governing every possible combination (I know 
this because we know and use it today), then I have 
no problem finding all the logically equivalent 
executable forms.  For any given triad they are a 
reasonably finite number, in many instances no more 
than one.  I have no problem using another set of 
rules to determine from a list of two or more one 
of which whose performance is not exceeded by any 
other.

Now I have a stream of now I have a stream of 
logically equivalent machine instructions against 
which I can now apply another set of specifications 
regarding their optimization in the machine 
architecture.  The point is that to do all of this 
I only need to use a specification language.  I can 
specify rules.  I can specify hardware.  In fact I 
can specify multiple target hardware systems as 
part of the same run, generating executable code 
for any number of different platforms.  No 
silly-willy, one-at-a-time code generations.<g>

If you don't like my specification language, use 
another logically equivalent one.  I'm not partial 
to it except as an example of a "universal" 
specification language.  As part of its 
universality is the ability to specify any other 
computer language.  If you use its multi-platform 
code generation capability, then you can offer your 
language on any of the other platforms, having only 
written (specified) it once.

Maybe "all possible logically equivalent programs" 
was misleading.  I don't have to generate it at the 
program level.  In fact such generation does not 
occur in practice.  The code generation always 
occurs at a lower level.  It's just that when it is 
done you have an executable program.<g>

"No, you can't precompute all possible encodings of 
all possible expressions."

No, no, no.  I don't precompute them any more than 
they are precomputed now.  I don't know how many 
different kinds of operators exist in your computer 
languages, but in mine they seem limited to 
boolean, logical, arithmetic, and string.  I'm very 
willing to show you a language-independent means of 
specifying all the possibilities and the rules 
governing their use.  I hate to use PL/I again, but 
it does offer more than any other programming 
language because it uses "practical" not "pure" 
strong typing.

Again you are thinking of a far greater problem 
than I am proposing.

"So I'm guessing that your talk about "exhaustive 
search" was talking about something else, then."

No, no, no.  I'm talking about the rule-based 
exhaustive search (true/false) proof method of 
logic programming.  That the same rules of logic 
can determine that certain paths need not be 
travelled does not change the results, only the 
time to produce them.  I have over and over (and 
over) again explained to you the finite exhaustive 
search that exists for any <oper><opnd><opnd> triad 
regardless of machine architectures or the number 
of them involved.  You have chosen to include 
enumerated logical equivalent forms that my rules 
would not allow.  You are free to do so.  My 
exhaustive search is limited to that permitted by 
the rules, which in turn are derived from 
heuristics.

"I'm not sure what an "iteration" is, but there's 
one thing I'm sure of: it has nothing to do with 
optimization."

Yes, yes, yes.  And no it doesn't.  Neither does an 
exhaustive search.  The optimization occurs after 
the search (or a search instance) is completed.

"I have a better suggestion, though: why not use 
the restrictions and heuristics the compiler 
researchers have been working on all these years to 
the problem?"

Well, well, well.  Here I thought that is what I 
was doing with my rule-based system, except that I 
want to take only the "best" of what they have 
produced.

"Perhaps this is the really important point I'm 
completely missing.  Even if it's not important, 
I'm completely missing it.  You keep bringing up 
the "rules in use in PL/I" as though they had 
anything to do with generating optimal code.  I 
don't understand that at all."

And it is well that you shouldn't as the PL/I rules 
deal with expression evaluation only.  You have to 
have something to optimize, in this instance an 
expression.  Before you can optimize it you must 
produce it.  Therein lies the purpose of the PL/I 
rules.

"I'm guessing you're talking about Baker's "The 
FORTH Shall be First" paper, which was an article 
in an ACM journal.  If so, you misread it."

While it would not be the first time I misread 
something, in this instance it was a different 
paper: Bawden's "Implementing Distributed Systems 
Using Linear Naming".  Having not yet gotten 
through all 156 pages, I will hold off any 
judgements on misreading.<g>

"One, it IS a restriction to permit the optimised 
code to contain only types which were present in 
the programmer's code."

I guess it depends on whose wishes the program is 
supposed to reflect.  You apparently have a problem 
with stupid or careless programmers.  I follow the 
general PL/I philosophy that the programmer is 
"king" and that what you do is the best job 
possible within his restrictions.  This may not 
result in "the" optimal solution, only in an 
optimized instance.  If you specify that the 
interactive tool make clear to the programmer the 
implications of his type choices, then the 
programmer can choose to remain or stay.  I don't 
think tools (or the authors of such tools) should 
be snickering or compensating for the programmer.  
The goal is to have better programmers.  You get 
that by incorporating such help in the tools, not 
in a hidden manner (somewhat arrogant in source) 
compensate for his (perceived) "failures".

"That's great, but this is another example where 
being restricted to the written types is a really 
bad idea.  The problem can be solved most 
economically without using any arithmetic at all -- 
the code "'7' emit" I listed is probably (short of 
some other vaguely possible code which didn't need 
to use a literal) the most efficient 
implementation."

We are confused on purposes here.  I want to 
increase the writer's productivity by offering him 
the utmost in assistance.  It is not my job to 
question his motives, but show him the implications 
of his writing.  If he chooses to remain with fixed 
decimal arithmetic instead of binary, I will honor 
that decision.  If he wants to know which in a 
particular instance performs better, I will honor 
that decision.  I, as a tool, am an assistant, not 
a dictator.

We are being buried in software maintenance, either 
changing something that exists or adding something 
new.  This expense in cost and time has continued 
to increase in spite of using "enhanced software 
methodologies", e.g. OO.  Obviously languages are 
not the solution nor are they the problem.  The 
problem (and its solution) lies in their 
implementation, in the tools.  If you had the 
"right" tool, the "right" kind of implementation, 
with any language capable of expressing the range 
of interest, software technology could maintain 
pace with hardware.

Our current tool set sucks.  I don't care how much 
better this tool set is better than that.  If 
neither allow software technology to maintain pace 
with hardware, it sucks.  It's just that simple.

You have to solve the problem.  Dealing with 
esoteric and exotic language features doesn't cut 
it.  Whether slots or sluts (a higher level slot) 
unless it addresses, unless it is part of the 
solution, it remains mired in the problem.  

LISP is one of the oldest programming languages.  
It has sprouted probably hundreds of dialects.  Yet 
no LISP or LISP-like development/maintenance 
environment functions to maintain the pace of 
software with hardware technology.  This is not an 
anti-LISP statement.  It is a statement of fact.  
It is a statement of fact about every other 
software language and methodlogy attempted.

Therefore the fault cannot lie with LISP or any 
other language.  It can only lie with their 
implementations which govern our use of them.  

While I cannot speak to the current state of 
affairs, initially LISP permeated all of AI 
systems, logic programming.  It was used to create 
the first Prolog compilers.  Why?  Because in an 
exhaustive true/false proof process may result in 
0, 1, or more true instances.  That my friend is a 
list, a native data type (an aggregate) in LISP.  
It permits rule-based operations on lists.

The fact is that this ability lies at the heart of 
logic programming.  It is intrinsic in any 
specification language like Prolog, Trilogy, or in 
my proposed SL/I.  Again the problem does not lie 
with the language used, but with its 
implementation.

I don't want to discuss philosophical differences 
regarding whether we follow the programmer's 
dictates or adopt a do-gooder attitude about 
knowing what's best for him.  You are entitled to 
have either in your implementation of choice.  My 
goal is to enable you to have that choice, not 
dictate to you what choices you have.

I want to bring down software costs (and time) to a 
minuscule fraction of their current burden.  In so 
doing provide for the first time in history the 
ability of software technology to outpace hardware.  
I want to solve a real problem that has continued 
to get worse over the last forty-plus years.  I 
cannot solve it with a language, but I must have 
one which allows me to express the solution.  I 
then need an implementation of the solution.  In my 
proposed methodology this is a single interactive 
tool I have dubbed "The Developer's Assistant".

If you in your infinite wisdom want to change it to 
"The Developer's Better Half", I want to enable you 
to do so.  I do not know what is best.  Therefore I 
prefer to enable, not impede others who might be on 
the right path.

Now a fourth generation, "universal" specification 
language includes all the capabilities of all other 
languages of all other generations.  That comes 
directly from logic and the fact that all computer 
systems and software are 100% logic based.  You may 
regard it as a restriction.  I won't argue it.  To 
me it is simply a fact that presents an opportunity 
to solve a problem besetting the entire IT 
profession.

"I'm confused.  I thought you just said that the 
optimiser would never change a type the user gave 
it (as when you claimed that the user had given 
decimal numbers); yet you admit that binary numbers 
would be faster.  This is a minor case, but there 
are many far worse ones: if the optimiser can't 
choose its own types and operations, how can you 
claim that the programmer is free???"

The confusion is that the programmer is free to 
behave stupidly and the optimizer is charged with 
doing the best it can with what he has done.  If 
you don't like that form of optimization, then 
change the rules.  I'm just giving you the rules I 
operate under.

I had many an account move from PL/I to COBOL 
because programmers did not use the tool, the 
compiler, intelligently.  Rather than improve the 
programmer the account made the decision to have 
another compiler dictate terms on his freedom.  Not 
my argument.  I use PL/I because out of the box I 
have never had to employ any other language to 
achieve a result.  It remains the most powerful 
programming language available today.

The reason you have an assistant as a tool, one who 
readily presents the results of any decision, is to 
improve "on" what you are doing and "at" your 
ability to do it.  If you have no curiosity, no 
desire to improve, it gives you the best with what 
you have provided.  However, it always stands at 
the "ready".

" The information you're ignoring is the fact that 
programs contain *internal* information, that is
information not visible, and that information is 
"an implementation detail"."

I'm sorry, but no way Jose.  Programs contain only 
written source.  I am proposing a tool in which 
nothing, absolutely nothing, is hidden "ever" from 
the writer.  It is a system of "perfect 
information", i.e. everything that can be known is.

"I'm running out of guesses.  If we agree that both 
satisfy the constraints, then why would you 
eliminate one of them?"

Both satisfy the constraints.  Only one passes the 
rules.  We can agree without the rules agree with 
us.<g>

"Because you explicitly said that there was only a 
couple of ways to express a "+", all of them having 
to do with addition.  Since there are actually an
infinite number of ways to do that, and only a 
"few" of them have to do with addition, it's quite 
obvious that you've done something akin to 
forgetting."

You have this fascination with binary arithmetic 
and using logical operators to perform arithmetic.  
I simply do not.  Whether or not they applied in a 
particular instance in which the operands are fully 
known, e.g. as literal values, would be determined 
by the rules.  If an XOR or OR provided the best 
choice, the rules would use it.  Thus I did not 
forget or ignore it.  To repeat there is not an 
infinite number of ways to process a triad.  I'm 
sorry.  Just not true.

" What does this have to do with the fact that "an 
instruction sequence which satisfies "0 3 + 4 1 * 
+" does also satisfies "3 4 +""?"

Look, what did the writer express?  That's what 
guides the rules for expression evaluation.  No 
attempt is made to produce all possible logically 
equivalent expressions the writer could have 
written.  The object is to do the best with what is 
given.  It may be that optimization produces a 
change, but the guidelines remain the same even for 
the optimized form.

The earlier point is that if "a" can only equal 
zero, i.e. a declare constant, then you can use one 
form of optimization.  If "a" can contain other 
values than zero, then optimization occurs for the 
general case, not the specific.  I'm sorry that's 
so confusing.

"They "limit" you from using a more efficient
representation, even when the more efficient 
representation is logically equivalent."

If you change what a writer has written, e.g. the 
data type, you have imposed a limit in turn.  You 
have made it impossible for a writer to impose his 
style in source.  I do not give a damn frankly 
about a more efficient representation unless 
circumstances demand it.  I do not want systems to 
place demands on or second-guess me.  I do not mind 
if I am notified that a better representation is 
possible.  That's the kind of help I expect from an 
assistant.  I do not mind if an assistant suggests 
a different representation, based upon my approval.

"You've just spent a long time telling me that 
current compiler technology doesn't work.  Now 
you're telling me that it does.  If the current
technology isn't broke, why do you want to spend 
energy fixing it?"

Current compiler technology (and into this you can 
toss in all the other available tools) doesn't 
enable software technology to keep pace with 
hardware.  For my money anything that doesn't do 
that is not "working" regardless of what useful 
results it may produce.  That you can take existing 
software technology tools and reform them in a 
manner that does solve the problem and allow 
software to have a greater pace than hardware is 
why I want to spend energy fixing them.

This compiler or that tool sucks, doesn't work, or 
whatever you want to accuse it of, not because it 
doesn't do what it is supposed to do, but what it 
does do does not solve the cost and time spiral.  I 
have no argument with what it does "right".  I want 
to turnaround what it does "wrong" so that the 
whole thing is right.  It turns out to do that I 
don't need more than one interactive tool, my 
software assistant.

"As far as I can tell, the optimiser you're 
describing now is utterly simple: it takes in PL/I 
code, and emits machine code which impliments 
*exactly* what the programmer requested, same type, 
same sequence of operations, same everything.  I 
wouldn't call that an optimiser; my first attempt 
at my Oberon compiler was far more sophisticated."

I use the PL/I optimizing compiler on OS/2, 
otherwise known as VisualAge PL/I Enterprise 
Edition (the expensive spread).  If I specify a 
decimal operand instead of a binary one, it assumes 
I know what I am doing.  If in the course of 
optimization it rearranges the containing 
expression, so be it.  I have never been arrogant 
as a software author, being always sensitive to the 
needs of my user.  If that meant allowing them to 
make a decision more in keeping with their comfort 
zone than in efficiency of operation, then that's 
what I did.  I know who is paying the bills and who 
is entitled to his choice.  I may inform him that 
better options are available, but the choice is 
his.  In no way do I assert my superior knowledge 
without his expressed consent.  We just happen to 
have a philosophical difference on this point.  I 
in no way want to impose mine on you any more than 
you imposing yours on mine.  The purpose of an 
assistant is to assist.  That says it is 
subservient to its "master".

"If you're going to pretend that optimization is 
possible in multiple steps, you should at least 
admit that the steps aren't discrete: each step 
affects all of the others, including the ones 
before it."

I'm not going to pretend at all.  Optimization can 
be an iterative process, occurring through multiple 
levels until in one pass through the levels no 
change takes place.  If that means starting over at 
the top after every change, then that's the price 
paid.

Optimization is an art form, a specialty within a 
specialty.  I am not going to claim any expertise 
whatsover, neither deny not claim any of the 
possibilities you mention.  What I do know is that 
when executed in software they follow the rules of 
logic.  As such they are specifiable in a 
"universal" specification language.  As long as 
they are specifiable (by someone) and I know from 
experience that they exist, I have no further 
concern (or interest).  If they are not in the 
specification pool, then they do not exist for me.  
I must content myself with what is available.

"This is because you clearly and repeatedly talked 
about how your program would explore all programs 
which are logically equivalent to the 
specifications.  If you're not in fact going to do 
that, then it would be highly proper of you to not 
say you are."

Let's lay this puppy to rest.  If I say it except 
in the context of translating machine-independent 
specifications of the third level into those of 
either the second or first machine-dependent 
specifications, then understand I didn't mean that: 
I only meant this.  It certainly does not occur at 
the program level only at the operator/operand 
level expression level.

"Rice's theorem applies quite well: you claim that 
you can generate a set of possible programs, then 
choose the fastest from among them (and resolve 
ties by choosing the smallest).  Rice's theorem 
points out that program termination is 
uncomputable; there's no computable way of knowing 
whether an arbitrary program will terminate, much 
less how long it takes to do so."

As hopefully we are off the logically equivalent 
program nonsense and into the only area in which 
logical equivalence applies (translation of 
machine-independent specifications into 
machine-dependent ones), then we will cease our 
concerns about upsetting Rice's Theorem.<g>  That 
bothered some people, thinking that I was somehow 
belittling a respected achievement in computer 
science.  Of course, I wasn't doing that at all.  I 
was simply operating in a different arena.

"I never cared one whit about expression 
evaluation.  Optimization is our topic.  Only the 
inputs and outputs of the program matter."

Maybe we have finally hit upon what separates us: 
we had different topics in mind.<g>  I claimed that 
it was possible to produce optimal code equal to or 
better than the best in assembly language 
programmers.  I also claimed (as others in private 
responses have confirmed) that the performance 
difference does not lie in optimization but in 
deliberately imposed "overhead" expense.  We do not 
perform as well because we can't, but because we 
choose not to.  For that reason it remains an 
option to write in a HLL and achieve the best in 
assembly language performance.  The issue is 
comparing apples to apples, same to same.  If you 
do, then assembly language offers no 
advantages--regardless of what your friend does.<g>

"You were, just a few messages ago, talking about 
how the current compilers didn't meet your desires.  
Now they suddenly seem to make you very happy."

Meeting my desires is one thing.  Having the best 
of a bad situation is another.  Until I have 
something better I will content myself with the 
best available: PL/I.  Besides I can be happy in a 
bad situation.  That like anything else is a choice 
we make.