Recent

Author Topic: Statement as memory barrier for globals ("volatile")  (Read 28641 times)

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Statement as memory barrier for globals ("volatile")
« Reply #30 on: November 25, 2017, 06:36:14 pm »
Which is EXACTLY the same as an assignable typed const behaves.

NO!

It is not.
Thaddy is still holding his position but this time in the bug tracker. Nothing will change his mind, nothing.  :(



OTOH, Remy Lebeau on SO:
Quote
Starting with Delphi 10.1 Berlin, the desktop compilers now support [volatile] as well.

http://docwiki.embarcadero.com/RADStudio/Berlin/en/Compiler_Attributes#Volatile

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Statement as memory barrier for globals ("volatile")
« Reply #31 on: November 26, 2017, 01:53:22 am »
I understand your pain.. Really....

 Its called Software politics, Resistance is FUTILE.

 At least Embarcadero knows what it's for.
The only true wisdom is knowing you know nothing

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Statement as memory barrier for globals ("volatile")
« Reply #32 on: November 26, 2017, 02:28:46 am »
At least Embarcadero knows what it's for.
FPC has more cases where volatile would be needed.

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Statement as memory barrier for globals ("volatile")
« Reply #33 on: November 26, 2017, 06:17:59 am »
Lets do some checks with the following concept code
Code: Pascal  [Select][+][-]
  1. program testVarAccess;
  2. var i: word;
  3. begin
  4.   i := 255;
  5.   if i > 0 then
  6.      i := 0;
  7.  
  8.   while True do
  9.   begin
  10.     if i = 1234 then
  11.       i := 0;
  12.   end;
  13. end.
Compiled with:
Code: [Select]
-Tembedded -Pavr -CpAVR5 -MObjFPC -Sm -O4 -vabq -Filib/avr-embedded -Fu. -FUlib/avr-embedded -FE../ -Wpatmega328p -g -a -XPavr- -al -Sm -Si -dF_CPU:=16000000Note -O4. Generated code for main:
Code: Pascal  [Select][+][-]
  1. begin
  2.   9e:   0e 94 5c 00     call    0xb8    ; 0xb8 <FPC_INIT_FUNC_TABLE>
  3.   i := 255;
  4.   a2:   2f ef           ldi     r18, 0xFF       ; 255
  5.   a4:   21 2d           mov     r18, r1
  6.   if i > 0 then
  7.      i := 0;
  8.   a6:   31 2d           mov     r19, r1
  9.   a8:   21 2d           mov     r18, r1
  10.  
  11.   while True do
  12.   begin
  13.     if i = 1234 then
  14.   aa:   32 3d           cpi     r19, 0xD2       ; 210
  15.   ac:   44 e0           ldi     r20, 0x04       ; 4
  16.   ae:   24 07           cpc     r18, r20
  17.   b0:   e1 f7           brne    .-8             ; 0xaa <PASCALMAIN+0xc>
  18.       i := 0;
  19.   b2:   31 2d           mov     r19, r1
  20.   b4:   21 2d           mov     r18, r1
  21.   while True do
  22.   b6:   f9 cf           rjmp    .-14            ; 0xaa <PASCALMAIN+0xc>
Clearly variable i is treated as a register variable only, which in this case is both correct and generates compact code. Now test what happens if an interrupt is also added to the mix:
Code: Pascal  [Select][+][-]
  1. program testVarAccess;
  2.  
  3. var i: word;
  4.  
  5. procedure Timer0Overflow; alias: 'TIMER0_OVF_ISR'; interrupt;
  6. begin
  7.   inc(i);
  8. end;
  9.  
  10. begin
  11.   i := 255;
  12.   if i > 0 then
  13.      i := 0;
  14.  
  15.   while True do
  16.   begin
  17.     if i = 1234 then
  18.       i := 0;
  19.   end;
  20. end.
Generated code:
Code: Pascal  [Select][+][-]
  1. procedure Timer0Overflow; alias: 'TIMER0_OVF_ISR'; interrupt;
  2. begin
  3.   9e:   af 93           push    r26
  4.   a0:   4f 93           push    r20
  5.   a2:   3f 93           push    r19
  6.   a4:   2f 93           push    r18
  7.   a6:   0f 92           push    r0
  8.   a8:   0f b6           in      r0, 0x3f        ; 63
  9.   aa:   0f 92           push    r0
  10.   inc(i);
  11.   ac:   40 91 00 01     lds     r20, 0x0100
  12.   b0:   30 91 01 01     lds     r19, 0x0101
  13.   b4:   21 e0           ldi     r18, 0x01       ; 1
  14.   b6:   42 0f           add     r20, r18
  15.   b8:   31 1d           adc     r19, r1
  16.   ba:   40 93 00 01     sts     0x0100, r20
  17.   be:   30 93 01 01     sts     0x0101, r19
  18. end;
  19.   c2:   0f 90           pop     r0
  20.   c4:   0f be           out     0x3f, r0        ; 63
  21.   c6:   0f 90           pop     r0
  22.   c8:   2f 91           pop     r18
  23.   ca:   3f 91           pop     r19
  24.   cc:   4f 91           pop     r20
  25.   ce:   af 91           pop     r26
  26.   d0:   18 95           reti
  27.  
  28. 000000d2 <PASCALMAIN>:
  29.  
  30. begin
  31.   d2:   0e 94 8d 00     call    0x11a   ; 0x11a <FPC_INIT_FUNC_TABLE>
  32.   i := 255;
  33.   d6:   3f ef           ldi     r19, 0xFF       ; 255
  34.   d8:   21 2d           mov     r18, r1
  35.   da:   30 93 00 01     sts     0x0100, r19
  36.   de:   20 93 01 01     sts     0x0101, r18
  37.   if i > 0 then
  38.   e2:   30 91 00 01     lds     r19, 0x0100
  39.   e6:   20 91 01 01     lds     r18, 0x0101
  40.   ea:   13 16           cp      r1, r19
  41.   ec:   12 06           cpc     r1, r18
  42.   ee:   30 f4           brcc    .+12            ; 0xfc <PASCALMAIN+0x2a>
  43.      i := 0;
  44.   f0:   21 2d           mov     r18, r1
  45.   f2:   31 2d           mov     r19, r1
  46.   f4:   20 93 00 01     sts     0x0100, r18
  47.   f8:   30 93 01 01     sts     0x0101, r19
  48.  
  49.   while True do
  50.   begin
  51.     if i = 1234 then
  52.   fc:   20 91 00 01     lds     r18, 0x0100
  53.  100:   30 91 01 01     lds     r19, 0x0101
  54.  104:   22 3d           cpi     r18, 0xD2       ; 210
  55.  106:   24 e0           ldi     r18, 0x04       ; 4
  56.  108:   32 07           cpc     r19, r18
  57.  10a:   c1 f7           brne    .-16            ; 0xfc <PASCALMAIN+0x2a>
  58.       i := 0;
  59.  10c:   31 2d           mov     r19, r1
  60.  10e:   21 2d           mov     r18, r1
  61.  110:   30 93 00 01     sts     0x0100, r19
  62.  114:   20 93 01 01     sts     0x0101, r18
  63.   while True do
  64.  118:   f1 cf           rjmp    .-30            ; 0xfc <PASCALMAIN+0x2a>
Clearly the interrupt functionality requires that variable i be read from memory on every access.  The generated code above clearly demonstrates this is the case.

So the compiler seems to recognize when not to optimize memory access away, at least in this rather trivial test case.  Now if only this behaviour is guaranteed and documented the whole need for volatile is redundant.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Statement as memory barrier for globals ("volatile")
« Reply #34 on: November 26, 2017, 06:14:58 pm »
So the compiler seems to recognize when not to optimize memory access away, at least in this rather trivial test case.  Now if only this behaviour is guaranteed and documented the whole need for volatile is redundant.
And i believe that is also what Thaddy was hinting on. The documentation states:
Quote
Contrary to ordinary constants, a value can be assigned to them at run-time.
In case the compiler optimized things away between different calls then it is the compiler/optimizer at fault, not respecting the consequences of the statement made in the documentation.

Do note that code optimization is really not my area of knowledge, so a compiler developer might argue that the default behaviour in such cases is undetermined. Is that mentioned somewhere in the documentation or should that be considered common knowledge ?

In that regards i also don't fully understand why there would be need for a compiler hint to force this or that, unless it isn't possible to guarantee the compiler behaviour in any other way.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Statement as memory barrier for globals ("volatile")
« Reply #35 on: November 27, 2017, 12:29:34 am »
So the compiler seems to recognize when not to optimize memory access away, at least in this rather trivial test case.
As you can see, we are guessing and we don't know the rules.

Now if only this behaviour is guaranteed and documented
+1

the whole need for volatile is redundant.
I disagree, volatile would help both the programmer and the compiler not to guess.

Here is a test where an interrupt procedure is *not* used:
Code: Pascal  [Select][+][-]
  1. program testVarAccess;
  2.  
  3. var
  4.   b1, b2: byte;
  5. //  pb1, pb2: pbyte;
  6.  
  7. begin
  8. {  pb1 := @b1;
  9.   pb2 := @b2;  //}
  10.  
  11.   b1 := 255;
  12.   if b1 > 0 then
  13.      b2 := 0;
  14.  
  15.   while True do
  16.   begin
  17.     if b2 = 123 then
  18.       b1 := 0;
  19.   end;
  20. end.

Code: ASM  [Select][+][-]
  1. .globl  main
  2. main:
  3. # Var b1 located in register r18
  4. # Var b2 located in register r19
  5. # [Blinky.lpr]
  6. # [7] begin
  7.         call    FPC_INIT_FUNC_TABLE
  8. # Var b1 located in register r18
  9. # [11] b1 := 255;
  10.         ldi     r26,-1
  11.         mov     r18,r26
  12. # Var b2 located in register r19
  13. # [13] b2 := 0;
  14.         mov     r19,r1
  15. .Lj3:
  16. # [17] if b2 = 123 then
  17.         cpi     r19,123
  18.         brne    .Lj3
  19. # [18] b1 := 0;
  20.         mov     r18,r1
  21. # [15] while True do
  22.         rjmp    .Lj3
  23. # [20] end.

See what happens when you add pointers:
Code: Pascal  [Select][+][-]
  1. program testVarAccess;
  2.  
  3. var
  4.   b1, b2: byte;
  5.   pb1, pb2: pbyte;
  6.  
  7. begin
  8.   pb1 := @b1;
  9.   pb2 := @b2;  //}
  10.  
  11.   b1 := 255;
  12.   if b1 > 0 then
  13.      b2 := 0;
  14.  
  15.   while True do
  16.   begin
  17.     if b2 = 123 then
  18.       b1 := 0;
  19.   end;
  20. end.

Code: ASM  [Select][+][-]
  1. .globl  main
  2. main:
  3. # Var pb1 located in register ??:r18
  4. # Var pb2 located in register ??:r18
  5. # [Blinky.lpr]
  6. # [7] begin
  7.         call    FPC_INIT_FUNC_TABLE
  8. # [8] pb1 := @b1;
  9.         ldi     r18,lo8(U_sPsTESTVARACCESS_ss_B1)
  10.         ldi     r19,hi8(U_sPsTESTVARACCESS_ss_B1)
  11. # Var pb1 located in register r18
  12. # [9] pb2 := @b2;  //}
  13.         ldi     r18,lo8(U_sPsTESTVARACCESS_ss_B2)
  14.         ldi     r19,hi8(U_sPsTESTVARACCESS_ss_B2)
  15. # Var pb2 located in register r18
  16. # [11] b1 := 255;
  17.         ldi     r26,-1
  18.         mov     r18,r26
  19.         sts     (U_sPsTESTVARACCESS_ss_B1),r18
  20. # [12] if b1 > 0 then
  21.         lds     r18,(U_sPsTESTVARACCESS_ss_B1)
  22.         cp      r1,r18
  23.         brsh    .Lj5
  24. # [13] b2 := 0;
  25.         mov     r18,r1
  26.         sts     (U_sPsTESTVARACCESS_ss_B2),r18
  27. .Lj5:
  28. # [17] if b2 = 123 then
  29.         lds     r18,(U_sPsTESTVARACCESS_ss_B2)
  30.         cpi     r18,123
  31.         brne    .Lj5
  32. # [18] b1 := 0;
  33.         mov     r18,r1
  34.         sts     (U_sPsTESTVARACCESS_ss_B1),r18
  35. # [15] while True do
  36.         rjmp    .Lj5
  37. # [20] end.

Notice how b1 and b2 without pointers where optimized in registers, while with pointers they were treated as volatile variables. It gets complicated when you use pointers, and the compiler tries the safest way and assumes these variables to be volatile which was not necessary.

More over, you used a small chip that does not take an external memory. Volatile is of more importance when the compiler deals with what seems to the CPU (or MC) as a normal [external] memory access while in fact is an I/O port. Without volatile the compiler will optimize the code wrongly.

On top of the above:
« Last Edit: November 27, 2017, 12:57:57 am by engkin »

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Statement as memory barrier for globals ("volatile")
« Reply #36 on: November 27, 2017, 01:31:53 am »
In that regards i also don't fully understand why there would be need for a compiler hint to force this or that, unless it isn't possible to guarantee the compiler behaviour in any other way.
Nothing in the documentation prevents the compiler from keeping a constant in a register, and based on {$J} it may allow/prevent a change to its value. On the other hand, accessing a volatile variable means accessing the memory every time, no matter what.

Simple example:
Imagine a set of ten temperature sensors memory mapped to one location. Every time you read that location you actually read a different sensor. So to read the same sensor twice you have to read that location 11 times!! The first reading holds the first value of that sensor, and the 11th reading holds the second value. Without volatile, the compiler will give you the first reading always.

Of course there are solutions, like using assembly, or using a function. Both imply that there is no equivalent to volatile in Pascal.
« Last Edit: November 27, 2017, 01:34:35 am by engkin »

jamie

  • Hero Member
  • *****
  • Posts: 6091
Re: Statement as memory barrier for globals ("volatile")
« Reply #37 on: November 27, 2017, 03:51:40 am »
Running some more test, it seem that writeable constants for the moment, at least the test I did
was always being referenced however, there is also a optimizer issue here.

 If I were to assign several variables with the same constant writeable value, then it simply waste
code space and time reloading each one when the first load could load that into a register and then
use that Reg to define the rest...
 
 because someone decided to make writeable constants act this way even when it means bloated code
generation, when not needed, you have no choice to force the compiler to act inefficiently.. 

  If the key word VOLATILE was employed, you can then have writeable constants be register loaded for
a serials of defines when there is no volatile issue but, when there is a volatile issue, one could prefix it
with the keyword VOLATILE or mark the writeable constant as Volatile, then the compiler can do what it is
currently doing now, and that is keep reloading from the constant source.

 as it is now, it makes for bloated code if that is the actual intention behind it or it just maybe a fluke that
it just happen to end up that way out of convenience.

 I would feel better if the VOLATILE keyword was employed so that we know for sure the compiler is
behaving like it should be and when not using the volatile we could assume the compiler will take advantage
of optimizing the writeable constants.
The only true wisdom is knowing you know nothing

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Statement as memory barrier for globals ("volatile")
« Reply #38 on: November 27, 2017, 01:27:16 pm »
The documentation states:
Quote
Contrary to ordinary constants, a value can be assigned to them at run-time.
In case the compiler optimized things away between different calls then it is the compiler/optimizer at fault, not respecting the consequences of the statement made in the documentation.
For optimisation there is only trouble in case of multithreading, because the constant could be changed in any moment of time and the other thread could be at any place in the code. But exactly the same holds for ALL* variables. (*Only procedure local variables surely cannot be changed from outside).

And I start to believe that this is actually the current situation, i.e. that all variables that are used in more than one procedure (or are published to other units) are treated as volatiles, at least something alike.

E.g. the "Terminated" variable of TThread is normally polled in a loop in the Execute method:
  while not Terminated do
Also in most cases the code within the loop doesn't modify the variable "Terminated", but by an other thread to indicate that the thread should terminate itself.
For a compiler seeing "Terminated" as NON-volatile this would mean, its either an infinite loop, or the loop isn't even entered once. Obviously, such optimisation isn't done.

Looking at optimisations, I would expect that the following lines
  AComponent.value:= 12;
  [...]
  AComponent.value:= AComponent.value * a;
are optimized to something like
  AComponent.value:= 12 * a;

On the other hand if the variable is used e.g. as locking mechanism:
  AComponent. Lockstate:= 2;
  [...]
  AComponent. Lockstate:= 3;
they may not be optimized, otherwise it breaks functionality.

So my question from the initial post still is open: Are these kinds of variables are treated like volatiles and if yes in what extend.

If the answer is yes, then introducing a volatile modifier actually would mean to introduce non-volatile variables and with that allow deeper optimisations. That may break existing code, though.

If the answer is no, then some improvements are neccessary to make fpc usable on target embedded.


Quote
In that regards i also don't fully understand why there would be need for a compiler hint to force this or that, unless it isn't possible to guarantee the compiler behaviour in any other way.
If all variables are volatile by default then of course the compiler behaviour is guaranteed and no optimisation issues can arise (because there couldn't be any variable optimisation be done).

EDIT:
From the programmers guide:
Quote
11.1.13    Register variables
When using the
-Or
switch, local variables or parameters which are used very often will be moved
to registers for faster access.
ftp://ftp.freepascal.org/pub/fpc/docs-pdf/prog.pdf#subsection.11.1.13
« Last Edit: November 27, 2017, 01:52:44 pm by kupferstecher »

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Statement as memory barrier for globals ("volatile")
« Reply #39 on: December 04, 2017, 05:31:49 pm »
Thank you for your clear examples engkin

Nothing in the documentation prevents the compiler from keeping a constant in a register,
That is where we kind of disagree :)

I quote again from documentation:
Quote
Contrary to ordinary constants, a value can be assigned to them at run-time.
Just like a ordinary variable, this special type of constant can be assigned a value at runtime.

That is a convention to which, i assume, we both agree.

Again i note my naive approach that tells me that if i can assign a value to it at runtime that the compiler (or optimizer) would have to take that convention into account.

By not doing so, the convention to which we agreed is worth nothing as the compiler/optimizer breaks that convention, producing code that is unpredictable.


In that regards i'm more in line with kupferstecher/ccrause's posts and the remark about this kind of constant always being 'volatile'.

Quote
and based on {$J} it may allow/prevent a change to its value. On the other hand, accessing a volatile variable means accessing the memory every time, no matter what.
I agree with you engkin that in case it is unclear that it would be more helpful to hint/instruct the compiler, i just fail to see why it should be the other way around (unless the motivation for that would be that other compilers implement it that way).

From the programmers guide:
Quote
11.1.13    Register variables
When using the
-Or
switch, local variables or parameters which are used very often will be moved
to registers for faster access.
ftp://ftp.freepascal.org/pub/fpc/docs-pdf/prog.pdf#subsection.11.1.13
Thank you for that link kupferstecher. I seem to have missed that.

Still, my naive approach tells me that if anything breaks there is something at fault. Would using normal variables break my code in a similar fashion do we then agree we should use a special keyword to keep code from breaking when using optimization ?

kupferstecher

  • Hero Member
  • *****
  • Posts: 583
Re: Statement as memory barrier for globals ("volatile")
« Reply #40 on: December 04, 2017, 06:08:52 pm »
Still, my naive approach tells me that if anything breaks there is something at fault.
As I wrote in my post before, the only way to achive that nothing gets broken by optimisations is not to optimize on variable level at all (only procedure local variables are safe).
I have the feeling that this is the current situation of fpc, but low optimisation isn't something good for advertise.

Quote
By not doing so, the convention to which we agreed is worth nothing as the compiler/optimizer breaks that convention, producing code that is unpredictable.
The convention is totally fine in parts of the programm where context isn't switched and that I'd say is most of the code in programs. Why should typed constants be more suitable for multithreading than normal variables?

Quote
i just fail to see why it should be the other way around
It would be imagable to introduce a variable modifier that does allow code optimisation for the marked variable (only). But normally most of the variables should be considered for optimisation. And only a very few in a programm are subject to context changes and thus are not allowed to be optimised. Also hardware register access of course may never be optimised.

Quote
Would using normal variables break my code in a similar fashion do we then agree we should use a special keyword to keep code from breaking when using optimization ?
As the examples showed they do :(
At least in rare cases.

engkin

  • Hero Member
  • *****
  • Posts: 3112
Re: Statement as memory barrier for globals ("volatile")
« Reply #41 on: December 05, 2017, 04:33:52 am »
Nothing in the documentation prevents the compiler from keeping a constant in a register,
That is where we kind of disagree :)
In this case you also disagree with the compiler. In this example the compiler optimized i := t into movl $1,%eax despite the fact that t is a writable constant. Consider that code as part of the example of temperature sensors. I am trying to read the values of the sensors, but the compiler decided to give me a fixed value 1.

I am trying to read the tenth sensor. Here is how it is done using C. How can I read that sensor using Pascal?.



I quote again from documentation:
Quote
Contrary to ordinary constants, a value can be assigned to them at run-time.
Just like a ordinary variable, this special type of constant can be assigned a value at runtime.
The implementation is left out. It does not specify whether this value is going to be assigned to a memory location or register(s), or used as an immediate value.

That is a convention to which, i assume, we both agree.

Again i note my naive approach that tells me that if i can assign a value to it at runtime that the compiler (or optimizer) would have to take that convention into account.

By not doing so, the convention to which we agreed is worth nothing as the compiler/optimizer breaks that convention, producing code that is unpredictable.

In that regards i'm more in line with kupferstecher/ccrause's posts and the remark about this kind of constant always being 'volatile'.
kupferstecher did not get a satisfactory answer, yet.
ccrause does not seem to believe that writable constants are volatile.
Jonas based on ccrause's quote "in FPC there isn't a full equivalent of "volatile""
Martin made it clear writable constants are not volatile.
ASerge knows there is no corresponding directive in FPC



Molly, two questions:

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Statement as memory barrier for globals ("volatile")
« Reply #42 on: December 05, 2017, 07:40:14 am »
In this case you also disagree with the compiler. In this example the compiler optimized i := t into movl $1,%eax despite the fact that t is a writable constant.
Yes, that is affirmative. To be consistent that generated code would also have to be considered 'wrong'.

Quote
Consider that code as part of the example of temperature sensors. I am trying to read the values of the sensors, but the compiler decided to give me a fixed value 1.
Understood.

Quote
I am trying to read the tenth sensor. Here is how it is done using C. How can I read that sensor using Pascal?.
Declaring your t as threadvar should be able to do the trick ? But i don't know how your sensor is declared exactly so that might perhaps not be an option for your case ? Note that i did got the underlying message there  :)

Quote
The implementation is left out. It does not specify whether this value is going to be assigned to a memory location or register(s), or used as an immediate value.
Yes, it is left out. We are not in disagreement there. However, being able to assign to it at runtime also means that whenever the value is changed, the generated code should account for that situation, otherwise the part "a value can be assigned to them at run-time" has no meaning whatsoever.

When using the naive approach, i don't care about what the compiler or optimizer does, as long as it obeys the statement (and corresponding implications that goes along with that statement). Either that or the documentation is incorrect (in which case it should add: but it doesn't matter what you write to them because the compiler simply ignores what you write to it... in certain circumstances, while in others it will work as intended by the programmer).

Yes, the underlying message  ;D

Quote
kupferstecher did not get a satisfactory answer, yet.
ccrause does not seem to believe that writable constants are volatile.
Jonas based on ccrause's quote "in FPC there isn't a full equivalent of "volatile""
Martin made it clear writable constants are not volatile.
ASerge knows there is no corresponding directive in FPC
Thank you for the links. I've read the thread though :-)

So from those we are able to conclude that writable constant don't act as volatile under shown examples/remarks.

Quote
Molly, two questions:
Because they are secretly converting their compiler into a transpiler which in the end will use gcc in order to be able to support more platforms  :P

But on a more serious note: Is there a particular reason to have a fix for this 'problem' using a volatile solution ? I can already sense the Delphi compatibility argument coming up there.

Quote
Using a threadvar ? See also my comment above.

molly

  • Hero Member
  • *****
  • Posts: 2330
Re: Statement as memory barrier for globals ("volatile")
« Reply #43 on: December 05, 2017, 07:54:17 am »
As I wrote in my post before, the only way to achive that nothing gets broken by optimisations is not to optimize on variable level at all (only procedure local variables are safe).
I have the feeling that this is the current situation of fpc, but low optimisation isn't something good for advertise.
You've got a very valid point there.

Quote
The convention is totally fine in parts of the programm where context isn't switched and that I'd say is most of the code in programs. Why should typed constants be more suitable for multithreading than normal variables?
I think we have a misunderstanding there as also engkin seems to believe i am in favour of using typed constant to 'solve' the issue. Let me clarify that this isn't what i attempted to advertise.

Based on thaddy's remarks I was merely suggesting that it could be possible that a typed constants currently act that way by default.

Quote
It would be imagable to introduce a variable modifier that does allow code optimisation for the marked variable (only). But normally most of the variables should be considered for optimisation. And only a very few in a programm are subject to context changes and thus are not allowed to be optimised. Also hardware register access of course may never be optimised.
Also a very valid point and is a very good argument to not do it the other way around as i suggested. I also prefer your remark about using a variable modifier or perhaps a specific section for those variables that aren't allowed to be 'optimized away'.

Quote
As the examples showed they do :(
At least in rare cases.
Yes, that indeed deserves a  :(
« Last Edit: December 05, 2017, 08:00:23 am by molly »

ccrause

  • Hero Member
  • *****
  • Posts: 845
Re: Statement as memory barrier for globals ("volatile")
« Reply #44 on: December 06, 2017, 04:15:34 am »

Simple example:
Imagine a set of ten temperature sensors memory mapped to one location.

To me it seems as if the original Pascal sample code you reference isn't memory mapped.  t is simply an assignable const.  I think your example started as a test of Thaddy's volatile = {$J+} const assertion.  So expanding your example to map variable t to a memory location does produce the expected (at least what I expected ) code:
Code: Pascal  [Select][+][-]
  1. program project1;
  2.  
  3. var
  4.   t: byte absolute 1;
  5.   temp: byte;
  6.  
  7. begin
  8.   t := 255;
  9.   temp := t;
  10.   WriteLn(temp);
  11. end.

The generated assembler for the main code (on x86_64 linux), optimization level -O4:
Code: Pascal  [Select][+][-]
  1. # [8] t := 255;
  2.         movq    $1,%rax
  3.         movb    $255,(%rax)
  4. .Ll3:
  5. # [9] temp := t;
  6.         movq    $1,%rax
  7.         movb    (%rax),%al
  8.         movb    %al,U_$P$PROJECT1_$$_TEMP(%rip)
  9. .Ll4:
  10. # [10] WriteLn(temp);
  11.         call    fpc_get_output@PLT
  12. # etc.
Memory is accessed both when writing and reading (if my limited understanding of AT&T assembler is correct).  Of course it generates a runtime error since the operating system is interfering...

 

TinyPortal © 2005-2018