I was looking for the source for glibc's rand() function, which an answer here links to.
Following the link, I'm puzzled about the code for the __random_r() TYPE_0 branch:
int32_t val = state; val = ((state * 1103515245) + 12345) & 0x7fffffff; state = val; *result = val;
What is the point of the
val variable, getting assigned and then immediately overwritten? The
random_data struct that holds state is nothing unusual.
As one would expect, compiling with
-O2 on godbolt gives the same code if you just eliminate
val. Is there a known reason for this pattern?
UPDATE: This seems it was an aberration in the version linked to from that answer, I've updated the links there to the 2.28 version. It might have been something that was done temporarily to aid in debugging by making the contents of
state easier to see in a local watchlist?
Wow, that is indeed some unbelievable garbage code.
There is no justification for this.
And not only is initialization of
val not needed, the fact is that
state is an
int32_t, and multiplication by
1103515245 will trigger undefined behaviour in GCC (integer overflow) on any platform with 32-bit
ints (= basically every one). And GCC is the compiler most often used to compile Glibc.
As noted by HostileFork, the code in more recent 2.28 reads:
int32_t val = ((state * 1103515245U) + 12345U) & 0x7fffffff; state = val; *result = val;
With this, not only is the useless initialization removed, but the
U suffix makes the multiplication happen with unsigned integers, avoiding undefined behaviour. The
& 0x7fffffff ensures that the resulting value fits into an
int32_t and is positive.
User contributions licensed under CC BY-SA 3.0