Nim
Nim copied to clipboard
Dereferencing result of `cast` in single expression triggers unnecessary copy
Description
let a = new array[1000, byte]
block:
for _ in cast[typeof(a)](a)[]:
discard
block:
let x = cast[typeof(a)](a) # not even var
for _ in x[]:
discard
Here, the first block/for loop triggers a whole-array copy:
typedef NU8 tyArray__29bRqg639bXs9cqGw2sQY470Q[1000];
...
{{tyArray__29bRqg639bXs9cqGw2sQY470Q colontmp_;
NI i;
nimZeroMem((void *)colontmp_, sizeof(tyArray__29bRqg639bXs9cqGw2sQY470Q));
nimCopyMem((void *)colontmp_, (NIM_CONST void *)((NU8 *)(a__k_u54)),
sizeof(tyArray__29bRqg639bXs9cqGw2sQY470Q));
i = ((NI)0);
{
while (1) {
___k_u99 = colontmp_[(i)-0];
{
if (!(((NI)999) <= i))
goto LA7_;
goto LA3;
}
LA7_:;
i += ((NI)1);
}
}
LA3:;
}
}
i.e. the for loop constructs the colontmp_ variable as the object to loop over, given:
for _ in cast[typeof(a)](a)[]:
discard
By contrast, splitting that apart a bit:
let x = cast[typeof(a)](a) # not even var
for _ in x[]:
discard
results in:
{
NU8 *colontmpD_;
colontmpD_ = NIM_NIL;
colontmpD_ = eqdup___k_u19(((NU8 *)(a__k_u54)));
x__k_u100 = colontmpD_;
{
NI i_2;
i_2 = ((NI)0);
{
while (1) {
___k_u105 = x__k_u100[(i_2)-0];
{
if (!(((NI)999) <= i_2))
goto LA16_;
goto LA12;
}
LA16_:;
i_2 += ((NI)1);
}
}
LA12:;
}
{
LA10_:;
}
{ eqdestroy___k_u13(x__k_u100); }
if (NIM_UNLIKELY(*nimErr_))
goto BeforeRet_;
}
Which does not have any copies. This is with --mm:orc; --mm:refc has a similar pattern but with, refc details, where for _ in cast[typeof(a)](a)[]: triggers a copy and let x = cast[typeof(a)](a) / for _ in x[]: doesn't.
Nim Version
Nim Compiler Version 2.0.9 [Linux: amd64]
Compiled at 2024-09-10
Copyright (c) 2006-2023 by Andreas Rumpf
git hash: 8d254a5945c5cb7612dff2a53be8f8d12b846d60
active boot switches: -d:release
Nim Compiler Version 2.1.99 [Linux: amd64]
Compiled at 2024-09-10
Copyright (c) 2006-2024 by Andreas Rumpf
git hash: 21771765a2c1f1fc86d87ad6e032d4050d8a651b
active boot switches: -d:release
Current Output
Extra copies-on-dereference
Expected Output
Dereference operator never copies
Known Workarounds
No response
Additional Information
No response