https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91287
--- Comment #22 from Xiong Hu XS Luo <luoxhu at cn dot ibm.com> --- (In reply to Xiong Hu XS Luo from comment #21) > (In reply to H.J. Lu from comment #19) > > (In reply to Richard Biener from comment #17) > > > (In reply to Richard Biener from comment #16) > > > > (In reply to Richard Biener from comment #15) > > > > > Honza probably knows where we output the LTO symtab and why we do not > > > > > put > > > > > undefs for builtins there. > > > > > > > > #include <math.h> > > > > double y, z; > > > > void foo (); > > > > int main() > > > > { > > > > volatile double x = atan2 (y, z); > > > > foo (); > > > > } > > > > > > > > > gcc-8 -c t.c -flto > > > > > gcc-nm t.o > > > > U foo > > > > 00000000 T main > > > > 00000000 C y > > > > 00000000 C z > > > > > > > > where's the > > > > > > > > U atan2 > > > > > > > > ? > > > > > > For > > > > > > double atan2 (double x, double y) { return x + y; } > > > > > > it doesn't appear either, this CU has an empty symbol table... > > > > > > I do remember quite some "funs" with builtin handling though, so the > > > current handling may be the least bad of all choices... > > > > [hjl@gnu-cfl-1 pr91287]$ cat foo1.c > > #include <stdlib.h> > > > > float > > atan2f (float x, float y) > > { > > abort (); > > return x * y; > > } > > [hjl@gnu-cfl-1 pr91287]$ cat foo.c > > float > > atan2f (float x, float y) > > { > > return x * y; > > } > > [hjl@gnu-cfl-1 pr91287]$ cat bar.c > > #include <math.h> > > > > extern float x, y, z; > > > > void > > bar (void) > > { > > x = atan2f (y, z); > > } > > [hjl@gnu-cfl-1 pr91287]$ cat main.c > > #include <math.h> > > > > extern void bar (void); > > > > float x, y = 1, z =1; > > > > int > > main (void) > > { > > x = atan2f (y, z); > > bar (); > > return 0; > > } > > [hjl@gnu-cfl-1 pr91287]$ make > > cc -O3 -c -o foo.o foo.c > > ar rc libfoo.a foo.o > > cc -O3 -fpic -c -o bar.o bar.c > > cc -O3 -fpic -c -o foo1.o foo1.c > > ld -shared -o libfoo1.so foo1.o # --version-script foo1.v > > ld -shared -o libbar.so bar.o libfoo1.so > > cc -flto -O3 -o x main.c libfoo.a libbar.so libfoo1.so -Wl,-R,. > > cc -O3 -o y main.c libfoo.a libbar.so libfoo1.so -Wl,-R,. > > ./y > > ./x > > make: *** [Makefile:9: all] Aborted > > [hjl@gnu-cfl-1 pr91287]$ > > > > Since atan2f isn't referenced in IR, linker doesn't extract atan2f from > > libfoo.a. atan2f is resolved to definition in libfoo1.so later. > Thanks for your test case. > If remove the libfoo1.so when build x, it will link libfoo.a. And run x will > not abort. > > luoxhu@genoa pr91287 $ ~/local/gcc_t/bin/gcc -flto -O3 -o x main.c libfoo.a > libbar.so -Wl,-R,. > luoxhu@genoa pr91287 $ ./x > > Since x can link the libfoo.a if libfoo1.so not exists, not quite understand > why "atan2f isn't referenced in IR"? > > Acutually my test case shows that binary built with LTO can link libmass.a > first when use gcc, but failed to link libmass.a if use gfortran(link > libm.so finally). > > PS: My test case (gcc LTO link libmass.a first) doesn't match with your case > result(gcc LTO link libfoo1.so instead of libfoo.a). BTW, the link sequence is quite important, switch libbar.so and libfoo.a, then x will link atan2 in libfoo.a instead of libfoo1.so, which matches my test case: ~/local/gcc_t/bin/gcc -flto -O3 -o x main.c libbar.so libfoo.a libfoo1.so -Wl,-R,.