digitalmars.D - Immutables converted to immediates
- Cecil Ward (23/23) Jun 28 2023 This is a question about either the front end or back end of GDC
- Cecil Ward (7/30) Jun 28 2023 What it’s for: I have a tight loop to skip to the end of the
- Timon Gehr (4/29) Jun 28 2023 You can force constant folding in the frontend like this:
- Iain Buclaw (26/37) Jul 01 2023 Right, `immutable` (as well as `const`) has rather wobbly
- Iain Buclaw (3/6) Jul 02 2023 Let's see how well
- Cecil Ward (7/28) Jul 02 2023 Thanks for that Iain, I didn’t know that but I suspected as much.
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
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
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
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
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
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: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.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() {
Jul 02 2023