Sujet : Re: Computer architects leaving Intel...
De : david.brown (at) *nospam* hesbynett.no (David Brown)
Groupes : comp.archDate : 01. Sep 2024, 21:07:53
Autres entêtes
Organisation : A noiseless patient Spider
Message-ID : <vb2hir$1ju7q$1@dont-email.me>
References : 1 2 3 4 5 6 7 8 9
User-Agent : Mozilla Thunderbird
On 31/08/2024 21:08, Thomas Koenig wrote:
Anton Ertl <anton@mips.complang.tuwien.ac.at> schrieb:
Of course the fans of compilers that do what nobody means found a
counterargument long ago: They claim that compilers would need psychic
powers to know what you mean.
Of course, different compiler writers have different opinions, but
what you write is very close to a straw man argument.
What compiler writers generlly agree upon is that specifications
matter (either in the language standard or in documented behavior
of the compiler). Howewer, the concept of a specification is
something that you do not appear to understand, and maybe never
will.
An example: I work in the chemical industry. If a pressure vessel
is rated for 16 bar overpressure, we are not allowed to run it at
32 bar. If the supplier happens to have sold vessels which can
actually withstand 32 bar, and then makes modifications which
lower the actual pressure the vessel can withstand only 16 bar,
the customer has no cause for complaint.
As usual, the specification goes both ways: The supplier
guarantees the pressure rating, and the customer is obliged
(by law, in this case) to never operate the vessel above its
pressure rating. Hence, safety valves rupture discs.
That is very well put.
Specifications are an agreement between the supplier and the client. The supplier promises particular functionality if the client stays within those specifications. It is how things work in a huge range of aspects of life. Sometimes there are agreements in place for what happens if the specifications are broken (fine if you fail to deliver as promised, jail sentence if you break the law, etc.), but these are really just extensions of the agreement and specification.
If we think about computing, we can start with mathematics for examples. A mathematical function maps one set onto another - it specifies what value in the output set is produced from each value in the input set. It does not specify the result for values that are not in the input set, even if they are in a "reasonable" superset. So the real square root function specifies an output for all non-negative real numbers - it does not specify the result for negative real numbers. Attempting to find the square root of a negative number is undefined behaviour.
Functions in computing are the same. You have a specification - a pre-condition, and a post-condition. The inputs (including the environment, if that is relevant) has to satisfy the pre-condition, and then the function guarantees that the post-condition will hold after the function call. Try to put anything else into the function without satisfying the pre-condition, and it's garbage in, garbage out. If you don't understand "garbage in, garbage out", you really don't understand the first thing about software development. This has been understood since the beginning of the programmable computer:
"""
On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question.
"""
In the context of compilers, the specification is the language standard in use at the time, combined with the specifications of any library functions or other code being used. If you don't follow those specifications - your input code does not meet the pre-conditions, or the pre-conditions are not met when your code is run - you get undefined behaviour. There is no rational way to expect any particular result when the input is in essence meaningless.
So if there is a function (or operator, or other feature) specified by the language or by library or function documentation, and you pass it something that is not documented as fulfilling the pre-conditions, it's garbage in, garbage out - your code is wrong. If your code makes assumptions about the workings of a function that are not specified in its post-condition, the code is wrong. It might work during testing, but it is not guaranteed to work. If you try to use a function outside its specifications, then your code is wrong.
Of course it is not always easy to make sure everything is correct within specifications. Programming languages and libraries are complicated, and people make mistakes. And where practical, it can be good to take that into consideration - if it is possible to give error messages or help in the case of bad inputs, then that can be very helpful to people. But it doesn't make sense to try to give the "right" output for wrong input. And it doesn't make sense to do this to the significant detriment of efficiency with correct inputs.
To compare this to specifications in other walks of life, imagine an electricity company. The specification they provide to you, the customer, has the pre-condition that you pay your bills. The post-condition is that you get electricity. If you break the specification - you stop paying your bills - it's perfectly reasonable that they cut off your electricity. But it is /nice/ if they first send you warning letters, and offers to re-arrange your debt. But if you are following the specifications and paying your bills, you would not want the electricity company to keep providing electricity to those who don't pay, because that would mean /you/ would have to pay more.
In the same way, I want my compiler to warn about potential problems or undefined behaviour when it reasonably can, rather than jumping straight to nasal daemons. But I don't want it to generate slower code that it otherwise could, just because some people might write incorrect code. I should not have to pay (in run-time efficiency losses) for other people's potential failure to follow specifications.
But I am quite happy to have compiler options to control the balance and behaviour. Compilers generally do little optimisation without flags explicitly enabling them. And some compilers have flags to change the language specifications (such as making signed integer arithmetic wrap). There's not a lot they could do better to satisfy people who want the tools to conform to their imagined specification rather than the actual specifications.
I suppose one thing they could do is that when a new compiler version comes out with new optimisations, they could have a flag that turns these off even if you have enabled others. Maybe you could have "-olimit=8" to say "limit optimisations to those in gcc 8". That might give fewer surprises to people who have got their code wrong.