Thanks Maxim,
Yes I should do that. I also intend to make the code used to reproduce the problem smaller.
One of my worries was that GCC considered the loop without side effects (ignoring the inline assembler in odp_spin()) and thus removed the loop (including the usage of the uninitialized variable). But that does not seem to be the case.
-- Ola
On 27 November 2014 at 08:58, Maxim Kuvyrkov maxim.kuvyrkov@linaro.org wrote:
Hi Ola,
I can confirm this problem with latest linaro-4.9-branch build. However, this is target-independent problem (reproducible on, at least, x86 and aarch64), so it is best to be tracked and addressed via upstream bugzilla.
Would you submit a PR on http://gcc.gnu.org/bugzilla ?
Thank you,
-- Maxim Kuvyrkov www.linaro.org
On Nov 25, 2014, at 1:34 AM, Pinski, Andrew Andrew.Pinski@caviumnetworks.com wrote:
Forwarding this message to the linaro toolchain list instead. I am not the person who should be supporting the Linaro ODP project with GCC questiosn; the toolchain team inside Linaro should be instead.
Thanks, Andrew Pinski
From: Ola Liljedahl ola.liljedahl@linaro.org Sent: Monday, November 24, 2014 2:31 PM To: lng-odp@lists.linaro.org; Pinski, Andrew Subject: strange behavior in GCC for use of uninitialized variables
Consider the following code fragment (from real life):
#include <stdint.h>
typedef volatile uint32_t odp_atomic_u32_t;
static inline uint32_t odp_atomic_fetch_inc_u32(odp_atomic_u32_t *ptr) { return __sync_fetch_and_add(ptr, 1); }
static inline void odp_spin(void) { #ifdef __SSE2__ __asm__ __volatile__ ("pause"); #else __asm__ __volatile__ ("rep; nop"); #endif }
typedef struct { int count; odp_atomic_u32_t bar; } odp_barrier_t;
void odp_barrier_wait(odp_barrier_t *barrier) { uint32_t count; int wasless;
// wasless = barrier->bar < barrier->count; <<<lost on git add -p __atomic_thread_fence(__ATOMIC_SEQ_CST); count = odp_atomic_fetch_inc_u32(&barrier->bar);
if (count == 2*barrier->count-1) { barrier->bar = 0; } else { while ((barrier->bar < barrier->count) == wasless) odp_spin(); } __atomic_thread_fence(__ATOMIC_SEQ_CST);
}
While fixing and cleaning up this code, the indicated line that initializes 'wasless' was dropped (because it reappears in a later patch in the patch set after the odp_atomic_fetch_inc call). To my surprise, GCC did not complain when compiling this file (using -O2 -Wall). But it does complain when compiling with -O0 -Wall. With some investigation, it seems like GCC understands that if a statement does not have any side effects so it can optimize away everything, including the usage of the uninitialized variable and thus also the corresponding warning.
olli@macmini:~/hacking/gcc-wunit$ gcc -O2 -Wall -c odp_barrier.c olli@macmini:~/hacking/gcc-wunit$ gcc -O0 -Wall -c odp_barrier.c odp_barrier.c: In function ‘odp_barrier_wait’: odp_barrier.c:42:9: warning: ‘wasless’ may be used uninitialized in this function [-Wmaybe-uninitialized] while ((barrier->bar < barrier->count) == was less)