View Issue Details

IDProjectCategoryView StatusLast Update
0036279FPCCompilerpublic2021-01-20 11:08
ReporterJulian Puhl Assigned ToFlorian  
Status resolvedResolutionfixed 
Product Version3.3.1 
Fixed in Version3.3.1 
Summary0036279: Compiler generates unnecessary moves when using inline methods
DescriptionThis is a simplified example. When you compile the program posted in "Steps To Reproduce" you will get two different assembly codes for the sums, despite of the code being the same:
# [37] Result1 := obj1.Getter1 + obj1.Getter2;
    movq U_$P$PROJECT1_$$_ARRAY1(%rip),%rdx
    movslq U_$P$PROJECT1_$$_INDEX(%rip),%rax
    movss (%rdx,%rax,4),%xmm1
    movq U_$P$PROJECT1_$$_ARRAY2(%rip),%rax
    movslq U_$P$PROJECT1_$$_INDEX(%rip),%rdx
    movss (%rax,%rdx,4),%xmm0
    addss %xmm1,%xmm0
# Var Result1 located in register xmm0
# [38] Result2 := array1[index] + array2[index];
    movq U_$P$PROJECT1_$$_ARRAY1(%rip),%rcx
    movslq U_$P$PROJECT1_$$_INDEX(%rip),%rax
    movq U_$P$PROJECT1_$$_ARRAY2(%rip),%rdx
    movss (%rcx,%rax,4),%xmm0
    addss (%rdx,%rax,4),%xmm0

As you can see, two mov instructions could be avoided. It would be nice if this behaviour could be fixed, since we have a lot of code which relies on the index being within the object (I moved it outside for this example). This code gets executed very often, so it is performance critical.
Steps To Reproduceprogram project1;

  array1: array of Single;
  array2: array of Single;
  index: Integer;

  TObj1 = object
    function Getter1: Single; inline;
    function Getter2: Single; inline;

  function TObj1.Getter1: Single;
    Result := array1[index];

  function TObj1.Getter2: Single;
    Result := array2[index];

  Result1, Result2: Single;
  obj1: TObj1;

  Result1 := obj1.Getter1 + obj1.Getter2;
  Result2 := array1[index] + array2[index];
TagsNo tags attached.
Fixed in Revision43501
Attached Files


Thaddy de Koning

2019-11-07 17:33

reporter   ~0119142

Your program crashes: you forget to set the arrays size,
Also: which optimization settings are you using?

Julian Puhl

2019-11-07 17:42

reporter   ~0119143

Last edited: 2019-11-07 17:44

View 2 revisions

This is only for demonstrating the assembly code. It is not meant for execution. Thus I stripped all unnecessary code, including initializations.
I tried O3, O4 and all the other optimizations which are unsafe/Ungrouped. Even WHO. It does not change a thing. -al is used to generate the assembly listing.

Marco van de Voort

2019-11-07 22:52

manager   ~0119150

It's indeed strange it doesn't reuse INDEX

Thaddy de Koning

2019-11-08 09:19

reporter   ~0119154

Yes, Marco, that is strange.
But Julian, plz write working code to demonstrate. Reason is that the compiler can (and will!) confuse code paths when presented with nonsense.
This is not the case here - apart from the fact it should not compile at all with proper compiler settings! - as far as I can tell, I have seen such things happen.
Rangechecks on, plz.

Julian Puhl

2019-11-08 11:25

reporter   ~0119155

Thaddy, I made sure that the assembly code did not change when removing code. Remember that this is a stripped down example from our original problem. My goal was to make it easier to find the code in the assembly listing. If the code would have changed I would not have done that.

Issue History

Date Modified Username Field Change
2019-11-07 16:52 Julian Puhl New Issue
2019-11-07 17:33 Thaddy de Koning Note Added: 0119142
2019-11-07 17:42 Julian Puhl Note Added: 0119143
2019-11-07 17:44 Julian Puhl Note Edited: 0119143 View Revisions
2019-11-07 22:52 Marco van de Voort Note Added: 0119150
2019-11-08 09:19 Thaddy de Koning Note Added: 0119154
2019-11-08 11:25 Julian Puhl Note Added: 0119155
2019-11-16 18:41 Florian Assigned To => Florian
2019-11-16 18:41 Florian Status new => resolved
2019-11-16 18:41 Florian Resolution open => fixed
2019-11-16 18:41 Florian Fixed in Version => 3.3.1
2019-11-16 18:41 Florian Fixed in Revision => 4350
2019-11-16 18:41 Florian FPCTarget => -
2021-01-20 11:08 Pierre Muller Fixed in Revision 4350 => 43501