While trying to optimise a block of code recently, I came across a curious aspect of the Pascal compiler.
The following block of dummy code shows the issue:
function Test(Ch : char) : byte;
begin
asm
MOVF FARG_Test_Ch, 0
MOVF R0
end;
Result := R0;
end;
The compiler generates this listing:
_Test:
;HexConvert.mpas,9 :: begin
;HexConvert.mpas,11 :: MOVF FARG_Test_Ch, 0
0x001C 0x5019 MOVF FARG_Test_Ch, 0, 0
;HexConvert.mpas,12 :: MOVF R0
0x001E 0x5200 MOVF R0, 1, 0
;HexConvert.mpas,14 :: Result := R0;
0x0020 0xF001C000 MOVFF R0, R1
;HexConvert.mpas,15 :: end;
0x0024 0xF000C001 MOVFF R1, R0
L_end_Test:
0x0028 0x0012 RETURN 0
; end of _Test
Clearly register R0 is used to return the result.
So why does the compiler insert the two 'MOVFF' instructions as they do not appear to add any functionality ?
Optimised code query
Re: Optimised code query
Although your example is not typical (due to use of assembly) and also not as apparent as could be demonstrated, you're right. Compiler forms internal variable storing function result that is copied at the end to internal registers (R0, R1, etc. depending of function result type). There's no optimization of this process, so when result of function is already in the right Rx registers, it is still being copied to the result variable and then back to Rx registers. Here's a simple example
Arithmetic library functions place their results in a standard way in Rx registers, but these are copied to result variable and then back:
Introduction of more aggressive optimization few years ago that now replaces as many local variables as possible with internal Rx registers (function result among them) didn't change the picture. (In fact, this kind of optimization produces sometimes more code and has to be blocked.)
Code: Select all
function dummy(arg:word): word;
begin
result:=arg*10;
End;{dummy}
Code: Select all
result:=arg*10;
MOVFF FARG_dummy_arg, R0
MOVFF FARG_dummy_arg+1, R1
MOVLW 10
MOVWF R4
MOVLW 0
MOVWF R5
CALL _Mul_16x16_U, 0
MOVFF R0, dummy_local_result \
MOVFF R1, dummy_local_result+1 | superfluous code
End;{dummy}
MOVFF dummy_local_result, R0 |
MOVFF dummy_local_result+1, R1 /
RETURN 0