View Issue Details
|ID||Project||Category||View Status||Date Submitted||Last Update|
|0035872||FPC||Compiler||public||2019-07-22 00:07||2019-07-27 19:48|
|Reporter||Timm Thaler||Assigned To||Jeppe Johansen|
|Status||resolved||Resolution||no change required|
|Product Version||3.3.1||Product Build||r42480|
|Target Version||Fixed in Version|
|Summary||0035872: AVR: Compiler produces inefficient code when compare 16 bit variables|
|Description||Since some weeks the compiler startet with producing inefficient code when comparing 16 bit variable with possible carry. The variables are expanded to 32 bit and the compare is done with 32 bit.|
Adding a constant in the compare is important to reproduce. It does not happen when comparing without adding or adding a variable.
|Steps To Reproduce||var|
a, b : uint16;
if a > b + 1 then begin
#  if a > b + 1 then begin
|Additional Information||Compiler options is -O3, but -O4 or -Os doesn't change behavior.|
It may seem to be a good idea to prevent overflow problems, but it puffs the code and doubles execution time - and in most cases it is not necessary.
|Tags||No tags attached.|
|Fixed in Revision|
I suspect this behaviour is caused by automatic type conversion rules 2 & 3a as can be seen below table 3.2 here: https://www.freepascal.org/docs-html/ref/refsu4.html. Rule 2 implies (but it is not all that clear to me) that the constant value is interpreted as a shortint. Rule 3a then requires the use of int32 to evaluate the expression.
A type cast of the constant value to an unsigned type may result in the desired code being generated (I don't have FPC for AVR handy at the moment so I cannot test this).
Type casting the constant to an unsigned type does reduce generated code size:
function testComparison(a, b: uint16): boolean;
if a > b + byte(1) then
Result := true
Result := false;
Results in the following assembler:
#  if a > b + byte(1) then
#  Result := true
#  Result := false;
#  end;
Edit: the type cast in the example code was missing for some reason.
I checked this for some operations (add, sub, mul, compare) and it is: Operation of 8 or 16 bit signed with 16 bit unsigned leads to an 32 bit signed result. So this is strange if one have to put an unsigned typecast to a positive constant, but it seems to be according to the conversion rules 3a.
uint8 uint16 int8 int16
uint8 =uint8 =uint16 =int8 =int16
uin16 =uint16 =uint16 =int32 =int32
int8 =int8 =int32 =int8 =int16
int16 =int16 =int32 =int16 =int16
So better use mostly signed types in calculations or compares.
I guess this can be closed?
|2019-07-22 00:07||Timm Thaler||New Issue|
|2019-07-23 10:58||Christo Crause||Note Added: 0117349|
|2019-07-23 21:15||Christo Crause||Note Added: 0117364|
|2019-07-24 13:55||Christo Crause||Note Edited: 0117364||View Revisions|
|2019-07-24 19:25||Timm Thaler||Note Added: 0117382|
|2019-07-25 11:39||Jeppe Johansen||Assigned To||=> Jeppe Johansen|
|2019-07-25 11:39||Jeppe Johansen||Status||new => resolved|
|2019-07-25 11:39||Jeppe Johansen||Resolution||open => no change required|
|2019-07-25 11:39||Jeppe Johansen||FPCTarget||=> -|