Emil Jerabek wrote:
during some debugging I noticed that GPC generates very hairy code for the `mod' operator with signed arguments. A closer look revealed that the code contains a lot of branching on conditions which can be determined on compile time, and most surprisingly, the value of X mod Y is recomputed _twice_, if X is negative. (I've attached a commented assembler dump.)
This may be partially a back-end problem (CSE?), but I feel there's something wrong in the relevant code in gpc-common.c (build_pascal_binary_op) as well.
I don't know if CSE is suppose to find this case, but at least is better to do it in the front-end indeed. (All it takes is a `save_expr' which I'm putting in now.)
`exp1 mod exp2' gets translated into something like
exp2 <= 0 ? error : exp1 >= 0 ? exp1 mod exp2 : ((-exp1) mod exp2) == 0 ? 0 : exp2 - (-exp1) mod exp2
This arranges that both arguments supplied to the "internal mod" are non-negative, but this information is not passed on -- the arguments are still declared as signed types, which apparently makes the back-end to produce the mess it does.
Right. I've changed it to unsigned types now, and it simplifies the generated code.
The result type of the whole `mod' expression looks dubious too. IIUIC, `exp1 mod exp2' inherits the type of exp1. Now, the result of `mod' is guaranteed to be nonnegative and to fit in the type of exp2 (or more precisely, it is in 0 .. High (type of (exp2)) - 1), whereas it needn't have anything to do with the type of exp1: consider
var X, Z: Integer; Y: LongInt;
begin X := -8; Y := High (LongInt); Z := X mod Y { -> overflow } end
True. (Though, of course, GPC currently doesn't check for overflows generally, so it won't detect this one either, but in other situations, using the other type should lead to correct results.)
(BTW, where is fjf434c.pas?)
Oh, I had put it aside to work on another problem it caused on some platforms (but didn't actually get around to it). Now I'm putting it back to see if these changes have any effect on that problem. (According to first quick tests, they seem to. :-)
CBFalconer wrote:
Adriaan van Os wrote:
I might be interesting to note that not all Pascal compilers follow the ISO 7185 Pascal standard for the mod operator. The standard states:
[...]
This is the result of Borland ignoring the standard. There is no excuse, because the standard was available long before the first Turbo Pascal. The drafts were published in Pascal News in the mid '70s. It is one of the reasons many will not consider Delphi/Borland/Turbo to be Pascal.
That's another reason why GPC's `mod' implementation is so hairy (because it emulates Borland's in `--borland-pascal') ...
Frank