This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug lto/77669] Incorrect LTO code on embedded ARM
- From: "wgh at beyondunreal dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Tue, 20 Sep 2016 23:11:32 +0000
- Subject: [Bug lto/77669] Incorrect LTO code on embedded ARM
- Auto-submitted: auto-generated
- References: <bug-77669-4@http.gcc.gnu.org/bugzilla/>
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77669
--- Comment #1 from wgh at beyondunreal dot com ---
The loop in question looks like this, in C++ and aseembly:
if (__urngrange > __urange)
{
// downscaling
const __uctype __uerange = __urange + 1; // __urange can be zero
const __uctype __scaling = __urngrange / __uerange;
const __uctype __past = __uerange * __scaling;
do
__ret = __uctype(__urng()) - __urngmin;
while (__ret >= __past);
__ret /= __scaling;
}
080001d6
<_ZNSt24uniform_int_distributionIiEclISt26linear_congruential_engineIjLj48271ELj0ELj2147483647EEEEiRT_RKNS0_10param_typeE.constprop.6>:
...
...
80001f4: f7ff ffda bl 80001ac
<_ZNSt8__detail4_ModIjLj2147483647ELj48271ELj0ELb0ELb1EE6__calcEj>
80001f8: 1e43 subs r3, r0, #1
80001fa: 429c cmp r4, r3
80001fc: d9fa bls.n 80001f4
<_ZNSt24uniform_int_distributionIiEclISt26linear_congruential_engineIjLj48271ELj0ELj2147483647EEEEiRT_RKNS0_10param_typeE.constprop.6+0x1e>
So LCG has been greatly optimized and has become a single __calc call.
gdb shows some extra "fake" frames, even though they have been optimized out.
#0 __calc (__x=0) at
/usr/lib/gcc/armv7m-hardfloat-eabi/5.4.0/include/g++-v5/bits/random.tcc:62
#1 0x080001f8 in std::__detail::__mod<unsigned int, 2147483647u, 48271u,
0u>(unsigned int) ()
at
/usr/lib/gcc/armv7m-hardfloat-eabi/5.4.0/include/g++-v5/bits/random.h:151
#2 operator() (this=0x20000430 <random_engine>) at
/usr/lib/gcc/armv7m-hardfloat-eabi/5.4.0/include/g++-v5/bits/random.h:332
#3 operator() (this=this@entry=0x2001ffd0, __param=..., __urng=...)
at
/usr/lib/gcc/armv7m-hardfloat-eabi/5.4.0/include/g++-v5/bits/uniform_int_dist.h:242
#4 0x080002be in operator() (__urng=..., this=0x2001ffd0) at
/usr/lib/gcc/armv7m-hardfloat-eabi/5.4.0/include/g++-v5/bits/uniform_int_dist.h:16
The __calc function looks like this in assembly:
080001ac <_ZNSt8__detail4_ModIjLj2147483647ELj48271ELj0ELb0ELb1EE6__calcEj>:
80001ac: f64a 52c8 movw r2, #44488 ; 0xadc8
80001b0: fbb0 f1f2 udiv r1, r0, r2
80001b4: fb02 0311 mls r3, r2, r1, r0
80001b8: f64b 428f movw r2, #48271 ; 0xbc8f
80001bc: 4353 muls r3, r2
80001be: f640 5247 movw r2, #3399 ; 0xd47
80001c2: fb02 f001 mul.w r0, r2, r1
80001c6: 4283 cmp r3, r0
80001c8: bf3c itt cc
80001ca: f103 4300 addcc.w r3, r3, #2147483648 ; 0x80000000
80001ce: f103 33ff addcc.w r3, r3, #4294967295 ; 0xffffffff
80001d2: 1a18 subs r0, r3, r0
80001d4: 4770 bx lr
It should calculate x = (ax + c) mod m, where a = 48271u, c = 0u, m =
2147483647u
So in case of x=0, new x will also be zero. Hmm, sounds weird.