www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Immutables converted to immediates

reply Cecil Ward <cecil cecilward.com> writes:
This is a question about either the front end or back end of GDC 
and maybe also LDC`.

At compile time, should the value of arr[0] etc be calculable so 
that the code below turns out to be something like *p == 1 where 
n is an immediate constant in asm?

immutable uint arr = [1,2,3];

immutable uint * p;
loop
     {
     if ( arr[0]== p[0] && arr[1] == p[1] && arr[2] == p[2]
         …
     }
GDC is generating a structure in the code segment and then 
fetching it even though the values of the elements ought to be 
known at compile-time. I’m not sure why. The actual code, x86-64 
in this case, consists of a load of fetches from the code segment 
into successive registers before the start of the loop, and the 
loop then consists of a load of instructions like cmp [r8+4*rax], 
r9, where r9, r10 etc we’re loaded up from the fetches from 
[rip+disp] before th4 loop, a minor strength reduction compared 
to a compare-immediate, as it has plenty of registers free. The 
mystery is why the fetches from [rip+disp] even exist, given that 
they are known values.
Jun 28 2023
next sibling parent Cecil Ward <cecil cecilward.com> writes:
On Wednesday, 28 June 2023 at 17:27:37 UTC, Cecil Ward wrote:
 This is a question about either the front end or back end of 
 GDC and maybe also LDC`.

 At compile time, should the value of arr[0] etc be calculable 
 so that the code below turns out to be something like *p == 1 
 where n is an immediate constant in asm?

 immutable uint arr = [1,2,3];

 immutable uint * p;
 loop
     {
     if ( arr[0]== p[0] && arr[1] == p[1] && arr[2] == p[2]
         …
     }
 GDC is generating a structure in the code segment and then 
 fetching it even though the values of the elements ought to be 
 known at compile-time. I’m not sure why. The actual code, 
 x86-64 in this case, consists of a load of fetches from the 
 code segment into successive registers before the start of the 
 loop, and the loop then consists of a load of instructions like 
 cmp [r8+4*rax], r9, where r9, r10 etc we’re loaded up from the 
 fetches from [rip+disp] before th4 loop, a minor strength 
 reduction compared to a compare-immediate, as it has plenty of 
 registers free. The mystery is why the fetches from [rip+disp] 
 even exist, given that they are known values.
What it’s for: I have a tight loop to skip to the end of the various types of D comments eg "*/", or until a newline for "//" comments etc. as I’ve written a cheap parser for a small part of the grammar of D. There’s quite a bit of overhead before the start of the loop, and I’m not sure that this is such a great idea, jury is still out. I need to think about it more.
Jun 28 2023
prev sibling next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 6/28/23 19:27, Cecil Ward wrote:
 This is a question about either the front end or back end of GDC and 
 maybe also LDC`.
 
 At compile time, should the value of arr[0] etc be calculable so that 
 the code below turns out to be something like *p == 1 where n is an 
 immediate constant in asm?
 
 immutable uint arr = [1,2,3];
 
 immutable uint * p;
 loop
      {
      if ( arr[0]== p[0] && arr[1] == p[1] && arr[2] == p[2]
          …
      }
 GDC is generating a structure in the code segment and then fetching it 
 even though the values of the elements ought to be known at 
 compile-time. I’m not sure why. The actual code, x86-64 in this case, 
 consists of a load of fetches from the code segment into successive 
 registers before the start of the loop, and the loop then consists of a 
 load of instructions like cmp [r8+4*rax], r9, where r9, r10 etc we’re 
 loaded up from the fetches from [rip+disp] before th4 loop, a minor 
 strength reduction compared to a compare-immediate, as it has plenty of 
 registers free. The mystery is why the fetches from [rip+disp] even 
 exist, given that they are known values.
You can force constant folding in the frontend like this: enum uint[3] a = arr[0..3]; if(a[0]== p[0] && a[1] == p[1] && a[2] == p[2])
Jun 28 2023
prev sibling parent reply Iain Buclaw <ibuclaw gdcproject.org> writes:
On Wednesday, 28 June 2023 at 17:27:37 UTC, Cecil Ward wrote:
 GDC is generating a structure in the code segment and then 
 fetching it even though the values of the elements ought to be 
 known at compile-time. I’m not sure why. The actual code, 
 x86-64 in this case, consists of a load of fetches from the 
 code segment into successive registers before the start of the 
 loop, and the loop then consists of a load of instructions like 
 cmp [r8+4*rax], r9, where r9, r10 etc we’re loaded up from the 
 fetches from [rip+disp] before th4 loop, a minor strength 
 reduction compared to a compare-immediate, as it has plenty of 
 registers free. The mystery is why the fetches from [rip+disp] 
 even exist, given that they are known values.
Right, `immutable` (as well as `const`) has rather wobbly meanings, because you can have immutable data/fields that are initialized by a constructor - so in the worst case it can't be rodata at all. For example: ``` immutable uint[] arr; shared static this() { arr = [1,2,3]; } ``` Here, we can't possibly know what the length of arr will end up being at run-time. Based on the current wording of [the spec](https://dlang.org/spec/const3.html#const_and_immutable), 2. `immutable` applies to data that cannot change. Immutable data values, once constructed, remain the same for the duration of the program's execution. 3. `const` applies to data that cannot be changed by the const reference to that data. It may, however, be changed by another reference to that same data. I guess there's scope for applying read-only semantics to both const and immutable locals/parameters. For static data, only immutables that aren't set in a ctor can be read-only.
Jul 01 2023
next sibling parent Iain Buclaw <ibuclaw gdcproject.org> writes:
On Saturday, 1 July 2023 at 20:52:14 UTC, Iain Buclaw wrote:
 I guess there's scope for applying read-only semantics to both 
 const and immutable locals/parameters.  For static data, only 
 immutables that aren't set in a ctor can be read-only.
Let's see how well [this](https://github.com/gcc-mirror/gcc/commit/61b1c562f8c703bff045e 1257120e42b7fae523) goes...
Jul 02 2023
prev sibling parent Cecil Ward <cecil cecilward.com> writes:
On Saturday, 1 July 2023 at 20:52:14 UTC, Iain Buclaw wrote:
 On Wednesday, 28 June 2023 at 17:27:37 UTC, Cecil Ward wrote:
 GDC is generating a structure in the code segment and then 
 fetching it even though the values of the elements ought to be 
 known at compile-time. I’m not sure why. The actual code, 
 x86-64 in this case, consists of a load of fetches from the 
 code segment into successive registers before the start of the 
 loop, and the loop then consists of a load of instructions 
 like cmp [r8+4*rax], r9, where r9, r10 etc we’re loaded up 
 from the fetches from [rip+disp] before th4 loop, a minor 
 strength reduction compared to a compare-immediate, as it has 
 plenty of registers free. The mystery is why the fetches from 
 [rip+disp] even exist, given that they are known values.
Right, `immutable` (as well as `const`) has rather wobbly meanings, because you can have immutable data/fields that are initialized by a constructor - so in the worst case it can't be rodata at all. For example: ``` immutable uint[] arr; shared static this() {
Thanks for that Iain, I didn’t know that but I suspected as much. It would be good if immutables could be just turned into immediate values where individual elements are known. It would also be good if larger immutables could be placed in real ROM or else in a readonly no-execute data segment, where the system architecture permits.
Jul 02 2023