This is GCC Bugzilla
This is GCC Bugzilla Version 2.20+
View Bug Activity | Format For Printing | Clone This Bug
Please be kind, this is my first ever gcc bug report... :-/ I built gcc-3.4.0 crossed for arm-linux with softfloat support, according to the configurations of crosstool-0.28-rc28, which means: Reading specs from /usr/local/arm/3.4.0/lib/gcc/arm-linux/3.4.0/specs Configured with: ../gcc-3.4.0/configure --target=arm-linux --host=i686-linux -- prefix=/usr/local/arm/3.4.0 --with-local-prefix=/usr/local/arm/3.4.0/arm- linux --with-headers=/usr/local/arm/3.4.0/arm-linux/include --disable-nls -- enable-languages=c,c++ --enable-shared --with-cpu=xscale --with-tune=xscale -- enable-multilib --without-fp --with-float=soft --enable-long-long --enable- c99 --enable-threads=posix --enable-__cxa_atexit --enable-symvers=gnu --enable- clocale=gnu Thread model: posix gcc version 3.4.0 I'm attempting to build the compaq/OHH bootloader, and it is failing because of the following believed-erroneous situation: In this example program, __start is any externally defined symbol, of at least void* or int type (those are the ones I tried). If its address is taken directly in a comparison against zero, the compiler skips the load and compare altogether and emits the non-zero case. With -O0, I can force this to work "right" by loading the address into a local var. But with any optimizations, that gets turned into the first form and "optimized" away. This worked correctly on 2.95.4. Example program: // // Compile with: /usr/local/arm/3.4.0/bin/arm-linux-gcc -O0 -fPIC -g -fverbose- asm -dp -Wa,-ahlms=a.cod -o a.o a.c // extern void* __start; int fake_main(int x, int y) { int a; if ((&__start) == 0) // This comparison is not done at all a = 1; else a = 2; // This store is emitted directly { void** p = &__start; // Force address load if (p == 0) // Correct code (but only on -O0) a = 3; else a = 4; } return a; } The debugging options "-g -fverbose-asm -dp -Wa,ahlms=a.cod" of course don't affect the problem. The -fPIC option does not affect the problem (but it's the way my code must be compiled). Head of assembly output showing full option set: 2 @ GNU C version 3.4.0 (arm-linux) 3 @ compiled by GNU C version 3.3.2 20031022 (Red Hat Linux 3.3.2-1). 4 @ GGC heuristics: --param ggc-min-expand=47 --param ggc-min-heapsize=31938 5 @ options passed: -D__ARM_ARCH_5TE__ -D__XSCALE__ - D__PIC__ -D__pic__ 6 @ -mcpu=xscale -msoft-float -auxbase-strip -g -O0 - fPIC -fverbose-asm 7 @ options enabled: -feliminate-unused-debug-types - fpeephole 8 @ -ffunction-cse -fkeep-static-consts -freg-struct- return -fgcse-lm 9 @ -fgcse-sm -fgcse-las -fsched-interblock -fsched-spec 10 @ -fsched-stalled-insns -fsched-stalled-insns-dep - fbranch-count-reg -fPIC 11 @ -fcommon -fverbose-asm -fargument-alias -fzero- initialized-in-bss -fident 12 @ -fmath-errno -ftrapping-math -mapcs-32 -malignment- traps -msoft-float 13 @ -mcpu=xscale Partial annotated assembler output showing instructions generated: 5:a.c **** int a; 6:a.c **** 7:a.c **** if ((&__start) == 0) // This comparison is not done at all 8:a.c **** a = 1; 9:a.c **** else 10:a.c **** a = 2; // This store is emitted directly 45 .loc 1 10 0 46 0020 0230A0E3 mov r3, #2 @ tmp70, @ 20 *arm_movsi_insn/1 [length = 4] 47 0024 1C300BE5 str r3, [fp, #-28] @ tmp70, a @ 21 *arm_movsi_insn/4 [length = 4] 48 .LBB2: 11:a.c **** 12:a.c **** { 13:a.c **** void** p = &__start; // Force address load 49 .loc 1 13 0
What's wrong with gcc's behavior? You use an extern symbol, so not defining it at all would yield a linker error. But if you define it, the symbol has an address, and that address must be non-zero, a fact that gcc can use when it eliminated if-then clauses because it already knows the value of the if-expression. This is a duplicate of a good number of other PRs. W.
Subject: Re: compare on address of global variable always evals to non-zero Well, that all depends on which symbol. In this particular case, the symbol is _start, as defined by an assembly stub that gets linked in -- this is a bootloader, and it loads out of flash, so the symbols address is indeed zero in most cases. ----- Original Message ----- From: "bangerth at dealii dot org" <gcc-bugzilla@gcc.gnu.org> To: <paul_r_nash@hotmail.com> Sent: Wednesday, July 14, 2004 4:49 PM Subject: [Bug c/16554] compare on address of global variable always evals to non-zero > > ------- Additional Comments From bangerth at dealii dot org 2004-07-14 23:49 ------- > What's wrong with gcc's behavior? You use an extern symbol, so not > defining it at all would yield a linker error. But if you define it, > the symbol has an address, and that address must be non-zero, a fact > that gcc can use when it eliminated if-then clauses because it already > knows the value of the if-expression. > > This is a duplicate of a good number of other PRs. > > W. > > -- > What |Removed |Added > -------------------------------------------------------------------------- -- > Status|UNCONFIRMED |RESOLVED > Resolution| |INVALID > > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=16554 > > ------- You are receiving this mail because: ------- > You reported the bug, or are watching the reporter. >
You want to mark the global variable as weak to change how gcc gets rid of the if.
Ah -- magic. That works out right. Thanks!